From 88510a61cd0b14158c9dde66c84d1217d7601960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=81Z=C3=81R=20Imre=20AI=20Agent?= Date: Thu, 16 Jul 2026 11:30:02 +0200 Subject: [PATCH] feat(pkg): add RemoteImage 2.0.10 (vetted live, stock) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RemoteImage 2.0.10 (github.com/asikart/remoteimage @2.0.10), vetted clean, stock; live deployed files (upstream ships build-layout — deployed bytes used for verification). Signed-off-by: LÁZÁR Imre Assisted-by: claude-code@claude-opus-4-8 --- .../components/com_remoteimage/access.xml | 13 + .../com_remoteimage/asset/css/index.html | 1 + .../com_remoteimage/asset/css/remoteimage.css | 48 + .../com_remoteimage/asset/index.html | 1 + .../asset/js/elfinder/Changelog | 63 + .../asset/js/elfinder/README.md | 116 + .../asset/js/elfinder/css/elfinder.min.css | 9 + .../asset/js/elfinder/css/index.html | 1 + .../asset/js/elfinder/css/theme.css | 49 + .../asset/js/elfinder/css2/elfinder.full.css | 1650 +++ .../asset/js/elfinder/css2/elfinder.min.css | 9 + .../asset/js/elfinder/css2/theme.css | 50 + .../asset/js/elfinder/elfinder.html | 40 + .../asset/js/elfinder/img/arrows-active.png | Bin 0 -> 201 bytes .../asset/js/elfinder/img/arrows-normal.png | Bin 0 -> 312 bytes .../asset/js/elfinder/img/crop.gif | Bin 0 -> 329 bytes .../asset/js/elfinder/img/dialogs.png | Bin 0 -> 18556 bytes .../asset/js/elfinder/img/icons-big.png | Bin 0 -> 35425 bytes .../asset/js/elfinder/img/icons-small.png | Bin 0 -> 7365 bytes .../asset/js/elfinder/img/logo.png | Bin 0 -> 14681 bytes .../asset/js/elfinder/img/progress.gif | Bin 0 -> 1727 bytes .../asset/js/elfinder/img/quicklook-bg.png | Bin 0 -> 78 bytes .../asset/js/elfinder/img/quicklook-icons.png | Bin 0 -> 2647 bytes .../asset/js/elfinder/img/resize.png | Bin 0 -> 101 bytes .../asset/js/elfinder/img/spinner-mini.gif | Bin 0 -> 1849 bytes .../asset/js/elfinder/img/toolbar.png | Bin 0 -> 18217 bytes .../js/elfinder/img/volume_icon_dropbox.png | Bin 0 -> 902 bytes .../asset/js/elfinder/img/volume_icon_ftp.png | Bin 0 -> 526 bytes .../js/elfinder/img/volume_icon_local.png | Bin 0 -> 434 bytes .../asset/js/elfinder/img/volume_icon_sql.png | Bin 0 -> 748 bytes .../asset/js/elfinder/js/elfinder.full.js | 12253 ++++++++++++++++ .../asset/js/elfinder/js/elfinder.min.js | 14 + .../js/elfinder/js/i18n/elfinder.LANG.js | 355 + .../asset/js/elfinder/js/i18n/elfinder.ar.js | 290 + .../asset/js/elfinder/js/i18n/elfinder.bg.js | 310 + .../asset/js/elfinder/js/i18n/elfinder.ca.js | 310 + .../asset/js/elfinder/js/i18n/elfinder.cs.js | 340 + .../asset/js/elfinder/js/i18n/elfinder.da.js | 354 + .../asset/js/elfinder/js/i18n/elfinder.de.js | 335 + .../asset/js/elfinder/js/i18n/elfinder.el.js | 355 + .../asset/js/elfinder/js/i18n/elfinder.es.js | 307 + .../asset/js/elfinder/js/i18n/elfinder.fa.js | 339 + .../asset/js/elfinder/js/i18n/elfinder.fr.js | 338 + .../asset/js/elfinder/js/i18n/elfinder.hu.js | 280 + .../asset/js/elfinder/js/i18n/elfinder.it.js | 340 + .../asset/js/elfinder/js/i18n/elfinder.jp.js | 353 + .../asset/js/elfinder/js/i18n/elfinder.ko.js | 340 + .../asset/js/elfinder/js/i18n/elfinder.nl.js | 361 + .../asset/js/elfinder/js/i18n/elfinder.no.js | 280 + .../asset/js/elfinder/js/i18n/elfinder.pl.js | 343 + .../js/elfinder/js/i18n/elfinder.pt_BR.js | 331 + .../asset/js/elfinder/js/i18n/elfinder.ru.js | 362 + .../asset/js/elfinder/js/i18n/elfinder.sk.js | 348 + .../asset/js/elfinder/js/i18n/elfinder.sl.js | 340 + .../asset/js/elfinder/js/i18n/elfinder.sv.js | 353 + .../asset/js/elfinder/js/i18n/elfinder.tr.js | 340 + .../asset/js/elfinder/js/i18n/elfinder.vi.js | 340 + .../js/elfinder/js/i18n/elfinder.zh_CN.js | 354 + .../js/elfinder/js/i18n/elfinder.zh_TW.js | 353 + .../elfinder/js/proxy/elFinderSupportVer1.js | 338 + .../com_remoteimage/asset/js/index.html | 1 + .../asset/js/jquery-ui/css/index.html | 1 + .../css/smoothness/images/index.html | 1 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../js/jquery-ui/css/smoothness/index.html | 1 + .../smoothness/jquery-ui-1.8.24.custom.css | 563 + .../asset/js/jquery-ui/index.html | 1 + .../asset/js/jquery-ui/js/index.html | 1 + .../asset/js/jquery-ui/js/jquery-1.7.2.min.js | 4 + .../js/jquery-ui-1.8.24.custom.min.js | 125 + .../asset/js/jquery/index.html | 1 + .../com_remoteimage/asset/js/jquery/jquery.js | 4 + .../com_remoteimage/asset/js/main.js | 8 + .../asset/js/remoteimage-admin.js | 124 + .../components/com_remoteimage/component.php | 37 + .../components/com_remoteimage/composer.json | 9 + .../components/com_remoteimage/config.xml | 275 + .../com_remoteimage/etc/config.dist.yml | 3 + .../com_remoteimage/etc/config.json | 6 + .../components/com_remoteimage/etc/index.html | 1 + .../com_remoteimage/helper/helper.php | 86 + .../com_remoteimage/helper/index.html | 1 + .../images/com_remoteimage_logo.png | Bin 0 -> 17787 bytes .../com_remoteimage/images/index.html | 1 + .../components/com_remoteimage/index.html | 1 + .../components/com_remoteimage/install.php | 108 + .../de-DE/de-DE.com_remoteimage.core.ini | 64 + .../language/de-DE/de-DE.com_remoteimage.ini | 78 + .../de-DE/de-DE.com_remoteimage.sys.ini | 10 + .../com_remoteimage/language/de-DE/index.html | 1 + .../language/en-GB/en-GB.com_remoteimage.ini | 93 + .../en-GB/en-GB.com_remoteimage.sys.ini | 10 + .../com_remoteimage/language/en-GB/index.html | 1 + .../language/fr-FR/fr-FR.com_remoteimage.ini | 90 + .../fr-FR/fr-FR.com_remoteimage.sys.ini | 10 + .../com_remoteimage/language/index.html | 1 + .../com_remoteimage/language/zh-TW/index.html | 1 + .../language/zh-TW/zh-TW.com_remoteimage.ini | 92 + .../zh-TW/zh-TW.com_remoteimage.sys.ini | 11 + .../com_remoteimage/remoteimage.php | 14 + .../com_remoteimage/remoteimage.xml | 62 + .../src/Elfinder/MySQLStorage.sql | 23 + .../src/Elfinder/connector.minimal.php | 61 + .../src/Elfinder/connector.php | 61 + .../src/Elfinder/elFinder.class.php | 1971 +++ .../src/Elfinder/elFinderConnector.class.php | 163 + .../Elfinder/elFinderVolumeDriver.class.php | 3741 +++++ .../Elfinder/elFinderVolumeDropbox.class.php | 1531 ++ .../src/Elfinder/elFinderVolumeFTP.class.php | 1430 ++ .../Elfinder/elFinderVolumeFTPIIS.class.php | 134 + .../elFinderVolumeLocalFileSystem.class.php | 763 + .../Elfinder/elFinderVolumeMySQL.class.php | 961 ++ .../src/Elfinder/elFinderVolumeS3.class.php | 732 + .../com_remoteimage/src/Elfinder/mime.types | 512 + .../Elfinder/plugins/AutoResize/plugin.php | 157 + .../Elfinder/plugins/Normalizer/plugin.php | 121 + .../src/Elfinder/plugins/Sanitizer/plugin.php | 100 + .../src/Elfinder/plugins/Watermark/logo.png | Bin 0 -> 12806 bytes .../src/Elfinder/plugins/Watermark/plugin.php | 243 + .../Component/RemoteimageComponent.php | 80 + .../src/Remoteimage/Component/TaskMapper.php | 31 + .../src/Remoteimage/Component/index.html | 1 + .../src/Remoteimage/Config/Config.php | 41 + .../src/Remoteimage/Config/index.html | 1 + .../Controller/ManagerController.php | 161 + .../Listener/Lite/LiteListener.php | 370 + .../src/Remoteimage/Listener/Lite/index.html | 1 + .../Remoteimage/Listener/Pro/ProListener.php | 407 + .../src/Remoteimage/Listener/Pro/index.html | 1 + .../src/Remoteimage/Listener/index.html | 1 + .../Provider/RemoteimageProvider.php | 34 + .../src/Remoteimage/Provider/index.html | 1 + .../src/Remoteimage/Router/Route.php | 44 + .../src/Remoteimage/Router/index.html | 1 + .../src/Remoteimage/View/ManagerView.php | 155 + .../src/Remoteimage/index.html | 1 + .../components/com_remoteimage/src/index.html | 1 + .../components/com_remoteimage/src/init.php | 17 + .../com_remoteimage/view/index.html | 1 + .../com_remoteimage/view/manager/html.php | 19 + .../com_remoteimage/view/manager/index.html | 1 + .../view/manager/tmpl/default.php | 244 + .../view/manager/tmpl/index.html | 1 + .../com_remoteimage/asset/css/index.html | 1 + .../com_remoteimage/asset/css/main.css | 33 + .../com_remoteimage/asset/index.html | 1 + .../com_remoteimage/asset/js/index.html | 1 + .../com_remoteimage/asset/js/main.js | 8 + .../components/com_remoteimage/component.php | 37 + .../com_remoteimage/images/index.html | 1 + .../components/com_remoteimage/index.html | 1 + .../com_remoteimage/remoteimage.php | 14 + .../components/com_remoteimage/router.php | 114 + .../components/com_remoteimage/routing.json | 11 + .../com_remoteimage/view/index.html | 1 + .../com_remoteimage/view/manager/html.php | 61 + .../com_remoteimage/view/manager/index.html | 1 + .../view/manager/tmpl/default.php | 9 + .../view/manager/tmpl/default.xml | 12 + .../view/manager/tmpl/index.html | 1 + .../editors-xtd/remoteimage/index.html | 1 + .../editors-xtd/remoteimage/install.php | 68 + .../de-DE.plg_editors-xtd_remoteimage.ini | 8 + .../de-DE.plg_editors-xtd_remoteimage.sys.ini | 8 + .../remoteimage/language/de-DE/index.html | 1 + .../en-GB.plg_editors-xtd_remoteimage.ini | 8 + .../en-GB.plg_editors-xtd_remoteimage.sys.ini | 8 + .../remoteimage/language/en-GB/index.html | 1 + .../remoteimage/language/index.html | 1 + .../remoteimage/language/zh-TW/index.html | 1 + .../zh-TW.plg_editors-xtd_remoteimage.ini | 8 + .../zh-TW.plg_editors-xtd_remoteimage.sys.ini | 8 + .../editors-xtd/remoteimage/lib/index.html | 1 + .../editors-xtd/remoteimage/remoteimage.php | 112 + .../editors-xtd/remoteimage/remoteimage.xml | 43 + .../plugins/system/remoteimage/index.html | 1 + .../plugins/system/remoteimage/install.php | 68 + .../de-DE/de-DE.plg_system_remoteimage.ini | 8 + .../de-DE.plg_system_remoteimage.sys.ini | 8 + .../remoteimage/language/de-DE/index.html | 1 + .../en-GB/en-GB.plg_system_remoteimage.ini | 8 + .../en-GB.plg_system_remoteimage.sys.ini | 8 + .../remoteimage/language/en-GB/index.html | 1 + .../system/remoteimage/language/index.html | 1 + .../remoteimage/language/zh-TW/index.html | 1 + .../zh-TW/zh-TW.plg_system_remoteimage.ini | 8 + .../zh-TW.plg_system_remoteimage.sys.ini | 8 + .../plugins/system/remoteimage/lib/index.html | 1 + .../system/remoteimage/remoteimage.php | 139 + .../system/remoteimage/remoteimage.xml | 48 + 202 files changed, 40819 insertions(+) create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/access.xml create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/css/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/css/remoteimage.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/Changelog create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/README.md create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/elfinder.min.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/theme.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.full.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.min.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/theme.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/elfinder.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/arrows-active.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/arrows-normal.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/crop.gif create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/dialogs.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/icons-big.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/icons-small.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/logo.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/progress.gif create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/quicklook-bg.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/quicklook-icons.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/resize.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/spinner-mini.gif create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/toolbar.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_dropbox.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_ftp.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_local.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_sql.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/elfinder.full.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/elfinder.min.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.LANG.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.ar.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.bg.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.ca.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.cs.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.da.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.de.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.el.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.es.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.fa.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.fr.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.hu.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.it.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.jp.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.ko.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.nl.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.no.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.pl.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.pt_BR.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.ru.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.sk.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.sl.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.sv.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.tr.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.vi.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.zh_CN.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/i18n/elfinder.zh_TW.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/js/proxy/elFinderSupportVer1.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-icons_222222_256x240.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-icons_454545_256x240.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-icons_888888_256x240.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/css/smoothness/jquery-ui-1.8.24.custom.css create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/js/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/js/jquery-1.7.2.min.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery-ui/js/jquery-ui-1.8.24.custom.min.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/jquery.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/main.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/asset/js/remoteimage-admin.js create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/component.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/composer.json create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/config.xml create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/etc/config.dist.yml create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/etc/config.json create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/etc/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/helper/helper.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/helper/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/images/com_remoteimage_logo.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/images/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/install.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.core.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.sys.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.sys.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.sys.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.sys.ini create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/remoteimage.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/remoteimage.xml create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/MySQLStorage.sql create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.minimal.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinder.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderConnector.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDriver.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDropbox.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTP.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTPIIS.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeLocalFileSystem.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeMySQL.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeS3.class.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/mime.types create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/AutoResize/plugin.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Normalizer/plugin.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Sanitizer/plugin.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Watermark/logo.png create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Watermark/plugin.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/RemoteimageComponent.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/TaskMapper.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Config/Config.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Config/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Controller/ManagerController.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/LiteListener.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/ProListener.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Provider/RemoteimageProvider.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Provider/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Router/Route.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Router/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/View/ManagerView.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/src/init.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/view/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/view/manager/html.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/view/manager/index.html create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/default.php create mode 100644 packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/asset/css/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/asset/css/main.css create mode 100644 packages/remoteimage/components/com_remoteimage/asset/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/asset/js/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/asset/js/main.js create mode 100644 packages/remoteimage/components/com_remoteimage/component.php create mode 100644 packages/remoteimage/components/com_remoteimage/images/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/remoteimage.php create mode 100644 packages/remoteimage/components/com_remoteimage/router.php create mode 100644 packages/remoteimage/components/com_remoteimage/routing.json create mode 100644 packages/remoteimage/components/com_remoteimage/view/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/view/manager/html.php create mode 100644 packages/remoteimage/components/com_remoteimage/view/manager/index.html create mode 100644 packages/remoteimage/components/com_remoteimage/view/manager/tmpl/default.php create mode 100644 packages/remoteimage/components/com_remoteimage/view/manager/tmpl/default.xml create mode 100644 packages/remoteimage/components/com_remoteimage/view/manager/tmpl/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/install.php create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/de-DE/de-DE.plg_editors-xtd_remoteimage.ini create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/de-DE/de-DE.plg_editors-xtd_remoteimage.sys.ini create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/de-DE/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.ini create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.sys.ini create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.ini create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.sys.ini create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/lib/index.html create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.php create mode 100644 packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.xml create mode 100644 packages/remoteimage/plugins/system/remoteimage/index.html create mode 100644 packages/remoteimage/plugins/system/remoteimage/install.php create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/de-DE/de-DE.plg_system_remoteimage.ini create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/de-DE/de-DE.plg_system_remoteimage.sys.ini create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/de-DE/index.html create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.ini create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.sys.ini create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/en-GB/index.html create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/index.html create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/zh-TW/index.html create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.ini create mode 100644 packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.sys.ini create mode 100644 packages/remoteimage/plugins/system/remoteimage/lib/index.html create mode 100644 packages/remoteimage/plugins/system/remoteimage/remoteimage.php create mode 100644 packages/remoteimage/plugins/system/remoteimage/remoteimage.xml diff --git a/packages/remoteimage/administrator/components/com_remoteimage/access.xml b/packages/remoteimage/administrator/components/com_remoteimage/access.xml new file mode 100644 index 00000000..261c86e9 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/access.xml @@ -0,0 +1,13 @@ + + +
+ + + + + + + + +
+
\ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/css/index.html b/packages/remoteimage/administrator/components/com_remoteimage/asset/css/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/css/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/css/remoteimage.css b/packages/remoteimage/administrator/components/com_remoteimage/asset/css/remoteimage.css new file mode 100644 index 00000000..79101c8f --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/css/remoteimage.css @@ -0,0 +1,48 @@ +/*! + * com_remoteimage + * + * Copyright 2012 - 2014 SMS Taiwan + * License GNU General Public License version 2 or later; + */ + +/* GLOBAL */ + + +/* FINDER */ + +#remoteimage-manager .ui-state-hover, +#remoteimage-manager .ui-widget-content .ui-state-hover { + border: none; +} + +/* FORM */ +#elfinder .elfinder-dialog-resize input { + max-width: 50px; +} + +#elfinder .elfinder-dialog-resize img { + max-width: none; +} + +#remoteimage-manager .elfinder-button-search input { + padding-left: 25px; +} + +#remoteimage-manager .elfinder .ui-icon-search { + top: 40%; +} + +#remoteimage-manager .elfinder .ui-icon-close { + top: 40%; + right: 10px; +} + +/* FOOTER */ + + +/* TREE */ +#remote-folder-wrap { + height: 500px; + overflow: auto ; +} + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/index.html b/packages/remoteimage/administrator/components/com_remoteimage/asset/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/Changelog b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/Changelog new file mode 100644 index 00000000..f6749c9b --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/Changelog @@ -0,0 +1,63 @@ +2012-04-10 Troex Nevelin + + * elFinder (2.0 rc1): + - Major code refactor + - 200+ bugs fixed since beta version + - 14 new translations + - FTP volume driver + - Advanced image editing dialog + + +2011-07-10 Troex Nevelin + + * elFinder (2.0 beta): + - New branch 2.x, total rewrite from scratch + - MySQL volume driver support (as file storage) + - Full drag & drop support with HTML5 upload + + +2011-06-20 Troex Nevelin + + * elFinder (1.2): + - jQuery and UI updated + - Python connector improvements + - QuickLook fixed + - CSS fixes + - New icons from http://pixel-mixer.com/ + - New languages: Czech, Dutch, German, Greek, French, Hungarian, + Italian, Japanese, Latvian, Polish, Brazilian Portuguese, + Slovak, Thai, Turkish, Vietnamese, Simplified Chinese, + Traditional Chinese + + +2010-03-11 Troex Nevelin + + * elFinder (1.1): + - Total rewrite from scratch. + - New PHP connector. + - Python connector. + - Create/Extract archives. + - QuickLook. + - "Places" for favorites. + - Background thumbnails creation. + - Exteneded configuration options of connector and client. + - Spanish localization. + - JSON API description. + - Full documentation in English, Russian and Spanish. + - No more use of jquery plugins. + - Website update. + - [bugfix] All known bugs fixed. + + +2009-11-09 Dmitry Levashov + + * elFinder (1.0.1): + - In directory tree panel added arrows to open/close directories + without entering in. + - Added shortcut support for copy/cut/paste/delete files and + folders. For Mac users added Command+Backspace support. + - Added context menu to current directory. + - Added help. + - [bugfix] invalid determing files/folders permissions using + "perms" options in php connector + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/README.md b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/README.md new file mode 100644 index 00000000..aa54cff2 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/README.md @@ -0,0 +1,116 @@ +elFinder +======== + +
+      _ ______ _           _           
+     | |  ____(_)         | |          
+  ___| | |__   _ _ __   __| | ___ _ __ 
+ / _ \ |  __| | | '_ \ / _` |/ _ \ '__|
+|  __/ | |    | | | | | (_| |  __/ |   
+ \___|_|_|    |_|_| |_|\__,_|\___|_|   
+
+ +elFinder is an open-source file manager for web, written in JavaScript using +jQuery UI. Creation is inspired by simplicity and convenience of Finder program +used in Mac OS X operating system. + + +Features +-------- + + * All operations with files and folders on a remote server (copy, move, + upload, create folder/file, rename, etc.) + * High performance server beckend and light client UI + * Multi-root support + * Local file system, MySQL, FTP volume storage drivers + * Background file upload with Drag & Drop HTML5 support + * List and Icons view + * Keyboard shortcuts + * Standard methods of file/group selection using mouse or keyboard + * Move/Copy files with Drag & Drop + * Archives create/extract (zip, rar, 7z, tar, gzip, bzip2) + * Rich context menu and toolbar + * Quicklook, preview for common file types + * Edit text files and images + * "Places" for your favorites + * Calculate directory sizes + * Thumbnails for image files + * Easy to integrate with web editors (elRTE, CKEditor, TinyMCE) + * Flexible configuration of access rights, upload file types, user interface + and other + * Extensibility + * Simple client-server API based on JSON + + +Requirements +------------ + +### Client + * Modern browser. elFinder was tested in Firefox 12, Internet Explorer 8+, + Safari 6, Opera 12 and Chrome 19 + +### Server + * Any web server + * PHP 5.2+ (for thumbnails - mogrify utility or GD/Imagick module) + + +3rd party connectors +-------------------- + * [Python](https://github.com/Studio-42/elfinder-python) + * [Django](https://github.com/mikery/django-elfinder) + * [Ruby/Rails](https://github.com/phallstrom/el_finder) + * [Java Servlet](https://github.com/Studio-42/elfinder-servlet) + + +Support +------- + + * [Homepage](http://elfinder.org) + * [Wiki](https://github.com/Studio-42/elFinder/wiki) + * [Issues](https://github.com/Studio-42/elFinder/issues) + * [Forum](http://elfinder.org/forum/) + * + + +Authors +------- + + * Chief developer: Dmitry "dio" Levashov + * Maintainer: Troex Nevelin + * Developers: Alexey Sukhotin , Naoki Sawada + * Icons: [PixelMixer](http://pixelmixer.ru), [Yusuke Kamiyamane](http://p.yusukekamiyamane.com) + +We hope our tools will be helpful for you. + + +License +------- + +elFinder is issued under a 3-clauses BSD license. + +
+Copyright (c) 2009-2012, Studio 42
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Studio 42 Ltd. nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL "STUDIO 42" BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/elfinder.min.css b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/elfinder.min.css new file mode 100644 index 00000000..19e5e7c8 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/elfinder.min.css @@ -0,0 +1,9 @@ +/*! + * elFinder - file manager for web + * Version 2.0 rc1 (2012-04-10) + * http://elfinder.org + * + * Copyright 2009-2012, Studio 42 + * Licensed under a 3 clauses BSD license + */ +.elfinder-dialog-resize{margin-top:.3em}.elfinder-resize-type{float:left;margin-bottom:.4em}.elfinder-resize-control{padding-top:3em}.elfinder-resize-control input[type=text]{border:1px solid #aaa;text-align:right}.elfinder-resize-preview{width:400px;height:400px;padding:10px;background:#fff;border:1px solid #aaa;float:right;position:relative;overflow:auto}.elfinder-resize-handle{position:relative}.elfinder-resize-handle-hline,.elfinder-resize-handle-vline{position:absolute;background-image:url("../img/crop.gif")}.elfinder-resize-handle-hline{width:100%;height:1px!important;background-repeat:repeat-x}.elfinder-resize-handle-vline{width:1px!important;height:100%;background-repeat:repeat-y}.elfinder-resize-handle-hline-top{top:0;left:0}.elfinder-resize-handle-hline-bottom{bottom:0;left:0}.elfinder-resize-handle-vline-left{top:0;left:0}.elfinder-resize-handle-vline-right{top:0;right:0}.elfinder-resize-handle-point{position:absolute;width:8px;height:8px;border:1px solid #777;background:0 0}.elfinder-resize-handle-point-n{top:0;left:50%;margin-top:-5px;margin-left:-5px}.elfinder-resize-handle-point-ne{top:0;right:0;margin-top:-5px;margin-right:-5px}.elfinder-resize-handle-point-e{top:50%;right:0;margin-top:-5px;margin-right:-5px}.elfinder-resize-handle-point-se{bottom:0;right:0;margin-bottom:-5px;margin-right:-5px}.elfinder-resize-handle-point-s{bottom:0;left:50%;margin-bottom:-5px;margin-left:-5px}.elfinder-resize-handle-point-sw{bottom:0;left:0;margin-bottom:-5px;margin-left:-5px}.elfinder-resize-handle-point-w{top:50%;left:0;margin-top:-5px;margin-left:-5px}.elfinder-resize-handle-point-nw{top:0;left:0;margin-top:-5px;margin-left:-5px}.elfinder-resize-spinner{position:absolute;width:200px;height:30px;top:50%;margin-top:-25px;left:50%;margin-left:-100px;text-align:center;background:url(../img/progress.gif) center bottom repeat-x}.elfinder-resize-row{margin-bottom:7px;position:relative}.elfinder-resize-label{float:left;width:80px;padding-top:3px}.elfinder-resize-reset{width:16px;height:16px;position:absolute;margin-top:-8px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-e{height:100%;width:10px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-s{width:100%;height:10px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-se{background:0 0;bottom:0;right:0;margin-right:-7px;margin-bottom:-7px}.elfinder-dialog-resize .ui-icon-grip-solid-vertical{position:absolute;top:50%;right:0;margin-top:-8px;margin-right:-11px}.elfinder-dialog-resize .ui-icon-grip-solid-horizontal{position:absolute;left:50%;bottom:0;margin-left:-8px;margin-bottom:-11px}.elfinder-resize-row .elfinder-buttonset{float:right}.elfinder-resize-rotate-slider{float:left;width:195px;margin:7px 7px 0}.elfinder-file-edit{width:99%;height:99%;margin:0;padding:2px;border:1px solid #ccc}.elfinder-help{margin-bottom:.5em}.elfinder-help .ui-tabs-panel{padding:.5em}.elfinder-dialog .ui-tabs .ui-tabs-nav li a{padding:.2em 1em}.elfinder-help-shortcuts{height:300px;padding:1em;margin:.5em 0;overflow:auto}.elfinder-help-shortcut{white-space:nowrap;clear:both}.elfinder-help-shortcut-pattern{float:left;width:160px}.elfinder-help-logo{width:100px;height:96px;float:left;margin-right:1em;background:url('../img/logo.png') center center no-repeat}.elfinder-help h3{font-size:1.5em;margin:.2em 0 .3em}.elfinder-help-separator{clear:both;padding:.5em}.elfinder-help-link{padding:2px}.elfinder-help .ui-priority-secondary{font-size:.9em}.elfinder-help .ui-priority-primary{margin-bottom:7px}.elfinder-help-team{clear:both;text-align:right;border-bottom:1px solid #ccc;margin:.5em 0;font-size:.9em}.elfinder-help-team div{float:left}.elfinder-help-license{font-size:.9em}.elfinder-help-disabled{font-weight:700;text-align:center;margin:90px 0}.elfinder-help .elfinder-dont-panic{display:block;border:1px solid transparent;width:200px;height:200px;margin:30px auto;text-decoration:none;text-align:center;position:relative;background:#d90004;-moz-box-shadow:5px 5px 9px #111;-webkit-box-shadow:5px 5px 9px #111;box-shadow:5px 5px 9px #111;background:-moz-radial-gradient(80px 80px,circle farthest-corner,#d90004 35%,#960004 100%);background:-webkit-gradient(radial,80 80,60,80 80,120,from(#d90004),to(#960004));-moz-border-radius:100px;-webkit-border-radius:100px;border-radius:100px;outline:none}.elfinder-help .elfinder-dont-panic span{font-size:3em;font-weight:700;text-align:center;color:#fff;position:absolute;left:0;top:45px}.elfinder{padding:0;position:relative;display:block}.elfinder-rtl{text-align:right;direction:rtl}.elfinder-workzone{padding:0;position:relative;overflow:hidden}.elfinder-perms,.elfinder-symlink{position:absolute;width:16px;height:16px;background-image:url(../img/toolbar.png);background-repeat:no-repeat;background-position:0 -528px}.elfinder-na .elfinder-perms{background-position:0 -96px}.elfinder-ro .elfinder-perms{background-position:0 -64px}.elfinder-wo .elfinder-perms{background-position:0 -80px}.elfinder-drag-helper{width:60px;height:50px;padding:0 0 0 25px;z-index:100000}.elfinder-drag-helper-icon-plus{position:absolute;width:16px;height:16px;left:43px;top:55px;background:url('../img/toolbar.png') 0 -544px no-repeat;display:none}.elfinder-drag-helper-plus .elfinder-drag-helper-icon-plus{display:block}.elfinder-drag-num{position:absolute;top:0;left:0;width:16px;height:14px;text-align:center;padding-top:2px;font-size:12px;font-weight:700;color:#fff;background-color:red;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.elfinder-drag-helper .elfinder-cwd-icon{margin:0 0 0 -24px;float:left}.elfinder-overlay{opacity:0;filter:Alpha(Opacity=0)}.elfinder .elfinder-panel{position:relative;background-image:none;padding:7px 12px}.elfinder-contextmenu,.elfinder-contextmenu-sub{display:none;position:absolute;border:1px solid #aaa;background:#fff;color:#555;padding:4px 0}.elfinder-contextmenu-sub{top:5px}.elfinder-contextmenu-ltr .elfinder-contextmenu-sub{margin-left:-5px}.elfinder-contextmenu-rtl .elfinder-contextmenu-sub{margin-right:-5px}.elfinder-contextmenu-item{position:relative;display:block;padding:4px 30px;text-decoration:none;white-space:nowrap;cursor:default}.elfinder-contextmenu .elfinder-contextmenu-item span{font-size:.76em;display:block}.elfinder-contextmenu-ltr .elfinder-contextmenu-item{text-align:left}.elfinder-contextmenu-rtl .elfinder-contextmenu-item{text-align:right}.elfinder-contextmenu-ltr .elfinder-contextmenu-sub .elfinder-contextmenu-item{padding-left:12px}.elfinder-contextmenu-rtl .elfinder-contextmenu-sub .elfinder-contextmenu-item{padding-right:12px}.elfinder-contextmenu-arrow,.elfinder-contextmenu-icon{position:absolute;top:50%;margin-top:-8px}.elfinder-contextmenu-ltr .elfinder-contextmenu-icon{left:8px}.elfinder-contextmenu-rtl .elfinder-contextmenu-icon{right:8px}.elfinder-contextmenu-arrow{width:16px;height:16px;background:url('../img/arrows-normal.png') 5px 4px no-repeat}.elfinder-contextmenu-ltr .elfinder-contextmenu-arrow{right:5px}.elfinder-contextmenu-rtl .elfinder-contextmenu-arrow{left:5px;background-position:0 -10px}.elfinder-contextmenu .ui-state-hover{border:0 solid;background-image:none}.elfinder-contextmenu-separator{height:0;border-top:1px solid #ccc;margin:0 1px}.elfinder-cwd-wrapper{overflow:auto;position:relative;padding:2px;margin:0}.elfinder-cwd-wrapper-list{padding:0}.elfinder-cwd{position:relative;font-size:.7em;cursor:default;padding:0;margin:0;-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;user-select:none}.elfinder .elfinder-cwd-wrapper.elfinder-droppable-active{padding:0;border:2px solid #8cafed}.elfinder-cwd-view-icons .elfinder-cwd-file{width:120px;height:80px;padding-bottom:2px;cursor:default;overflow:hidden}.elfinder-ltr .elfinder-cwd-view-icons .elfinder-cwd-file{float:left;margin:0 3px 12px 0}.elfinder-rtl .elfinder-cwd-view-icons .elfinder-cwd-file{float:right;margin:0 0 5px 3px}.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover{border:0 solid}.elfinder-cwd-view-icons .elfinder-cwd-file-wrapper{width:52px;height:52px;margin:1px auto;padding:2px;position:relative}.elfinder-cwd-view-icons .elfinder-cwd-filename{text-align:center;white-space:pre;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis;margin:3px 1px 0;padding:1px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.elfinder-cwd-view-icons .elfinder-perms{bottom:4px;right:2px}.elfinder-cwd-view-icons .elfinder-symlink{bottom:6px;left:0}.elfinder-cwd-icon{display:block;width:48px;height:48px;margin:0 auto;background:url('../img/icons-big.png') 0 0 no-repeat;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}.elfinder-cwd .elfinder-droppable-active .elfinder-cwd-icon{background-position:0 -100px}.elfinder-cwd-icon-directory{background-position:0 -50px}.elfinder-cwd-icon-application{background-position:0 -150px}.elfinder-cwd-icon-x-empty,.elfinder-cwd-icon-text{background-position:0 -200px}.elfinder-cwd-icon-image,.elfinder-cwd-icon-vnd-adobe-photoshop,.elfinder-cwd-icon-postscript{background-position:0 -250px}.elfinder-cwd-icon-audio{background-position:0 -300px}.elfinder-cwd-icon-video,.elfinder-cwd-icon-flash-video{background-position:0 -350px}.elfinder-cwd-icon-rtf,.elfinder-cwd-icon-rtfd{background-position:0 -401px}.elfinder-cwd-icon-pdf{background-position:0 -450px}.elfinder-cwd-icon-vnd-ms-office,.elfinder-cwd-icon-msword,.elfinder-cwd-icon-vnd-ms-word,.elfinder-cwd-icon-vnd-oasis-opendocument-text,.elfinder-cwd-icon-ms-excel,.elfinder-cwd-icon-vnd-ms-excel,.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet,.elfinder-cwd-icon-vnd-ms-powerpoint,.elfinder-cwd-icon-vnd-oasis-opendocument-presentation{background-position:0 -500px}.elfinder-cwd-icon-html{background-position:0 -550px}.elfinder-cwd-icon-css{background-position:0 -600px}.elfinder-cwd-icon-javascript,.elfinder-cwd-icon-x-javascript{background-position:0 -650px}.elfinder-cwd-icon-x-perl{background-position:0 -700px}.elfinder-cwd-icon-x-python{background-position:0 -750px}.elfinder-cwd-icon-x-ruby{background-position:0 -800px}.elfinder-cwd-icon-x-sh,.elfinder-cwd-icon-x-shellscript{background-position:0 -850px}.elfinder-cwd-icon-x-c,.elfinder-cwd-icon-x-csrc,.elfinder-cwd-icon-x-chdr,.elfinder-cwd-icon-x-c--,.elfinder-cwd-icon-x-c--src,.elfinder-cwd-icon-x-c--hdr,.elfinder-cwd-icon-x-java,.elfinder-cwd-icon-x-java-source{background-position:0 -900px}.elfinder-cwd-icon-x-php{background-position:0 -950px}.elfinder-cwd-icon-xml{background-position:0 -1000px}.elfinder-cwd-icon-zip,.elfinder-cwd-icon-x-zip,.elfinder-cwd-icon-x-7z-compressed{background-position:0 -1050px}.elfinder-cwd-icon-x-gzip,.elfinder-cwd-icon-x-tar{background-position:0 -1100px}.elfinder-cwd-icon-x-bzip,.elfinder-cwd-icon-x-bzip2{background-position:0 -1150px}.elfinder-cwd-icon-x-rar,.elfinder-cwd-icon-x-rar-compressed{background-position:0 -1200px}.elfinder-cwd-icon-x-shockwave-flash{background-position:0 -1250px}.elfinder-cwd-icon-group{background-position:0 -1300px}.elfinder-cwd input{width:100%;border:0 solid;margin:0;padding:0}.elfinder-cwd-view-icons input,.elfinder-cwd-view-icons{text-align:center}.elfinder-cwd table{width:100%;border-collapse:collapse;border:0 solid;margin:0 0 10px}.elfinder .elfinder-cwd table thead tr{border-left:0 solid;border-top:0 solid;border-right:0 solid}.elfinder .elfinder-cwd table thead td{font-size:.9em}.elfinder .elfinder-cwd table td{padding:3px 12px;white-space:pre;overflow:hidden;text-align:right;cursor:default;border:0 solid}.elfinder-ltr .elfinder-cwd table td{text-align:right}.elfinder-ltr .elfinder-cwd table td:first-child{text-align:left}.elfinder-rtl .elfinder-cwd table td{text-align:left}.elfinder-rtl .elfinder-cwd table td:first-child{text-align:right}.elfinder-odd-row{background:#eee}.elfinder-cwd-view-list .elfinder-cwd-file-wrapper{width:97%;position:relative}.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-file-wrapper{padding-left:23px}.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-file-wrapper{padding-right:23px}.elfinder-cwd-view-list .elfinder-perms,.elfinder-cwd-view-list .elfinder-symlink{top:50%;margin-top:-6px}.elfinder-ltr .elfinder-cwd-view-list .elfinder-perms{left:7px}.elfinder-ltr .elfinder-cwd-view-list .elfinder-symlink{left:-7px}.elfinder-cwd-view-list td .elfinder-cwd-icon{width:16px;height:16px;position:absolute;top:50%;margin-top:-8px;background-image:url(../img/icons-small.png)}.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-icon{left:0}.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-icon{right:0}.std42-dialog{padding:0}.std42-dialog .ui-dialog-titlebar{border-left:0 solid transparent;border-top:0 solid transparent;border-right:0 solid transparent;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;font-size:.82em;font-weight:400;padding:.2em 1em}.std42-dialog .ui-dialog-titlebar-close,.std42-dialog .ui-dialog-titlebar-close:hover{padding:1px}.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar{text-align:right}.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close{right:auto;left:.3em}.std42-dialog .ui-dialog-content{padding:.3em .5em;font-size:.72em}.std42-dialog .ui-dialog-buttonpane{border:0 solid;margin:0;padding:.5em .7em;font-size:.76em}.std42-dialog .ui-dialog-buttonpane button{margin:0 0 0 .4em;padding:0;outline:0 solid}.std42-dialog .ui-dialog-buttonpane button span{padding:2px 9px}.elfinder-dialog .ui-resizable-e,.elfinder-dialog .ui-resizable-s{width:0;height:0}.std42-dialog .ui-button input{cursor:pointer}.elfinder-dialog-icon{position:absolute;width:32px;height:32px;left:12px;top:50%;margin-top:-15px;background:url("../img/dialogs.png") 0 0 no-repeat}.elfinder-rtl .elfinder-dialog-icon{left:auto;right:12px}.elfinder-dialog-error .ui-dialog-content,.elfinder-dialog-confirm .ui-dialog-content{padding-left:56px;min-height:35px}.elfinder-rtl .elfinder-dialog-error .ui-dialog-content,.elfinder-rtl .elfinder-dialog-confirm .ui-dialog-content{padding-left:0;padding-right:56px}.elfinder-dialog-notify .ui-dialog-titlebar-close{display:none}.elfinder-dialog-notify .ui-dialog-content{padding:0}.elfinder-notify{border-bottom:1px solid #ccc;position:relative;padding:.5em;text-align:center;overflow:hidden}.elfinder-ltr .elfinder-notify{padding-left:30px}.elfinder-rtl .elfinder-notify{padding-right:30px}.elfinder-notify:last-child{border:0 solid}.elfinder-notify-progressbar{width:180px;height:8px;border:1px solid #aaa;background:#f5f5f5;margin:5px auto;overflow:hidden}.elfinder-notify-progress{width:100%;height:8px;background:url(../img/progress.gif) center center repeat-x}.elfinder-notify-progressbar,.elfinder-notify-progress{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.elfinder-dialog-icon-open,.elfinder-dialog-icon-file,.elfinder-dialog-icon-reload{background-position:0 -225px}.elfinder-dialog-icon-mkdir{background-position:0 -64px}.elfinder-dialog-icon-mkfile{background-position:0 -96px}.elfinder-dialog-icon-copy,.elfinder-dialog-icon-prepare,.elfinder-dialog-icon-move{background-position:0 -128px}.elfinder-dialog-icon-upload{background-position:0 -160px}.elfinder-dialog-icon-rm{background-position:0 -192px}.elfinder-dialog-icon-download{background-position:0 -260px}.elfinder-dialog-icon-save{background-position:0 -295px}.elfinder-dialog-icon-rename{background-position:0 -330px}.elfinder-dialog-icon-archive,.elfinder-dialog-icon-extract{background-position:0 -365px}.elfinder-dialog-icon-search{background-position:0 -402px}.elfinder-dialog-confirm-applyall{padding-top:3px}.elfinder-dialog-confirm .elfinder-dialog-icon{background-position:0 -32px}.elfinder-info-title .elfinder-cwd-icon{float:left;width:48px;height:48px;margin-right:1em}.elfinder-info-title strong{display:block;padding:.3em 0 .5em}.elfinder-info-tb{min-width:200px;border:0 solid;margin:1em .2em;font-size:.9em}.elfinder-info-tb td{white-space:nowrap;padding:2px}.elfinder-info-tb tr td:first-child{text-align:right}.elfinder-info-tb span{float:left}.elfinder-info-tb a{outline:none;text-decoration:underline}.elfinder-info-tb a:hover{text-decoration:none}.elfinder-info-spinner{width:14px;height:14px;float:left;background:url("../img/spinner-mini.gif") center center no-repeat;margin:0 5px}.elfinder-upload-dropbox{font-size:1.2em;text-align:center;padding:2em 0;border:3px dashed #aaa}.elfinder-upload-dropbox.ui-state-hover{background:#dfdfdf;border:3px dashed #555}.elfinder-upload-dialog-or{font-size:1.2em;margin:.3em 0;text-align:center}.elfinder-upload-dialog-wrapper{text-align:center}.elfinder-upload-dialog-wrapper .ui-button{position:relative;overflow:hidden}.elfinder-upload-dialog-wrapper .ui-button form{position:absolute;right:0;top:0;opacity:0;filter:Alpha(Opacity=0)}.elfinder-upload-dialog-wrapper .ui-button form input{padding:0 20px;font-size:3em}.dialogelfinder .dialogelfinder-drag{border-left:0 solid;border-top:0 solid;border-right:0 solid;font-weight:400;font-size:.9em;padding:2px 12px;cursor:move;position:relative;text-align:left}.elfinder-rtl .dialogelfinder-drag{text-align:right}.dialogelfinder-drag-close{position:absolute;top:50%;margin-top:-8px}.elfinder-ltr .dialogelfinder-drag-close{right:12px}.elfinder-rtl .dialogelfinder-drag-close{left:12px}.elfinder .elfinder-navbar{width:230px;padding:3px 5px;font-size:.72em;background-image:none;border-top:0 solid;border-bottom:0 solid;overflow:auto;display:none;position:relative;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;user-select:none}.elfinder-ltr .elfinder-navbar{float:left;border-left:0 solid}.elfinder-rtl .elfinder-navbar{float:right;border-right:0 solid}.elfinder-ltr .ui-resizable-e{margin-left:10px}.elfinder-tree{display:table;width:100%;margin:0 0 .5em}.elfinder-navbar-dir{position:relative;display:block;white-space:nowrap;padding:3px 12px;margin:0;outline:0 solid;border:1px solid transparent;cursor:default}.elfinder-ltr .elfinder-navbar-dir{padding-left:35px}.elfinder-rtl .elfinder-navbar-dir{padding-right:35px}.elfinder-navbar-arrow{width:12px;height:14px;position:absolute;display:none;top:50%;margin-top:-8px;background-image:url("../img/arrows-normal.png");background-repeat:no-repeat}.ui-state-active .elfinder-navbar-arrow{background-image:url("../img/arrows-active.png")}.elfinder-navbar-collapsed .elfinder-navbar-arrow{display:block}.elfinder-ltr .elfinder-navbar-collapsed .elfinder-navbar-arrow{background-position:0 4px;left:0}.elfinder-rtl .elfinder-navbar-collapsed .elfinder-navbar-arrow{background-position:0 -10px;right:0}.elfinder-ltr .elfinder-navbar-expanded .elfinder-navbar-arrow,.elfinder-rtl .elfinder-navbar-expanded .elfinder-navbar-arrow{background-position:0 -21px}.elfinder-navbar-icon{width:16px;height:16px;position:absolute;top:50%;margin-top:-8px;background-image:url("../img/toolbar.png");background-repeat:no-repeat;background-position:0 -16px}.elfinder-ltr .elfinder-navbar-icon{left:14px}.elfinder-rtl .elfinder-navbar-icon{right:14px}.elfinder-tree .elfinder-navbar-root .elfinder-navbar-icon{background-position:0 0}.elfinder-places .elfinder-navbar-root .elfinder-navbar-icon{background-position:0 -48px}.ui-state-active .elfinder-navbar-icon,.elfinder-droppable-active .elfinder-navbar-icon,.ui-state-hover .elfinder-navbar-icon{background-position:0 -32px}.elfinder-navbar-subtree{display:none}.elfinder-ltr .elfinder-navbar-subtree{margin-left:12px}.elfinder-rtl .elfinder-navbar-subtree{margin-right:12px}.elfinder-navbar-spinner{width:14px;height:14px;position:absolute;display:block;top:50%;margin-top:-7px;background:url("../img/spinner-mini.gif") center center no-repeat}.elfinder-ltr .elfinder-navbar-spinner{left:0;margin-left:-2px}.elfinder-rtl .elfinder-navbar-spinner{right:0;margin-right:-2px}.elfinder-navbar .elfinder-perms{top:50%;margin-top:-8px}.elfinder-ltr .elfinder-navbar .elfinder-perms{left:18px}.elfinder-rtl .elfinder-navbar .elfinder-perms{right:18px}.elfinder-ltr .elfinder-navbar .elfinder-symlink{left:8px}.elfinder-rtl .elfinder-navbar .elfinder-symlink{right:8px}.elfinder-navbar .ui-resizable-handle{width:12px;background:url('../img/resize.png') center center no-repeat;left:0}.elfinder-nav-handle-icon{position:absolute;top:50%;margin:-8px 2px 0;opacity:.5;filter:Alpha(Opacity=50)}.elfinder-places{border:1px solid transparent}.elfinder-places.elfinder-droppable-active{border:1px solid #8cafed}.elfinder-place-drag .elfinder-navbar-dir{font-size:.9em}.elfinder-quicklook{position:absolute;background:url("../img/quicklook-bg.png");display:none;overflow:hidden;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px;padding:20px 0 40px}.elfinder-quicklook .ui-resizable-se{width:14px;height:14px;right:5px;bottom:3px;background:url("../img/toolbar.png") 0 -496px no-repeat}.elfinder-quicklook-fullscreen{border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;-webkit-background-clip:padding-box;padding:0;background:#000;z-index:90000;display:block}.elfinder-quicklook-fullscreen .elfinder-quicklook-titlebar{display:none}.elfinder-quicklook-fullscreen .elfinder-quicklook-preview{border:0 solid}.elfinder-quicklook-titlebar{text-align:center;background:#777;position:absolute;left:0;top:0;width:100%;height:20px;-moz-border-radius-topleft:7px;-webkit-border-top-left-radius:7px;border-top-left-radius:7px;-moz-border-radius-topright:7px;-webkit-border-top-right-radius:7px;border-top-right-radius:7px;cursor:move}.elfinder-quicklook-title{font-size:.7em;color:#fff;white-space:nowrap;overflow:hidden;padding:2px 0}.elfinder-quicklook-titlebar .ui-icon{position:absolute;left:4px;top:50%;margin-top:-8px;width:16px;height:16px;cursor:default}.elfinder-quicklook-preview{overflow:hidden;position:relative;border:0 solid;border-left:1px solid transparent;border-right:1px solid transparent;height:100%}.elfinder-quicklook-info-wrapper{position:absolute;width:100%;left:0;top:50%;margin-top:-50px}.elfinder-quicklook-info{padding:0 12px 0 112px}.elfinder-quicklook-info .elfinder-quicklook-info-data:first-child{color:#fff;font-weight:700;padding-bottom:.5em}.elfinder-quicklook-info-data{font-size:.72em;padding-bottom:.2em;color:#fff}.elfinder-quicklook .elfinder-cwd-icon{position:absolute;left:32px;top:50%;margin-top:-20px}.elfinder-quicklook-preview img{display:block;margin:0 auto}.elfinder-quicklook-navbar{position:absolute;left:50%;bottom:4px;width:140px;height:32px;padding:0;margin-left:-70px;border:1px solid transparent;border-radius:19px;-moz-border-radius:19px;-webkit-border-radius:19px}.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar{width:188px;margin-left:-94px;padding:5px;border:1px solid #eee;background:#000}.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-icon-close,.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-separator{display:inline}.elfinder-quicklook-navbar-icon{width:32px;height:32px;margin:0 7px;float:left;background:url("../img/quicklook-icons.png") 0 0 no-repeat}.elfinder-quicklook-navbar-icon-fullscreen{background-position:0 -64px}.elfinder-quicklook-navbar-icon-fullscreen-off{background-position:0 -96px}.elfinder-quicklook-navbar-icon-prev{background-position:0 0}.elfinder-quicklook-navbar-icon-next{background-position:0 -32px}.elfinder-quicklook-navbar-icon-close{background-position:0 -128px;display:none}.elfinder-quicklook-navbar-separator{width:1px;height:32px;float:left;border-left:1px solid #fff;display:none}.elfinder-quicklook-preview-text-wrapper{width:100%;height:100%;background:#fff;color:#222;font-size:.9em;overflow:auto}pre.elfinder-quicklook-preview-text{margin:0;padding:3px 9px}.elfinder-quicklook-preview-html,.elfinder-quicklook-preview-pdf{width:100%;height:100%;background:#fff;border:0 solid;margin:0}.elfinder-quicklook-preview-flash{width:100%;height:100%}.elfinder-quicklook-preview-audio{width:100%;position:absolute;bottom:0;left:0}embed.elfinder-quicklook-preview-audio{height:30px;background:0 0}.elfinder-quicklook-preview-video{width:100%;height:100%}.elfinder-statusbar{text-align:center;font-weight:400;padding:.2em .5em;border-right:0 solid transparent;border-bottom:0 solid transparent;border-left:0 solid transparent}.elfinder-statusbar a{text-decoration:none}.elfinder-statusbar div{font-size:.7em}.elfinder-path{max-width:30%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis}.elfinder-ltr .elfinder-path{float:left}.elfinder-rtl .elfinder-path{float:right}.elfinder-stat-size{white-space:nowrap}.elfinder-ltr .elfinder-stat-size{float:right}.elfinder-rtl .elfinder-stat-size{float:left}.elfinder-stat-selected{white-space:nowrap;overflow:hidden}.elfinder-toolbar{padding:4px 0 3px;border-left:0 solid transparent;border-top:0 solid transparent;border-right:0 solid transparent}.elfinder-buttonset{margin:1px 4px;float:left;background:0 0;padding:0;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.elfinder .elfinder-button{width:16px;height:16px;margin:0;padding:4px;float:left;overflow:hidden;position:relative;border:0 solid}.elfinder .ui-icon-search{cursor:pointer}.elfinder-button:first-child{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.elfinder-button:last-child{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.elfinder-toolbar-button-separator{float:left;padding:0;height:24px;border-top:0 solid;border-right:0 solid;border-bottom:0 solid;width:0}.elfinder .elfinder-button.ui-state-disabled{opacity:1;filter:Alpha(Opacity=100)}.elfinder .elfinder-button.ui-state-disabled .elfinder-button-icon{opacity:.4;filter:Alpha(Opacity=40)}.elfinder-rtl .elfinder-buttonset{float:right}.elfinder-button-icon{width:16px;height:16px;display:block;background:url('../img/toolbar.png') no-repeat}.elfinder-button-icon-home{background-position:0 0}.elfinder-button-icon-back{background-position:0 -112px}.elfinder-button-icon-forward{background-position:0 -128px}.elfinder-button-icon-up{background-position:0 -144px}.elfinder-button-icon-reload{background-position:0 -160px}.elfinder-button-icon-open{background-position:0 -176px}.elfinder-button-icon-mkdir{background-position:0 -192px}.elfinder-button-icon-mkfile{background-position:0 -208px}.elfinder-button-icon-rm{background-position:0 -224px}.elfinder-button-icon-copy{background-position:0 -240px}.elfinder-button-icon-cut{background-position:0 -256px}.elfinder-button-icon-paste{background-position:0 -272px}.elfinder-button-icon-getfile{background-position:0 -288px}.elfinder-button-icon-duplicate{background-position:0 -304px}.elfinder-button-icon-rename{background-position:0 -320px}.elfinder-button-icon-edit{background-position:0 -336px}.elfinder-button-icon-quicklook{background-position:0 -352px}.elfinder-button-icon-upload{background-position:0 -368px}.elfinder-button-icon-download{background-position:0 -384px}.elfinder-button-icon-info{background-position:0 -400px}.elfinder-button-icon-extract{background-position:0 -416px}.elfinder-button-icon-archive{background-position:0 -432px}.elfinder-button-icon-view{background-position:0 -448px}.elfinder-button-icon-view-list{background-position:0 -464px}.elfinder-button-icon-help{background-position:0 -480px}.elfinder-button-icon-resize{background-position:0 -512px}.elfinder-button-icon-search{background-position:0 -561px}.elfinder-button-icon-sort{background-position:0 -577px}.elfinder-button-icon-rotate-r{background-position:0 -625px}.elfinder-button-icon-rotate-l{background-position:0 -641px}.elfinder .elfinder-menubutton{overflow:visible}.elfinder-button-menu{position:absolute;left:0;top:26px;padding:3px 0}.elfinder-button-menu-item{white-space:nowrap;font-size:.72em;cursor:default;padding:5px 19px;position:relative}.elfinder-button-menu .ui-state-hover{border:0 solid}.elfinder-menu-item-sort-dir{width:16px;height:16px;position:absolute;left:2px;top:50%;margin-top:-8px;background:url("../img/toolbar.png") 0 -594px no-repeat;display:none}.elfinder-button-menu-item-selected .elfinder-menu-item-sort-dir{display:block}.elfinder-menu-item-sort-desc .elfinder-menu-item-sort-dir{background-position:0 -608px}.elfinder-button form{position:absolute;top:0;right:0;opacity:0;filter:Alpha(Opacity=0);cursor:pointer}.elfinder .elfinder-button form input{background:0 0;cursor:default}.elfinder .elfinder-button-search{border:0 solid;background:0 0;padding:0;margin:1px 4px;height:auto;min-height:26px;float:right;width:202px}.elfinder-ltr .elfinder-button-search{float:right;margin-right:10px}.elfinder-rtl .elfinder-button-search{float:left;margin-left:10px}.elfinder-button-search input{width:160px;height:22px;padding:0 20px;font-size:.8em;line-height:22px;border:1px solid #aaa;-moz-border-radius:12px;-webkit-border-radius:12px;border-radius:12px;outline:0 solid}.elfinder-rtl .elfinder-button-search input{direction:rtl}.elfinder-button-search .ui-icon{position:absolute;height:18px;top:50%;margin:-9px 4px 0;opacity:.6;filter:Alpha(Opacity=60)}.elfinder-ltr .elfinder-button-search .ui-icon-search{left:0}.elfinder-rtl .elfinder-button-search .ui-icon-search,.elfinder-ltr .elfinder-button-search .ui-icon-close{right:0}.elfinder-rtl .elfinder-button-search .ui-icon-close{left:0} \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/index.html b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/theme.css b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/theme.css new file mode 100644 index 00000000..369270ad --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css/theme.css @@ -0,0 +1,49 @@ +/** + * MacOS X like theme for elFinder. + * Required jquery ui "smoothness" theme. + * + * @author Dmitry (dio) Levashov + **/ + +/* dialogs */ +.std42-dialog, .std42-dialog .ui-widget-content { background-color:#ededed; background-image:none; background-clip: content-box; } + +/* navbar */ +.elfinder .elfinder-navbar { background:#dde4eb; } +.elfinder-navbar .ui-state-hover { background:transparent; border-color:transparent; } +.elfinder-navbar .ui-state-active { background: #3875d7; border-color:#3875d7; color:#fff; } +/* disabled elfinder */ +.elfinder-disabled .elfinder-navbar .ui-state-active { background: #dadada; border-color:#aaa; color:#fff; } + + +/* current directory */ +/* selected file in "icons" view */ +.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover { background:#ccc; } +/* list view*/ +.elfinder-cwd table tr:nth-child(odd) { background-color:#edf3fe; } +.elfinder-cwd table tr { border-top:1px solid #fff; } + +/* common selected background/color */ +.elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, +.elfinder-cwd table td.ui-state-hover, +.elfinder-button-menu .ui-state-hover { background: #3875d7; color:#fff;} +/* disabled elfinder */ +.elfinder-disabled .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, +.elfinder-disabled .elfinder-cwd table td.ui-state-hover { background:#dadada;} + +/* statusbar */ +.elfinder .elfinder-statusbar { color:#555; } +.elfinder .elfinder-statusbar a { text-decoration:none; color:#555;} + + +.std42-dialog .elfinder-help, .std42-dialog .elfinder-help .ui-widget-content { background:#fff;} + +/* contextmenu */ +.elfinder-contextmenu .ui-state-hover { background: #3875d7; color:#fff; } +.elfinder-contextmenu .ui-state-hover .elfinder-contextmenu-arrow { background-image:url('../img/arrows-active.png'); } + + + + + + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.full.css b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.full.css new file mode 100644 index 00000000..87cb28e2 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.full.css @@ -0,0 +1,1650 @@ +/*! + * elFinder - file manager for web + * Version 2.1 (Nightly: 595cc96) (2014-04-24) + * http://elfinder.org + * + * Copyright 2009-2013, Studio 42 + * Licensed under a 3 clauses BSD license + */ + +/* File: /home/osc/elFinder-build/elFinder/css/commands.css */ +/******************************************************************/ +/* COMMANDS STYLES */ +/******************************************************************/ + +/********************** COMMAND "RESIZE" ****************************/ +.elfinder-dialog-resize { margin-top:.3em; } +.elfinder-resize-type { float:left; margin-bottom: .4em; } +.elfinder-resize-control { padding-top:3em; } +.elfinder-resize-control input[type=text] { border:1px solid #aaa; text-align: right; } +.elfinder-resize-preview { + width:400px; + height:400px; + padding:10px; + background:#fff; + border:1px solid #aaa; + float:right; + position:relative; + overflow:auto; +/* z-index:100;*/ +} + +.elfinder-resize-handle { position:relative;} + +.elfinder-resize-handle-hline, +.elfinder-resize-handle-vline { + position:absolute; + background-image:url("../img/crop.gif"); +} + +.elfinder-resize-handle-hline { + width:100%; + height:1px !important; + background-repeat:repeat-x; +} +.elfinder-resize-handle-vline { + width:1px !important; + height:100%; + background-repeat:repeat-y; +} + +.elfinder-resize-handle-hline-top { top:0; left:0; } +.elfinder-resize-handle-hline-bottom { bottom:0; left:0; } +.elfinder-resize-handle-vline-left { top:0; left:0; } +.elfinder-resize-handle-vline-right { top:0; right:0; } + +.elfinder-resize-handle-point { + position:absolute; + width:8px; + height:8px; + border:1px solid #777; + background:transparent; +} + +.elfinder-resize-handle-point-n { + top:0; + left:50%; + margin-top:-5px; + margin-left:-5px; +} +.elfinder-resize-handle-point-ne { + top:0; + right:0; + margin-top:-5px; + margin-right:-5px; +} +.elfinder-resize-handle-point-e { + top:50%; + right:0; + margin-top:-5px; + margin-right:-5px; +} +.elfinder-resize-handle-point-se { + bottom:0; + right:0; + margin-bottom:-5px; + margin-right:-5px; +} +.elfinder-resize-handle-point-s { + bottom:0; + left:50%; + margin-bottom:-5px; + margin-left:-5px; +} +.elfinder-resize-handle-point-sw { + bottom:0; + left:0; + margin-bottom:-5px; + margin-left:-5px; +} +.elfinder-resize-handle-point-w { + top:50%; + left:0; + margin-top:-5px; + margin-left:-5px; +} +.elfinder-resize-handle-point-nw { + top:0; + left:0; + margin-top:-5px; + margin-left:-5px; +} + +.elfinder-resize-spinner { + position:absolute; + width:200px; + height:30px; + top:50%; + margin-top:-25px; + left:50%; + margin-left:-100px; + text-align:center; + background:url(../img/progress.gif) center bottom repeat-x; +} + +.elfinder-resize-row { margin-bottom:7px; position:relative;} + +.elfinder-resize-label { float:left; width:80px; padding-top: 3px; } + +.elfinder-resize-reset { + width:16px; + height:16px; +/* border:1px solid #111;*/ + position:absolute; + margin-top:-8px; +} + +.elfinder-dialog .elfinder-dialog-resize .ui-resizable-e { height:100%; width:10px; } +.elfinder-dialog .elfinder-dialog-resize .ui-resizable-s { width:100%; height:10px; } +.elfinder-dialog .elfinder-dialog-resize .ui-resizable-se { + background:transparent; + bottom:0; + right:0; + margin-right:-7px; + margin-bottom:-7px; +} + +.elfinder-dialog-resize .ui-icon-grip-solid-vertical { + position:absolute; + top:50%; + right:0; + margin-top:-8px; + margin-right:-11px; +} +.elfinder-dialog-resize .ui-icon-grip-solid-horizontal { + position:absolute; + left:50%; + bottom:0; + margin-left:-8px; + margin-bottom:-11px;; +} + +.elfinder-resize-row .elfinder-buttonset { float:right; } + +.elfinder-resize-rotate-slider { + float: left; + width: 195px; + margin: 7px 7px 0; +} + +/********************** COMMAND "EDIT" ****************************/ +/* edit text file textarea */ +.elfinder-file-edit { + width:99%; + height:99%; + margin:0; + padding:2px; + border:1px solid #ccc; +} + + +/********************** COMMAND "HELP" ****************************/ +/* help dialog */ +.elfinder-help { margin-bottom:.5em; } + +/* fix tabs */ +.elfinder-help .ui-tabs-panel { padding:.5em; } +.elfinder-dialog .ui-tabs .ui-tabs-nav li a { padding:.2em 1em;} + +.elfinder-help-shortcuts { + height:300px; + padding:1em; + margin:.5em 0; + overflow:auto; +} +.elfinder-help-shortcut { white-space:nowrap; clear:both;} + +.elfinder-help-shortcut-pattern { float:left; width:160px;} + +.elfinder-help-logo { + width:100px; + height:96px; + float:left; + margin-right:1em; + background:url('../img/logo.png') center center no-repeat; +} + +.elfinder-help h3 { font-size:1.5em; margin:.2em 0 .3em 0; } + +.elfinder-help-separator { clear:both; padding:.5em; } + +.elfinder-help-link { padding:2px; } + +.elfinder-help .ui-priority-secondary { font-size:.9em;} + +.elfinder-help .ui-priority-primary { margin-bottom:7px;} + +.elfinder-help-team { + clear: both; + text-align:right; + border-bottom:1px solid #ccc; + margin:.5em 0; + font-size:.9em; +} + +.elfinder-help-team div { float:left; } +.elfinder-help-license { font-size:.9em;} + +.elfinder-help-disabled { + font-weight:bold; + text-align:center; + margin:90px 0; +} + +.elfinder-help .elfinder-dont-panic { + display:block; + border:1px solid transparent; + width:200px; + height:200px; + margin:30px auto; + text-decoration:none; + text-align:center; + position:relative; + background:#d90004; + -moz-box-shadow: 5px 5px 9px #111; + -webkit-box-shadow: 5px 5px 9px #111; + box-shadow: 5px 5px 9px #111; + background: -moz-radial-gradient(80px 80px, circle farthest-corner, #d90004 35%, #960004 100%); + background: -webkit-gradient(radial, 80 80, 60, 80 80, 120, from(#d90004), to(#960004)); + -moz-border-radius: 100px; + -webkit-border-radius: 100px; + border-radius: 100px; + outline:none; +} + +.elfinder-help .elfinder-dont-panic span { + font-size:3em; + font-weight:bold; + text-align:center; + color:#fff; + position:absolute; + left:0; + top:45px; +} + + + + +/* File: /home/osc/elFinder-build/elFinder/css/common.css */ +/*********************************************/ +/* COMMON ELFINDER STUFFS */ +/*********************************************/ + +/* common container */ +.elfinder { padding:0; position:relative; display:block; } + +/* right to left enviroment */ +.elfinder-rtl { text-align:right; direction:rtl; } + +/* nav and cwd container */ +.elfinder-workzone { + padding: 0; + position:relative; + overflow:hidden; +} + +/* dir/file permissions and symlink markers */ +.elfinder-lock, +.elfinder-perms, +.elfinder-symlink { + position:absolute; + width:16px; + height:16px; + background-image:url(../img/toolbar.png); + background-repeat:no-repeat; + background-position:0 -528px; +} + +.elfinder-symlink { } + +/* noaccess */ +.elfinder-na .elfinder-perms { background-position:0 -96px; } + +/* read only */ +.elfinder-ro .elfinder-perms { background-position:0 -64px;} + +/* write only */ +.elfinder-wo .elfinder-perms { background-position:0 -80px;} + +/* locked */ +.elfinder-lock { + background-position:0 -656px; +} + +/* drag helper */ +.elfinder-drag-helper { + width:60px; + height:50px; + padding:0 0 0 25px; + z-index:100000; +} + +/* drag helper "plus" icon */ +.elfinder-drag-helper-icon-plus { + position:absolute; + width:16px; + height:16px; + left:43px; + top:55px; + background:url('../img/toolbar.png') 0 -544px no-repeat; + display:none; +} + +/* show "plus" icon when ctrl/shift pressed */ +.elfinder-drag-helper-plus .elfinder-drag-helper-icon-plus { display:block; } + +/* files num in drag helper */ +.elfinder-drag-num { + position:absolute; + top:0; + left:0; + width:16px; + height:14px; + text-align:center; + padding-top:2px; + + font-weight:bold; + color:#fff; + background-color:red; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +/* icon in drag helper */ +.elfinder-drag-helper .elfinder-cwd-icon { margin:0 0 0 -24px; float:left; } + +/* transparent overlay >_< */ +.elfinder-overlay { opacity: 0; filter:Alpha(Opacity=0); } + +/* panels under/below cwd (for search field etc) */ +.elfinder .elfinder-panel { + position:relative; + background-image:none; + padding:7px 12px; +} + + + + + + +/* File: /home/osc/elFinder-build/elFinder/css/contextmenu.css */ +/* menu and submenu */ +.elfinder-contextmenu, +.elfinder-contextmenu-sub { + display:none; + position:absolute; + border:1px solid #aaa; + background:#fff; + color:#555; + padding:4px 0; +} + +/* submenu */ +.elfinder-contextmenu-sub { top:5px; } +/* submenu in rtl/ltr enviroment */ +.elfinder-contextmenu-ltr .elfinder-contextmenu-sub { margin-left:-5px; } +.elfinder-contextmenu-rtl .elfinder-contextmenu-sub { margin-right:-5px; } + +/* menu item */ +.elfinder-contextmenu-item { + position:relative; + display:block; + padding:4px 30px; + text-decoration:none; + white-space:nowrap; + cursor:default; +} +/* text in item */ +.elfinder-contextmenu .elfinder-contextmenu-item span { display:block; } + + + +/* submenu item in rtl/ltr enviroment */ +.elfinder-contextmenu-ltr .elfinder-contextmenu-item { text-align:left; } +.elfinder-contextmenu-rtl .elfinder-contextmenu-item { text-align:right; } +.elfinder-contextmenu-ltr .elfinder-contextmenu-sub .elfinder-contextmenu-item { padding-left:12px; } +.elfinder-contextmenu-rtl .elfinder-contextmenu-sub .elfinder-contextmenu-item { padding-right:12px; } + +/* command/submenu icon */ +.elfinder-contextmenu-arrow, +.elfinder-contextmenu-icon { + position:absolute; + top:50%; + margin-top:-8px; +} + +/* command icon in rtl/ltr enviroment */ +.elfinder-contextmenu-ltr .elfinder-contextmenu-icon { left:8px; } +.elfinder-contextmenu-rtl .elfinder-contextmenu-icon { right:8px; } + +/* arrow icon */ +.elfinder-contextmenu-arrow { + width:16px; + height:16px; + background:url('../img/arrows-normal.png') 5px 4px no-repeat; +} + +/* arrow icon in rtl/ltr enviroment */ +.elfinder-contextmenu-ltr .elfinder-contextmenu-arrow { right:5px; } +.elfinder-contextmenu-rtl .elfinder-contextmenu-arrow { left:5px; background-position: 0 -10px; } + +/* disable ui border/bg image on hover */ +.elfinder-contextmenu .ui-state-hover { border:0 solid; background-image:none;} + +/* separator */ +.elfinder-contextmenu-separator { + height:0px; + border-top:1px solid #ccc; + margin:0 1px; +} + +/* File: /home/osc/elFinder-build/elFinder/css/cwd.css */ +/******************************************************************/ +/* CURRENT DIRECTORY STYLES */ +/******************************************************************/ +/* cwd container to avoid selectable on scrollbar */ +.elfinder-cwd-wrapper { + overflow: auto; + position:relative; + padding:2px; + margin:0; +} + +.elfinder-cwd-wrapper-list { padding:0; } + +/* container */ +.elfinder-cwd { + position:relative; + cursor:default; + padding:0; + margin:0; + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + user-select: none; + -webkit-tap-highlight-color:rgba(0,0,0,0); +} + +/* container active on dropenter */ +.elfinder .elfinder-cwd-wrapper.elfinder-droppable-active { + padding:0; + border:2px solid #8cafed; +} + + +/************************** ICONS VIEW ********************************/ + +/* file container */ +.elfinder-cwd-view-icons .elfinder-cwd-file { + width:120px; + height:80px; + padding-bottom:2px; + cursor:default; + border:none; +/* overflow:hidden;*/ +/* position:relative;*/ +} + +/* ltr/rtl enviroment */ +.elfinder-ltr .elfinder-cwd-view-icons .elfinder-cwd-file { float:left; margin:0 3px 12px 0; } +.elfinder-rtl .elfinder-cwd-view-icons .elfinder-cwd-file { float:right; margin:0 0 5px 3px; } + +/* remove ui hover class border */ +.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover { border:0 solid; } + +/* icon wrapper to create selected highlight around icon */ +.elfinder-cwd-view-icons .elfinder-cwd-file-wrapper { + width:52px; + height:52px; + margin:1px auto 1px auto; + padding:2px; + position:relative; +} + +/* file name place */ +.elfinder-cwd-view-icons .elfinder-cwd-filename { + text-align:center; + white-space:pre; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; + margin:3px 1px 0 1px; + padding:1px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +/* permissions/symlink markers */ +.elfinder-cwd-view-icons .elfinder-perms { bottom:4px; right:2px; } +.elfinder-cwd-view-icons .elfinder-lock { top:-3px; right:-2px; } +.elfinder-cwd-view-icons .elfinder-symlink { bottom:6px; left:0px; } + +/* icon/thumbnail */ +.elfinder-cwd-icon { + display:block; + width:48px; + height:48px; + margin:0 auto; + background: url('../img/icons-big.png') 0 0 no-repeat; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; +} + +/* "opened folder" icon on dragover */ +.elfinder-cwd .elfinder-droppable-active .elfinder-cwd-icon { background-position: 0 -100px; } + +/* mimetypes icons */ +.elfinder-cwd-icon-directory { background-position:0 -50px; } +.elfinder-cwd-icon-application { background-position:0 -150px; } +.elfinder-cwd-icon-x-empty, +.elfinder-cwd-icon-text { background-position:0 -200px; } +.elfinder-cwd-icon-image, +.elfinder-cwd-icon-vnd-adobe-photoshop, +.elfinder-cwd-icon-postscript { background-position:0 -250px; } +.elfinder-cwd-icon-audio { background-position:0 -300px; } +.elfinder-cwd-icon-video, +.elfinder-cwd-icon-flash-video { background-position:0 -350px; } +.elfinder-cwd-icon-rtf, +.elfinder-cwd-icon-rtfd { background-position: 0 -401px; } +.elfinder-cwd-icon-pdf { background-position: 0 -450px; } +.elfinder-cwd-icon-ms-excel, +.elfinder-cwd-icon-msword, +.elfinder-cwd-icon-vnd-ms-excel, +.elfinder-cwd-icon-vnd-ms-excel-addin-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-excel-sheet-binary-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-excel-sheet-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-excel-template-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-office, +.elfinder-cwd-icon-vnd-ms-powerpoint, +.elfinder-cwd-icon-vnd-ms-powerpoint-addin-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-powerpoint-presentation-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-powerpoint-slide-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-powerpoint-slideshow-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-powerpoint-template-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-word, +.elfinder-cwd-icon-vnd-ms-word-document-macroEnabled-12, +.elfinder-cwd-icon-vnd-ms-word-template-macroEnabled-12, +.elfinder-cwd-icon-vnd-oasis-opendocument-chart, +.elfinder-cwd-icon-vnd-oasis-opendocument-database, +.elfinder-cwd-icon-vnd-oasis-opendocument-formula, +.elfinder-cwd-icon-vnd-oasis-opendocument-graphics, +.elfinder-cwd-icon-vnd-oasis-opendocument-graphics-template, +.elfinder-cwd-icon-vnd-oasis-opendocument-image, +.elfinder-cwd-icon-vnd-oasis-opendocument-presentation, +.elfinder-cwd-icon-vnd-oasis-opendocument-presentation-template, +.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet, +.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet-template, +.elfinder-cwd-icon-vnd-oasis-opendocument-text, +.elfinder-cwd-icon-vnd-oasis-opendocument-text-master, +.elfinder-cwd-icon-vnd-oasis-opendocument-text-template, +.elfinder-cwd-icon-vnd-oasis-opendocument-text-web, +.elfinder-cwd-icon-vnd-openofficeorg-extension, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-presentation, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slide, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slideshow, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-template, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-sheet, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-template, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-document, +.elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-template { background-position: 0 -500px; } +.elfinder-cwd-icon-html { background-position: 0 -550px; } +.elfinder-cwd-icon-css { background-position: 0 -600px; } +.elfinder-cwd-icon-javascript, +.elfinder-cwd-icon-x-javascript { background-position: 0 -650px; } +.elfinder-cwd-icon-x-perl { background-position: 0 -700px; } +.elfinder-cwd-icon-x-python { background-position: 0 -750px; } +.elfinder-cwd-icon-x-ruby { background-position: 0 -800px; } +.elfinder-cwd-icon-x-sh, +.elfinder-cwd-icon-x-shellscript { background-position: 0 -850px; } +.elfinder-cwd-icon-x-c, +.elfinder-cwd-icon-x-csrc, +.elfinder-cwd-icon-x-chdr, +.elfinder-cwd-icon-x-c--, +.elfinder-cwd-icon-x-c--src, +.elfinder-cwd-icon-x-c--hdr, +.elfinder-cwd-icon-x-java, +.elfinder-cwd-icon-x-java-source { background-position: 0 -900px; } +.elfinder-cwd-icon-x-php { background-position: 0 -950px; } +.elfinder-cwd-icon-xml { background-position: 0 -1000px; } +.elfinder-cwd-icon-zip, +.elfinder-cwd-icon-x-zip, +.elfinder-cwd-icon-x-7z-compressed { background-position: 0 -1050px; } +.elfinder-cwd-icon-x-gzip, +.elfinder-cwd-icon-x-tar { background-position: 0 -1100px; } +.elfinder-cwd-icon-x-bzip, +.elfinder-cwd-icon-x-bzip2 { background-position: 0 -1150px; } +.elfinder-cwd-icon-x-rar, +.elfinder-cwd-icon-x-rar-compressed { background-position: 0 -1200px; } +.elfinder-cwd-icon-x-shockwave-flash { background-position: 0 -1250px; } +.elfinder-cwd-icon-group { background-position:0 -1300px;} + +/* textfield inside icon */ +.elfinder-cwd input { width:100%; border:0px solid; margin:0; padding:0; } +.elfinder-cwd-view-icons input {text-align:center; } + +.elfinder-cwd-view-icons { text-align:center; } + + +/************************************ LIST VIEW ************************************/ + +/*.elfinder-cwd-view-list { padding:0 0 4px 0; }*/ + +.elfinder-cwd table { width:100%; border-collapse:collapse; border:0 solid; margin:0 0 10px 0; } +.elfinder .elfinder-cwd table thead tr { border-left:0 solid; border-top:0 solid; border-right:0 solid; } + +.elfinder .elfinder-cwd table td { + padding:3px 12px; + white-space:pre; + overflow:hidden; + text-align:right; + cursor:default; + border:0 solid; + +} + +.elfinder-ltr .elfinder-cwd table td { text-align:right; } +.elfinder-ltr .elfinder-cwd table td:first-child { text-align:left; } +.elfinder-rtl .elfinder-cwd table td { text-align:left; } +.elfinder-rtl .elfinder-cwd table td:first-child { text-align:right; } + +.elfinder-odd-row { background:#eee; } + +/* filename container */ +.elfinder-cwd-view-list .elfinder-cwd-file-wrapper { width:97%; position:relative; } +/* filename container in ltr/rtl enviroment */ +.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-file-wrapper { padding-left:23px; } +.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-file-wrapper { padding-right:23px; } + +/* premissions/symlink marker */ +.elfinder-cwd-view-list .elfinder-perms, +.elfinder-cwd-view-list .elfinder-lock, +.elfinder-cwd-view-list .elfinder-symlink { top:50%; margin-top:-6px; } +/* markers in ltr/rtl enviroment */ +.elfinder-ltr .elfinder-cwd-view-list .elfinder-perms { left:7px; } +.elfinder-ltr .elfinder-cwd-view-list .elfinder-lock { left:9px; top:0px; } +.elfinder-ltr .elfinder-cwd-view-list .elfinder-symlink { left:-7px; } + +/* file icon */ +.elfinder-cwd-view-list td .elfinder-cwd-icon { + width:16px; + height:16px; + position:absolute; + top:50%; + margin-top:-8px; + background-image:url(../img/icons-small.png); +} +/* icon in ltr/rtl enviroment */ +.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-icon { left:0; } +.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-icon { right:0; } + + + +/* File: /home/osc/elFinder-build/elFinder/css/dialog.css */ +/*********************************************/ +/* DIALOGS STYLES */ +/*********************************************/ + +/* common dialogs class */ +.std42-dialog { + padding:0; + position:absolute; + left:auto; + right:auto; +} + +/* titlebar */ +.std42-dialog .ui-dialog-titlebar { + border-left:0 solid transparent; + border-top:0 solid transparent; + border-right:0 solid transparent; + -moz-border-radius-bottomleft: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + font-weight:normal; + padding:.2em 1em; +} + +.std42-dialog .ui-dialog-titlebar-close, +.std42-dialog .ui-dialog-titlebar-close:hover { padding:1px; } + +.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar { text-align:right; } +.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close { right:auto; left:.3em; } + +/* content */ +.std42-dialog .ui-dialog-content { + padding:.3em .5em; +} + +/* buttons */ +.std42-dialog .ui-dialog-buttonpane { + border:0 solid; + margin:0; + padding:.5em .7em; +} + +.std42-dialog .ui-dialog-buttonpane button { margin:0 0 0 .4em; padding:0; outline:0px solid; } +.std42-dialog .ui-dialog-buttonpane button span { padding:2px 9px; } + +.elfinder-dialog .ui-resizable-e, +.elfinder-dialog .ui-resizable-s { width:0; height:0;} + +.std42-dialog .ui-button input { cursor: pointer;} + +/* error/notify/confirm dialogs icon */ +.elfinder-dialog-icon { + position:absolute; + width:32px; + height:32px; + left:12px; + top:50%; + margin-top:-15px; + background:url("../img/dialogs.png") 0 0 no-repeat; +} + +.elfinder-rtl .elfinder-dialog-icon { left:auto; right:12px;} + + + +/*********************** ERROR DIALOG **************************/ + +.elfinder-dialog-error .ui-dialog-content, +.elfinder-dialog-confirm .ui-dialog-content { padding-left: 56px; min-height:35px; } + +.elfinder-rtl .elfinder-dialog-error .ui-dialog-content, +.elfinder-rtl .elfinder-dialog-confirm .ui-dialog-content { padding-left:0; padding-right: 56px; } + +/*********************** NOTIFY DIALOG **************************/ + +.elfinder-dialog-notify .ui-dialog-titlebar-close { display:none; } +.elfinder-dialog-notify .ui-dialog-content { padding:0; } + +/* one notification container */ +.elfinder-notify { + border-bottom:1px solid #ccc; + position:relative; + padding:.5em; + + text-align:center; + overflow:hidden; +} + +.elfinder-ltr .elfinder-notify { padding-left:30px; } +.elfinder-rtl .elfinder-notify { padding-right:30px; } + +.elfinder-notify:last-child { border:0 solid; } + +/* progressbar */ +.elfinder-notify-progressbar { + width:180px; + height:8px; + border:1px solid #aaa; + background:#f5f5f5; + margin:5px auto; + overflow:hidden; +} + +.elfinder-notify-progress { + width:100%; + height:8px; + background:url(../img/progress.gif) center center repeat-x; +} + +.elfinder-notify-progressbar, .elfinder-notify-progress { + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; +} + +/* icons */ +.elfinder-dialog-icon-open, +.elfinder-dialog-icon-file { background-position: 0 -225px; } +.elfinder-dialog-icon-reload { background-position: 0 -225px; } +.elfinder-dialog-icon-mkdir { background-position: 0 -64px; } +.elfinder-dialog-icon-mkfile { background-position: 0 -96px; } +.elfinder-dialog-icon-copy, +.elfinder-dialog-icon-prepare, +.elfinder-dialog-icon-move { background-position: 0 -128px;} +.elfinder-dialog-icon-upload { background-position: 0 -160px; } +.elfinder-dialog-icon-chunkmerge { background-position: 0 -160px; } +.elfinder-dialog-icon-rm { background-position: 0 -192px; } +.elfinder-dialog-icon-download { background-position: 0 -260px; } +.elfinder-dialog-icon-save { background-position: 0 -295px; } +.elfinder-dialog-icon-rename { background-position: 0 -330px; } +.elfinder-dialog-icon-archive, +.elfinder-dialog-icon-extract { background-position: 0 -365px; } +.elfinder-dialog-icon-search { background-position: 0 -402px; } +.elfinder-dialog-icon-resize, +.elfinder-dialog-icon-loadimg, +.elfinder-dialog-icon-netmount, +.elfinder-dialog-icon-netunmount, +.elfinder-dialog-icon-dim { background-position: 0 -434px; } + +/*********************** CONFIRM DIALOG **************************/ + +.elfinder-dialog-confirm-applyall { padding-top:3px; } + +.elfinder-dialog-confirm .elfinder-dialog-icon { background-position:0 -32px; } + + + +/*********************** FILE INFO DIALOG **************************/ + + +.elfinder-info-title .elfinder-cwd-icon { + float:left; + width:48px; + height:48px; + margin-right:1em; +} + +.elfinder-info-title strong { display:block; padding:.3em 0 .5em 0; } + +.elfinder-info-tb { + min-width:200px; + border:0 solid; + margin:1em .2em 1em .2em; +} + +.elfinder-info-tb td { white-space:nowrap; padding:2px; } + +.elfinder-info-tb tr td:first-child { text-align:right; } + +.elfinder-info-tb span { float:left;} +.elfinder-info-tb a { outline: none; text-decoration:underline; } +.elfinder-info-tb a:hover { text-decoration:none; } +.elfinder-info-spinner { + width:14px; + height:14px; + float:left; + background: url("../img/spinner-mini.gif") center center no-repeat; + margin:0 5px; +} + +.elfinder-netmount-tb { margin:0 auto; } +.elfinder-netmount-tb input { border:1px solid #ccc; } +/*********************** UPLOAD DIALOG **************************/ + +.elfinder-upload-dropbox { + text-align:center; + padding:2em 0; + border:3px dashed #aaa; + height: 1em; + overflow: hidden; +} + +.elfinder-upload-dropbox.ui-state-hover { + background:#dfdfdf; + border:3px dashed #555; +} + +.elfinder-upload-dialog-or { + margin:.3em 0; + text-align:center; +} + +.elfinder-upload-dialog-wrapper { text-align:center; } + +.elfinder-upload-dialog-wrapper .ui-button { position:relative; overflow:hidden; } + +.elfinder-upload-dialog-wrapper .ui-button form { + position:absolute; + right:0; + top:0; + opacity: 0; filter:Alpha(Opacity=0); +} + +.elfinder-upload-dialog-wrapper .ui-button form input { + padding:0 20px; + font-size:3em; + +} + + +/* dialog for elFinder itself */ +.dialogelfinder .dialogelfinder-drag { + border-left:0 solid; + border-top:0 solid; + border-right:0 solid; + font-weight:normal; + padding:2px 12px; + cursor:move; + position:relative; + text-align:left; +} + +.elfinder-rtl .dialogelfinder-drag { text-align:right;} + +.dialogelfinder-drag-close { + position: absolute; + top:50%; + margin-top:-8px; +} + +.elfinder-ltr .dialogelfinder-drag-close { right:12px; } +.elfinder-rtl .dialogelfinder-drag-close { left:12px; } + + + +/* File: /home/osc/elFinder-build/elFinder/css/fonts.css */ +.elfinder-contextmenu .elfinder-contextmenu-item span { font-size:.76em; } + +.elfinder-cwd-view-icons .elfinder-cwd-filename { font-size:.7em; } +.elfinder-cwd-view-list td { font-size:.7em; } + +.std42-dialog .ui-dialog-titlebar { font-size:.82em; } +.std42-dialog .ui-dialog-content { font-size:.72em; } +.std42-dialog .ui-dialog-buttonpane { font-size:.76em; } +.elfinder-info-tb { font-size:.9em; } +.elfinder-upload-dropbox { font-size:1.2em; } +.elfinder-upload-dialog-or { font-size:1.2em; } +.dialogelfinder .dialogelfinder-drag { font-size:.9em; } +.elfinder .elfinder-navbar { font-size:.72em; } +.elfinder-place-drag .elfinder-navbar-dir { font-size:.9em;} +.elfinder-quicklook-title { font-size:.7em; } +.elfinder-quicklook-info-data { font-size:.72em; } +.elfinder-quicklook-preview-text-wrapper { font-size:.9em; } +.elfinder-button-menu-item { font-size:.72em; } +.elfinder-button-search input { font-size:.8em; } +.elfinder-statusbar div { font-size:.7em; } +.elfinder-drag-num { font-size:12px; } + + +/* File: /home/osc/elFinder-build/elFinder/css/navbar.css */ +/*********************************************/ +/* NAVIGATION PANEL */ +/*********************************************/ + +/* container */ +.elfinder .elfinder-navbar { + width:230px; + padding:3px 5px; + background-image:none; + border-top:0 solid; + border-bottom:0 solid; + overflow:auto; + display:none; + position:relative; + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + user-select: none; + -webkit-tap-highlight-color:rgba(0,0,0,0); +/* border:1px solid #111;*/ +} + + +/* ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar { float:left; border-left:0 solid; } +.elfinder-rtl .elfinder-navbar { float:right; border-right:0 solid; } +.elfinder-ltr .ui-resizable-e { margin-left:10px; } + +/* folders tree container */ +.elfinder-tree { + display:table; width:100%; margin: 0 0 .5em 0; + -webkit-tap-highlight-color:rgba(0,0,0,0); +} + +/* one folder wrapper */ +.elfinder-navbar-wrapper, .elfinder-place-wrapper { } + +/* folder */ +.elfinder-navbar-dir { + position:relative; + display:block; + white-space:nowrap; + padding:3px 12px; + margin: 0; + outline:0px solid; + border:1px solid transparent; + cursor:default; + +} + +/* ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar-dir { padding-left:35px; } +.elfinder-rtl .elfinder-navbar-dir { padding-right:35px; } + +/* arrow before icon */ +.elfinder-navbar-arrow { + width:12px; + height:14px; + position:absolute; + display:none; + top:50%; + margin-top:-8px; + background-image:url("../img/arrows-normal.png"); + background-repeat:no-repeat; +/* border:1px solid #111;*/ +} + +.ui-state-active .elfinder-navbar-arrow { background-image:url("../img/arrows-active.png"); } + +/* collapsed/expanded arrow view */ +.elfinder-navbar-collapsed .elfinder-navbar-arrow { display:block; } + +/* arrow ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar-collapsed .elfinder-navbar-arrow { background-position: 0 4px; left:0; } +.elfinder-rtl .elfinder-navbar-collapsed .elfinder-navbar-arrow { background-position: 0 -10px; right:0; } +.elfinder-ltr .elfinder-navbar-expanded .elfinder-navbar-arrow, +.elfinder-rtl .elfinder-navbar-expanded .elfinder-navbar-arrow { background-position:0 -21px; } + + +/* folder icon */ +.elfinder-navbar-icon { + width:16px; + height:16px; + position:absolute; + top:50%; + margin-top:-8px; + background-image:url("../img/toolbar.png"); + background-repeat:no-repeat; + background-position:0 -16px; +} + +/* ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar-icon { left:14px; } +.elfinder-rtl .elfinder-navbar-icon { right:14px; } + +/* root folder */ +.elfinder-tree .elfinder-navbar-root .elfinder-navbar-icon { background-position:0 0; } +.elfinder-places .elfinder-navbar-root .elfinder-navbar-icon { background-position:0 -48px; } + +/* icon in active/hove/dropactive state */ +.ui-state-active .elfinder-navbar-icon, +.elfinder-droppable-active .elfinder-navbar-icon, +.ui-state-hover .elfinder-navbar-icon { background-position:0 -32px; } + +/* subdirs tree */ +.elfinder-navbar-subtree { display:none; } + +/* ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar-subtree { margin-left:12px; } +.elfinder-rtl .elfinder-navbar-subtree { margin-right:12px; } + + +/* spinner */ +.elfinder-navbar-spinner { + width:14px; + height:14px; + position:absolute; + display:block; + top:50%; + margin-top:-7px; + background: url("../img/spinner-mini.gif") center center no-repeat; +} +/* spinner ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar-spinner { left:0; margin-left:-2px; } +.elfinder-rtl .elfinder-navbar-spinner { right:0; margin-right:-2px; } + +/* permissions marker */ +.elfinder-navbar .elfinder-perms { top:50%; margin-top:-8px; } + +/* locked marker */ +.elfinder-navbar .elfinder-lock { top:-2px; } + +/* permissions/symlink markers ltr/rtl enviroment */ +.elfinder-ltr .elfinder-navbar .elfinder-perms { left: 18px; } +.elfinder-rtl .elfinder-navbar .elfinder-perms { right: 18px; } +.elfinder-ltr .elfinder-navbar .elfinder-lock { left: 18px; } +.elfinder-rtl .elfinder-navbar .elfinder-lock { right: 18px; } +.elfinder-ltr .elfinder-navbar .elfinder-symlink { left: 8px; } +.elfinder-rtl .elfinder-navbar .elfinder-symlink { right: 8px; } + +/* resizable */ +.elfinder-navbar .ui-resizable-handle { width:12px; background:transparent url('../img/resize.png') center center no-repeat; } +.elfinder-nav-handle-icon { + position:absolute; + top:50%; + margin:-8px 2px 0 2px; + opacity: .5; filter:Alpha(Opacity=50); +} + +.elfinder-places { border:1px solid transparent;} +.elfinder-places.elfinder-droppable-active { + border:1px solid #8cafed; +} + + + + + + + +/* File: /home/osc/elFinder-build/elFinder/css/places.css */ + +/* File: /home/osc/elFinder-build/elFinder/css/quicklook.css */ +/* quicklook window */ +.elfinder-quicklook { + position:absolute; + background:url("../img/quicklook-bg.png"); + display:none; + overflow:hidden; + border-radius:7px; + -moz-border-radius:7px; + -webkit-border-radius:7px; + padding:20px 0 40px 0; +} + +.elfinder-quicklook .ui-resizable-se { + width:14px; + height:14px; + right:5px; + bottom:3px; + background:url("../img/toolbar.png") 0 -496px no-repeat;} + +/* quicklook fullscreen window */ +.elfinder-quicklook-fullscreen { + border-radius:0; + -moz-border-radius:0; + -webkit-border-radius:0; + -webkit-background-clip: padding-box; +/* background-clip:padding-box;*/ + padding:0; + background:#000; + z-index:90000; + display:block; +} +/* hide titlebar in fullscreen mode */ +.elfinder-quicklook-fullscreen .elfinder-quicklook-titlebar { display:none; } + +/* hide preview border in fullscreen mode */ +.elfinder-quicklook-fullscreen .elfinder-quicklook-preview { border:0 solid ;} + +/* quicklook titlebar */ +.elfinder-quicklook-titlebar { + text-align:center; + background:#777; + position:absolute; + left:0; + top:0; + width:100%; + height:20px; + -moz-border-radius-topleft: 7px; + -webkit-border-top-left-radius: 7px; + border-top-left-radius: 7px; + -moz-border-radius-topright: 7px; + -webkit-border-top-right-radius: 7px; + border-top-right-radius: 7px; + cursor:move; +} + +/* window title */ +.elfinder-quicklook-title { + color:#fff; + white-space:nowrap; + overflow:hidden; + padding:2px 0; +} + +/* icon "close" in titlebar */ +.elfinder-quicklook-titlebar .ui-icon { + position:absolute; + left : 4px; + top:50%; + margin-top:-8px; + width:16px; + height:16px; + cursor:default; +} + +/* main part of quicklook window */ +.elfinder-quicklook-preview { + overflow:hidden; + position:relative; + border:0 solid; + border-left:1px solid transparent; + border-right:1px solid transparent; + height:100%; +} + +/* wrapper for file info/icon */ +.elfinder-quicklook-info-wrapper { + position:absolute; + width:100%; + left:0; + top:50%; + margin-top:-50px; +} + +/* file info */ +.elfinder-quicklook-info { + padding: 0 12px 0 112px; +} + +/* file name in info */ +.elfinder-quicklook-info .elfinder-quicklook-info-data:first-child { + color:#fff; + font-weight:bold; + padding-bottom:.5em; +} + +/* other data in info */ +.elfinder-quicklook-info-data { + padding-bottom:.2em; + color:#fff; +} + + +/* file icon */ +.elfinder-quicklook .elfinder-cwd-icon { + position:absolute; + left:32px; + top:50%; + margin-top:-20px; +} + +/* image in preview */ +.elfinder-quicklook-preview img { + display:block; + margin:0 auto; +} + +/* navigation bar on quicklook window bottom */ +.elfinder-quicklook-navbar { + position:absolute; + left:50%; + bottom:4px; + width:140px; + height:32px; + padding:0px; + margin-left:-70px; + border:1px solid transparent; + border-radius:19px; + -moz-border-radius:19px; + -webkit-border-radius:19px; +} + +/* navigation bar in fullscreen mode */ +.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar { + width:188px; + margin-left:-94px; + padding:5px; + border:1px solid #eee; + background:#000; +} + +/* show close icon in fullscreen mode */ +.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-icon-close, +.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-separator { + display:inline; +} + +/* icons in navbar */ +.elfinder-quicklook-navbar-icon { + width:32px; + height:32px; + margin:0 7px; + float:left; + background:url("../img/quicklook-icons.png") 0 0 no-repeat; + +} + +/* fullscreen icon */ +.elfinder-quicklook-navbar-icon-fullscreen { + background-position:0 -64px; +} + +/* exit fullscreen icon */ +.elfinder-quicklook-navbar-icon-fullscreen-off { + background-position:0 -96px; +} + +/* prev file icon */ +.elfinder-quicklook-navbar-icon-prev { + background-position:0 0; +} + +/* next file icon */ +.elfinder-quicklook-navbar-icon-next { + background-position:0 -32px; +} + +/* close icon */ +.elfinder-quicklook-navbar-icon-close { + background-position:0 -128px; + display:none; +} + +/* icons separator */ +.elfinder-quicklook-navbar-separator { + width:1px; + height:32px; + float:left; + border-left:1px solid #fff; + display:none; +} + +/* text files preview wrapper */ +.elfinder-quicklook-preview-text-wrapper { + width: 100%; + height:100%; + background:#fff; + color:#222; + overflow:auto; +} + +/* text preview */ +pre.elfinder-quicklook-preview-text { + margin:0; + padding:3px 9px; +} + +/* html/pdf preview */ +.elfinder-quicklook-preview-html, +.elfinder-quicklook-preview-pdf { + width:100%; + height:100%; + background:#fff; + border:0 solid; + margin:0; +} + +/* swf preview container */ +.elfinder-quicklook-preview-flash { + width:100%; + height:100%; +} + +/* audio preview container */ +.elfinder-quicklook-preview-audio { + width:100%; + position:absolute; + bottom:0; + left:0; +} + +/* audio preview using embed */ +embed.elfinder-quicklook-preview-audio { + height:30px; + background:transparent; +} + +/* video preview container */ +.elfinder-quicklook-preview-video { + width:100%; + height:100%; +} + + + + + + + + + + + + + + +/* File: /home/osc/elFinder-build/elFinder/css/statusbar.css */ +/******************************************************************/ +/* STATUSBAR STYLES */ +/******************************************************************/ + + +/* statusbar container */ +.elfinder-statusbar { + text-align:center; + font-weight:normal; + padding:.2em .5em; + + border-right:0 solid transparent; + border-bottom:0 solid transparent; + border-left:0 solid transparent; +} + +.elfinder-statusbar a { text-decoration:none; } + + + +/* path in statusbar */ +.elfinder-path { + max-width:30%; + white-space:nowrap; + overflow:hidden; + text-overflow:ellipsis; + -o-text-overflow:ellipsis; +} +.elfinder-ltr .elfinder-path { float:left; } +.elfinder-rtl .elfinder-path { float:right; } + +/* total/selected size in statusbar */ +.elfinder-stat-size { white-space:nowrap; } +.elfinder-ltr .elfinder-stat-size { float:right; } +.elfinder-rtl .elfinder-stat-size { float:left; } + +.elfinder-stat-selected { white-space:nowrap; overflow:hidden; } + +/* File: /home/osc/elFinder-build/elFinder/css/toolbar.css */ +/*********************************************/ +/* TOOLBAR STYLES */ +/*********************************************/ +/* toolbar container */ +.elfinder-toolbar { + padding:4px 0 3px 0; + border-left:0 solid transparent; + border-top:0 solid transparent; + border-right:0 solid transparent; +} + +/* container for button's group */ +.elfinder-buttonset { + margin: 1px 4px; + float:left; + background:transparent; + padding:0; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; +} + +/*.elfinder-buttonset:first-child { margin:0; }*/ + +/* button */ +.elfinder .elfinder-button { + width:16px; + height:16px; + margin:0; + padding:4px; + float:left; + overflow:hidden; + position:relative; + border:0 solid; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +.elfinder .ui-icon-search { cursor:pointer;} + +.elfinder-button:first-child { + -moz-border-radius-topleft: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} + +.elfinder-button:last-child { + -moz-border-radius-topright: 4px; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +/* separator between buttons, required for berder between button with ui color */ +.elfinder-toolbar-button-separator { + float:left; + padding:0; + height:24px; + border-top:0 solid; + border-right:0 solid; + border-bottom:0 solid; + width:0; +} + +/* change icon opacity^ not button */ +.elfinder .elfinder-button.ui-state-disabled { opacity:1; filter:Alpha(Opacity=100);} +.elfinder .elfinder-button.ui-state-disabled .elfinder-button-icon { opacity:.4; filter:Alpha(Opacity=40);} + +/* rtl enviroment */ +.elfinder-rtl .elfinder-buttonset { float:right; } + +/* icon inside button */ +.elfinder-button-icon { + width:16px; + height:16px; + display:block; + background:url('../img/toolbar.png') no-repeat; +} + +/* buttons icons */ +.elfinder-button-icon-home { background-position: 0 0; } +.elfinder-button-icon-back { background-position: 0 -112px; } +.elfinder-button-icon-forward { background-position: 0 -128px; } +.elfinder-button-icon-up { background-position: 0 -144px; } +.elfinder-button-icon-reload { background-position: 0 -160px; } +.elfinder-button-icon-open { background-position: 0 -176px; } +.elfinder-button-icon-mkdir { background-position: 0 -192px; } +.elfinder-button-icon-mkfile { background-position: 0 -208px; } +.elfinder-button-icon-rm { background-position: 0 -224px; } +.elfinder-button-icon-copy { background-position: 0 -240px; } +.elfinder-button-icon-cut { background-position: 0 -256px; } +.elfinder-button-icon-paste { background-position: 0 -272px; } +.elfinder-button-icon-getfile { background-position: 0 -288px; } +.elfinder-button-icon-duplicate { background-position: 0 -304px; } +.elfinder-button-icon-rename { background-position: 0 -320px; } +.elfinder-button-icon-edit { background-position: 0 -336px; } +.elfinder-button-icon-quicklook { background-position: 0 -352px; } +.elfinder-button-icon-upload { background-position: 0 -368px; } +.elfinder-button-icon-download { background-position: 0 -384px; } +.elfinder-button-icon-info { background-position: 0 -400px; } +.elfinder-button-icon-extract { background-position: 0 -416px; } +.elfinder-button-icon-archive { background-position: 0 -432px; } +.elfinder-button-icon-view { background-position: 0 -448px; } +.elfinder-button-icon-view-list { background-position: 0 -464px; } +.elfinder-button-icon-help { background-position: 0 -480px; } +.elfinder-button-icon-resize { background-position: 0 -512px; } +.elfinder-button-icon-search { background-position: 0 -561px; } +.elfinder-button-icon-sort { background-position: 0 -577px; } +.elfinder-button-icon-rotate-r { background-position: 0 -625px; } +.elfinder-button-icon-rotate-l { background-position: 0 -641px; } +.elfinder-button-icon-netmount { background-position: 0 -688px; } +.elfinder-button-icon-netunmount { background-position: 0 -96px; } + +/* button with dropdown menu*/ +.elfinder .elfinder-menubutton { overflow:visible; } + + + +/* menu */ +.elfinder-button-menu { + position:absolute; + left:0; + top:25px; + padding:3px 0; +} + +/* menu item */ +.elfinder-button-menu-item { + white-space:nowrap; + cursor:default; + padding:5px 19px; + position:relative; +} + +/* fix hover ui class */ +.elfinder-button-menu .ui-state-hover { border:0 solid; } + +.elfinder-button-menu-item-separated { border-top:1px solid #ccc; } + +.elfinder-button-menu-item .ui-icon { + width:16px; + height:16px; + position:absolute; + left:2px; + top:50%; + margin-top:-8px; + display:none; +} + +.elfinder-button-menu-item-selected .ui-icon { display:block; } +.elfinder-button-menu-item-selected-asc .ui-icon-arrowthick-1-n { display:none; } +.elfinder-button-menu-item-selected-desc .ui-icon-arrowthick-1-s { display:none; } + +/* hack for upload button */ +.elfinder-button form { + position:absolute; + top:0; + right:0; + opacity: 0; filter:Alpha(Opacity=0); + cursor: pointer; +} + +.elfinder .elfinder-button form input { background:transparent; cursor: default;} + +/* search "button" */ +.elfinder .elfinder-button-search { + border:0 solid; + background:transparent; + padding:0; + margin: 1px 4px; + height: auto; + min-height: 26px; + float:right; + width:202px; +} + +/* ltr/rte enviroment */ +.elfinder-ltr .elfinder-button-search { float:right; margin-right:10px; } +.elfinder-rtl .elfinder-button-search { float:left; margin-left:10px; } + +/* search text field */ +.elfinder-button-search input { + width:160px; + height:22px; + padding:0 20px; + line-height: 22px; + border:0 solid; + border:1px solid #aaa; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + outline:0px solid; +} + +.elfinder-rtl .elfinder-button-search input { direction:rtl; } + +/* icons */ +.elfinder-button-search .ui-icon { + position:absolute; + height:18px; + top: 50%; + margin:-9px 4px 0 4px; + opacity: .6; + filter:Alpha(Opacity=60); +} + +/* search/close icons */ +.elfinder-ltr .elfinder-button-search .ui-icon-search { left:0;} +.elfinder-rtl .elfinder-button-search .ui-icon-search { right:0;} +.elfinder-ltr .elfinder-button-search .ui-icon-close { right:0;} +.elfinder-rtl .elfinder-button-search .ui-icon-close { left:0;} + + + + + + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.min.css b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.min.css new file mode 100644 index 00000000..42ab8fab --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/elfinder.min.css @@ -0,0 +1,9 @@ +/*! + * elFinder - file manager for web + * Version 2.1 (Nightly: 595cc96) (2014-04-24) + * http://elfinder.org + * + * Copyright 2009-2013, Studio 42 + * Licensed under a 3 clauses BSD license + */ +.elfinder-dialog-resize{margin-top:.3em}.elfinder-resize-type{float:left;margin-bottom:.4em}.elfinder-resize-control{padding-top:3em}.elfinder-resize-control input[type=text]{border:1px solid #aaa;text-align:right}.elfinder-resize-preview{width:400px;height:400px;padding:10px;background:#fff;border:1px solid #aaa;float:right;position:relative;overflow:auto}.elfinder-resize-handle{position:relative}.elfinder-resize-handle-hline,.elfinder-resize-handle-vline{position:absolute;background-image:url("../img/crop.gif")}.elfinder-resize-handle-hline{width:100%;height:1px!important;background-repeat:repeat-x}.elfinder-resize-handle-vline{width:1px!important;height:100%;background-repeat:repeat-y}.elfinder-resize-handle-hline-top{top:0;left:0}.elfinder-resize-handle-hline-bottom{bottom:0;left:0}.elfinder-resize-handle-vline-left{top:0;left:0}.elfinder-resize-handle-vline-right{top:0;right:0}.elfinder-resize-handle-point{position:absolute;width:8px;height:8px;border:1px solid #777;background:0 0}.elfinder-resize-handle-point-n{top:0;left:50%;margin-top:-5px;margin-left:-5px}.elfinder-resize-handle-point-ne{top:0;right:0;margin-top:-5px;margin-right:-5px}.elfinder-resize-handle-point-e{top:50%;right:0;margin-top:-5px;margin-right:-5px}.elfinder-resize-handle-point-se{bottom:0;right:0;margin-bottom:-5px;margin-right:-5px}.elfinder-resize-handle-point-s{bottom:0;left:50%;margin-bottom:-5px;margin-left:-5px}.elfinder-resize-handle-point-sw{bottom:0;left:0;margin-bottom:-5px;margin-left:-5px}.elfinder-resize-handle-point-w{top:50%;left:0;margin-top:-5px;margin-left:-5px}.elfinder-resize-handle-point-nw{top:0;left:0;margin-top:-5px;margin-left:-5px}.elfinder-resize-spinner{position:absolute;width:200px;height:30px;top:50%;margin-top:-25px;left:50%;margin-left:-100px;text-align:center;background:url(../img/progress.gif) center bottom repeat-x}.elfinder-resize-row{margin-bottom:7px;position:relative}.elfinder-resize-label{float:left;width:80px;padding-top:3px}.elfinder-resize-reset{width:16px;height:16px;position:absolute;margin-top:-8px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-e{height:100%;width:10px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-s{width:100%;height:10px}.elfinder-dialog .elfinder-dialog-resize .ui-resizable-se{background:0 0;bottom:0;right:0;margin-right:-7px;margin-bottom:-7px}.elfinder-dialog-resize .ui-icon-grip-solid-vertical{position:absolute;top:50%;right:0;margin-top:-8px;margin-right:-11px}.elfinder-dialog-resize .ui-icon-grip-solid-horizontal{position:absolute;left:50%;bottom:0;margin-left:-8px;margin-bottom:-11px}.elfinder-resize-row .elfinder-buttonset{float:right}.elfinder-resize-rotate-slider{float:left;width:195px;margin:7px 7px 0}.elfinder-file-edit{width:99%;height:99%;margin:0;padding:2px;border:1px solid #ccc}.elfinder-help{margin-bottom:.5em}.elfinder-help .ui-tabs-panel{padding:.5em}.elfinder-dialog .ui-tabs .ui-tabs-nav li a{padding:.2em 1em}.elfinder-help-shortcuts{height:300px;padding:1em;margin:.5em 0;overflow:auto}.elfinder-help-shortcut{white-space:nowrap;clear:both}.elfinder-help-shortcut-pattern{float:left;width:160px}.elfinder-help-logo{width:100px;height:96px;float:left;margin-right:1em;background:url('../img/logo.png') center center no-repeat}.elfinder-help h3{font-size:1.5em;margin:.2em 0 .3em}.elfinder-help-separator{clear:both;padding:.5em}.elfinder-help-link{padding:2px}.elfinder-help .ui-priority-secondary{font-size:.9em}.elfinder-help .ui-priority-primary{margin-bottom:7px}.elfinder-help-team{clear:both;text-align:right;border-bottom:1px solid #ccc;margin:.5em 0;font-size:.9em}.elfinder-help-team div{float:left}.elfinder-help-license{font-size:.9em}.elfinder-help-disabled{font-weight:700;text-align:center;margin:90px 0}.elfinder-help .elfinder-dont-panic{display:block;border:1px solid transparent;width:200px;height:200px;margin:30px auto;text-decoration:none;text-align:center;position:relative;background:#d90004;-moz-box-shadow:5px 5px 9px #111;-webkit-box-shadow:5px 5px 9px #111;box-shadow:5px 5px 9px #111;background:-moz-radial-gradient(80px 80px,circle farthest-corner,#d90004 35%,#960004 100%);background:-webkit-gradient(radial,80 80,60,80 80,120,from(#d90004),to(#960004));-moz-border-radius:100px;-webkit-border-radius:100px;border-radius:100px;outline:none}.elfinder-help .elfinder-dont-panic span{font-size:3em;font-weight:700;text-align:center;color:#fff;position:absolute;left:0;top:45px}.elfinder{padding:0;position:relative;display:block}.elfinder-rtl{text-align:right;direction:rtl}.elfinder-workzone{padding:0;position:relative;overflow:hidden}.elfinder-lock,.elfinder-perms,.elfinder-symlink{position:absolute;width:16px;height:16px;background-image:url(../img/toolbar.png);background-repeat:no-repeat;background-position:0 -528px}.elfinder-na .elfinder-perms{background-position:0 -96px}.elfinder-ro .elfinder-perms{background-position:0 -64px}.elfinder-wo .elfinder-perms{background-position:0 -80px}.elfinder-lock{background-position:0 -656px}.elfinder-drag-helper{width:60px;height:50px;padding:0 0 0 25px;z-index:100000}.elfinder-drag-helper-icon-plus{position:absolute;width:16px;height:16px;left:43px;top:55px;background:url('../img/toolbar.png') 0 -544px no-repeat;display:none}.elfinder-drag-helper-plus .elfinder-drag-helper-icon-plus{display:block}.elfinder-drag-num{position:absolute;top:0;left:0;width:16px;height:14px;text-align:center;padding-top:2px;font-weight:700;color:#fff;background-color:red;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.elfinder-drag-helper .elfinder-cwd-icon{margin:0 0 0 -24px;float:left}.elfinder-overlay{opacity:0;filter:Alpha(Opacity=0)}.elfinder .elfinder-panel{position:relative;background-image:none;padding:7px 12px}.elfinder-contextmenu,.elfinder-contextmenu-sub{display:none;position:absolute;border:1px solid #aaa;background:#fff;color:#555;padding:4px 0}.elfinder-contextmenu-sub{top:5px}.elfinder-contextmenu-ltr .elfinder-contextmenu-sub{margin-left:-5px}.elfinder-contextmenu-rtl .elfinder-contextmenu-sub{margin-right:-5px}.elfinder-contextmenu-item{position:relative;display:block;padding:4px 30px;text-decoration:none;white-space:nowrap;cursor:default}.elfinder-contextmenu .elfinder-contextmenu-item span{display:block}.elfinder-contextmenu-ltr .elfinder-contextmenu-item{text-align:left}.elfinder-contextmenu-rtl .elfinder-contextmenu-item{text-align:right}.elfinder-contextmenu-ltr .elfinder-contextmenu-sub .elfinder-contextmenu-item{padding-left:12px}.elfinder-contextmenu-rtl .elfinder-contextmenu-sub .elfinder-contextmenu-item{padding-right:12px}.elfinder-contextmenu-arrow,.elfinder-contextmenu-icon{position:absolute;top:50%;margin-top:-8px}.elfinder-contextmenu-ltr .elfinder-contextmenu-icon{left:8px}.elfinder-contextmenu-rtl .elfinder-contextmenu-icon{right:8px}.elfinder-contextmenu-arrow{width:16px;height:16px;background:url('../img/arrows-normal.png') 5px 4px no-repeat}.elfinder-contextmenu-ltr .elfinder-contextmenu-arrow{right:5px}.elfinder-contextmenu-rtl .elfinder-contextmenu-arrow{left:5px;background-position:0 -10px}.elfinder-contextmenu .ui-state-hover{border:0 solid;background-image:none}.elfinder-contextmenu-separator{height:0;border-top:1px solid #ccc;margin:0 1px}.elfinder-cwd-wrapper{overflow:auto;position:relative;padding:2px;margin:0}.elfinder-cwd-wrapper-list{padding:0}.elfinder-cwd{position:relative;cursor:default;padding:0;margin:0;-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.elfinder .elfinder-cwd-wrapper.elfinder-droppable-active{padding:0;border:2px solid #8cafed}.elfinder-cwd-view-icons .elfinder-cwd-file{width:120px;height:80px;padding-bottom:2px;cursor:default;border:none}.elfinder-ltr .elfinder-cwd-view-icons .elfinder-cwd-file{float:left;margin:0 3px 12px 0}.elfinder-rtl .elfinder-cwd-view-icons .elfinder-cwd-file{float:right;margin:0 0 5px 3px}.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover{border:0 solid}.elfinder-cwd-view-icons .elfinder-cwd-file-wrapper{width:52px;height:52px;margin:1px auto;padding:2px;position:relative}.elfinder-cwd-view-icons .elfinder-cwd-filename{text-align:center;white-space:pre;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis;margin:3px 1px 0;padding:1px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.elfinder-cwd-view-icons .elfinder-perms{bottom:4px;right:2px}.elfinder-cwd-view-icons .elfinder-lock{top:-3px;right:-2px}.elfinder-cwd-view-icons .elfinder-symlink{bottom:6px;left:0}.elfinder-cwd-icon{display:block;width:48px;height:48px;margin:0 auto;background:url('../img/icons-big.png') 0 0 no-repeat;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}.elfinder-cwd .elfinder-droppable-active .elfinder-cwd-icon{background-position:0 -100px}.elfinder-cwd-icon-directory{background-position:0 -50px}.elfinder-cwd-icon-application{background-position:0 -150px}.elfinder-cwd-icon-x-empty,.elfinder-cwd-icon-text{background-position:0 -200px}.elfinder-cwd-icon-image,.elfinder-cwd-icon-vnd-adobe-photoshop,.elfinder-cwd-icon-postscript{background-position:0 -250px}.elfinder-cwd-icon-audio{background-position:0 -300px}.elfinder-cwd-icon-video,.elfinder-cwd-icon-flash-video{background-position:0 -350px}.elfinder-cwd-icon-rtf,.elfinder-cwd-icon-rtfd{background-position:0 -401px}.elfinder-cwd-icon-pdf{background-position:0 -450px}.elfinder-cwd-icon-ms-excel,.elfinder-cwd-icon-msword,.elfinder-cwd-icon-vnd-ms-excel,.elfinder-cwd-icon-vnd-ms-excel-addin-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-excel-sheet-binary-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-excel-sheet-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-excel-template-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-office,.elfinder-cwd-icon-vnd-ms-powerpoint,.elfinder-cwd-icon-vnd-ms-powerpoint-addin-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-presentation-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-slide-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-slideshow-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-powerpoint-template-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-word,.elfinder-cwd-icon-vnd-ms-word-document-macroEnabled-12,.elfinder-cwd-icon-vnd-ms-word-template-macroEnabled-12,.elfinder-cwd-icon-vnd-oasis-opendocument-chart,.elfinder-cwd-icon-vnd-oasis-opendocument-database,.elfinder-cwd-icon-vnd-oasis-opendocument-formula,.elfinder-cwd-icon-vnd-oasis-opendocument-graphics,.elfinder-cwd-icon-vnd-oasis-opendocument-graphics-template,.elfinder-cwd-icon-vnd-oasis-opendocument-image,.elfinder-cwd-icon-vnd-oasis-opendocument-presentation,.elfinder-cwd-icon-vnd-oasis-opendocument-presentation-template,.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet,.elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet-template,.elfinder-cwd-icon-vnd-oasis-opendocument-text,.elfinder-cwd-icon-vnd-oasis-opendocument-text-master,.elfinder-cwd-icon-vnd-oasis-opendocument-text-template,.elfinder-cwd-icon-vnd-oasis-opendocument-text-web,.elfinder-cwd-icon-vnd-openofficeorg-extension,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-presentation,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slide,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slideshow,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-template,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-sheet,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-template,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-document,.elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-template{background-position:0 -500px}.elfinder-cwd-icon-html{background-position:0 -550px}.elfinder-cwd-icon-css{background-position:0 -600px}.elfinder-cwd-icon-javascript,.elfinder-cwd-icon-x-javascript{background-position:0 -650px}.elfinder-cwd-icon-x-perl{background-position:0 -700px}.elfinder-cwd-icon-x-python{background-position:0 -750px}.elfinder-cwd-icon-x-ruby{background-position:0 -800px}.elfinder-cwd-icon-x-sh,.elfinder-cwd-icon-x-shellscript{background-position:0 -850px}.elfinder-cwd-icon-x-c,.elfinder-cwd-icon-x-csrc,.elfinder-cwd-icon-x-chdr,.elfinder-cwd-icon-x-c--,.elfinder-cwd-icon-x-c--src,.elfinder-cwd-icon-x-c--hdr,.elfinder-cwd-icon-x-java,.elfinder-cwd-icon-x-java-source{background-position:0 -900px}.elfinder-cwd-icon-x-php{background-position:0 -950px}.elfinder-cwd-icon-xml{background-position:0 -1000px}.elfinder-cwd-icon-zip,.elfinder-cwd-icon-x-zip,.elfinder-cwd-icon-x-7z-compressed{background-position:0 -1050px}.elfinder-cwd-icon-x-gzip,.elfinder-cwd-icon-x-tar{background-position:0 -1100px}.elfinder-cwd-icon-x-bzip,.elfinder-cwd-icon-x-bzip2{background-position:0 -1150px}.elfinder-cwd-icon-x-rar,.elfinder-cwd-icon-x-rar-compressed{background-position:0 -1200px}.elfinder-cwd-icon-x-shockwave-flash{background-position:0 -1250px}.elfinder-cwd-icon-group{background-position:0 -1300px}.elfinder-cwd input{width:100%;border:0 solid;margin:0;padding:0}.elfinder-cwd-view-icons input,.elfinder-cwd-view-icons{text-align:center}.elfinder-cwd table{width:100%;border-collapse:collapse;border:0 solid;margin:0 0 10px}.elfinder .elfinder-cwd table thead tr{border-left:0 solid;border-top:0 solid;border-right:0 solid}.elfinder .elfinder-cwd table td{padding:3px 12px;white-space:pre;overflow:hidden;text-align:right;cursor:default;border:0 solid}.elfinder-ltr .elfinder-cwd table td{text-align:right}.elfinder-ltr .elfinder-cwd table td:first-child{text-align:left}.elfinder-rtl .elfinder-cwd table td{text-align:left}.elfinder-rtl .elfinder-cwd table td:first-child{text-align:right}.elfinder-odd-row{background:#eee}.elfinder-cwd-view-list .elfinder-cwd-file-wrapper{width:97%;position:relative}.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-file-wrapper{padding-left:23px}.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-file-wrapper{padding-right:23px}.elfinder-cwd-view-list .elfinder-perms,.elfinder-cwd-view-list .elfinder-lock,.elfinder-cwd-view-list .elfinder-symlink{top:50%;margin-top:-6px}.elfinder-ltr .elfinder-cwd-view-list .elfinder-perms{left:7px}.elfinder-ltr .elfinder-cwd-view-list .elfinder-lock{left:9px;top:0}.elfinder-ltr .elfinder-cwd-view-list .elfinder-symlink{left:-7px}.elfinder-cwd-view-list td .elfinder-cwd-icon{width:16px;height:16px;position:absolute;top:50%;margin-top:-8px;background-image:url(../img/icons-small.png)}.elfinder-ltr .elfinder-cwd-view-list .elfinder-cwd-icon{left:0}.elfinder-rtl .elfinder-cwd-view-list .elfinder-cwd-icon{right:0}.std42-dialog{padding:0;position:absolute;left:auto;right:auto}.std42-dialog .ui-dialog-titlebar{border-left:0 solid transparent;border-top:0 solid transparent;border-right:0 solid transparent;-moz-border-radius-bottomleft:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;font-weight:400;padding:.2em 1em}.std42-dialog .ui-dialog-titlebar-close,.std42-dialog .ui-dialog-titlebar-close:hover{padding:1px}.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar{text-align:right}.elfinder-rtl .elfinder-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close{right:auto;left:.3em}.std42-dialog .ui-dialog-content{padding:.3em .5em}.std42-dialog .ui-dialog-buttonpane{border:0 solid;margin:0;padding:.5em .7em}.std42-dialog .ui-dialog-buttonpane button{margin:0 0 0 .4em;padding:0;outline:0 solid}.std42-dialog .ui-dialog-buttonpane button span{padding:2px 9px}.elfinder-dialog .ui-resizable-e,.elfinder-dialog .ui-resizable-s{width:0;height:0}.std42-dialog .ui-button input{cursor:pointer}.elfinder-dialog-icon{position:absolute;width:32px;height:32px;left:12px;top:50%;margin-top:-15px;background:url("../img/dialogs.png") 0 0 no-repeat}.elfinder-rtl .elfinder-dialog-icon{left:auto;right:12px}.elfinder-dialog-error .ui-dialog-content,.elfinder-dialog-confirm .ui-dialog-content{padding-left:56px;min-height:35px}.elfinder-rtl .elfinder-dialog-error .ui-dialog-content,.elfinder-rtl .elfinder-dialog-confirm .ui-dialog-content{padding-left:0;padding-right:56px}.elfinder-dialog-notify .ui-dialog-titlebar-close{display:none}.elfinder-dialog-notify .ui-dialog-content{padding:0}.elfinder-notify{border-bottom:1px solid #ccc;position:relative;padding:.5em;text-align:center;overflow:hidden}.elfinder-ltr .elfinder-notify{padding-left:30px}.elfinder-rtl .elfinder-notify{padding-right:30px}.elfinder-notify:last-child{border:0 solid}.elfinder-notify-progressbar{width:180px;height:8px;border:1px solid #aaa;background:#f5f5f5;margin:5px auto;overflow:hidden}.elfinder-notify-progress{width:100%;height:8px;background:url(../img/progress.gif) center center repeat-x}.elfinder-notify-progressbar,.elfinder-notify-progress{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.elfinder-dialog-icon-open,.elfinder-dialog-icon-file,.elfinder-dialog-icon-reload{background-position:0 -225px}.elfinder-dialog-icon-mkdir{background-position:0 -64px}.elfinder-dialog-icon-mkfile{background-position:0 -96px}.elfinder-dialog-icon-copy,.elfinder-dialog-icon-prepare,.elfinder-dialog-icon-move{background-position:0 -128px}.elfinder-dialog-icon-upload,.elfinder-dialog-icon-chunkmerge{background-position:0 -160px}.elfinder-dialog-icon-rm{background-position:0 -192px}.elfinder-dialog-icon-download{background-position:0 -260px}.elfinder-dialog-icon-save{background-position:0 -295px}.elfinder-dialog-icon-rename{background-position:0 -330px}.elfinder-dialog-icon-archive,.elfinder-dialog-icon-extract{background-position:0 -365px}.elfinder-dialog-icon-search{background-position:0 -402px}.elfinder-dialog-icon-resize,.elfinder-dialog-icon-loadimg,.elfinder-dialog-icon-netmount,.elfinder-dialog-icon-netunmount,.elfinder-dialog-icon-dim{background-position:0 -434px}.elfinder-dialog-confirm-applyall{padding-top:3px}.elfinder-dialog-confirm .elfinder-dialog-icon{background-position:0 -32px}.elfinder-info-title .elfinder-cwd-icon{float:left;width:48px;height:48px;margin-right:1em}.elfinder-info-title strong{display:block;padding:.3em 0 .5em}.elfinder-info-tb{min-width:200px;border:0 solid;margin:1em .2em}.elfinder-info-tb td{white-space:nowrap;padding:2px}.elfinder-info-tb tr td:first-child{text-align:right}.elfinder-info-tb span{float:left}.elfinder-info-tb a{outline:none;text-decoration:underline}.elfinder-info-tb a:hover{text-decoration:none}.elfinder-info-spinner{width:14px;height:14px;float:left;background:url("../img/spinner-mini.gif") center center no-repeat;margin:0 5px}.elfinder-netmount-tb{margin:0 auto}.elfinder-netmount-tb input{border:1px solid #ccc}.elfinder-upload-dropbox{text-align:center;padding:2em 0;border:3px dashed #aaa;height:1em;overflow:hidden}.elfinder-upload-dropbox.ui-state-hover{background:#dfdfdf;border:3px dashed #555}.elfinder-upload-dialog-or{margin:.3em 0;text-align:center}.elfinder-upload-dialog-wrapper{text-align:center}.elfinder-upload-dialog-wrapper .ui-button{position:relative;overflow:hidden}.elfinder-upload-dialog-wrapper .ui-button form{position:absolute;right:0;top:0;opacity:0;filter:Alpha(Opacity=0)}.elfinder-upload-dialog-wrapper .ui-button form input{padding:0 20px;font-size:3em}.dialogelfinder .dialogelfinder-drag{border-left:0 solid;border-top:0 solid;border-right:0 solid;font-weight:400;padding:2px 12px;cursor:move;position:relative;text-align:left}.elfinder-rtl .dialogelfinder-drag{text-align:right}.dialogelfinder-drag-close{position:absolute;top:50%;margin-top:-8px}.elfinder-ltr .dialogelfinder-drag-close{right:12px}.elfinder-rtl .dialogelfinder-drag-close{left:12px}.elfinder-contextmenu .elfinder-contextmenu-item span{font-size:.76em}.elfinder-cwd-view-icons .elfinder-cwd-filename,.elfinder-cwd-view-list td{font-size:.7em}.std42-dialog .ui-dialog-titlebar{font-size:.82em}.std42-dialog .ui-dialog-content{font-size:.72em}.std42-dialog .ui-dialog-buttonpane{font-size:.76em}.elfinder-info-tb{font-size:.9em}.elfinder-upload-dropbox,.elfinder-upload-dialog-or{font-size:1.2em}.dialogelfinder .dialogelfinder-drag{font-size:.9em}.elfinder .elfinder-navbar{font-size:.72em}.elfinder-place-drag .elfinder-navbar-dir{font-size:.9em}.elfinder-quicklook-title{font-size:.7em}.elfinder-quicklook-info-data{font-size:.72em}.elfinder-quicklook-preview-text-wrapper{font-size:.9em}.elfinder-button-menu-item{font-size:.72em}.elfinder-button-search input{font-size:.8em}.elfinder-statusbar div{font-size:.7em}.elfinder-drag-num{font-size:12px}.elfinder .elfinder-navbar{width:230px;padding:3px 5px;background-image:none;border-top:0 solid;border-bottom:0 solid;overflow:auto;display:none;position:relative;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.elfinder-ltr .elfinder-navbar{float:left;border-left:0 solid}.elfinder-rtl .elfinder-navbar{float:right;border-right:0 solid}.elfinder-ltr .ui-resizable-e{margin-left:10px}.elfinder-tree{display:table;width:100%;margin:0 0 .5em;-webkit-tap-highlight-color:rgba(0,0,0,0)}.elfinder-navbar-dir{position:relative;display:block;white-space:nowrap;padding:3px 12px;margin:0;outline:0 solid;border:1px solid transparent;cursor:default}.elfinder-ltr .elfinder-navbar-dir{padding-left:35px}.elfinder-rtl .elfinder-navbar-dir{padding-right:35px}.elfinder-navbar-arrow{width:12px;height:14px;position:absolute;display:none;top:50%;margin-top:-8px;background-image:url("../img/arrows-normal.png");background-repeat:no-repeat}.ui-state-active .elfinder-navbar-arrow{background-image:url("../img/arrows-active.png")}.elfinder-navbar-collapsed .elfinder-navbar-arrow{display:block}.elfinder-ltr .elfinder-navbar-collapsed .elfinder-navbar-arrow{background-position:0 4px;left:0}.elfinder-rtl .elfinder-navbar-collapsed .elfinder-navbar-arrow{background-position:0 -10px;right:0}.elfinder-ltr .elfinder-navbar-expanded .elfinder-navbar-arrow,.elfinder-rtl .elfinder-navbar-expanded .elfinder-navbar-arrow{background-position:0 -21px}.elfinder-navbar-icon{width:16px;height:16px;position:absolute;top:50%;margin-top:-8px;background-image:url("../img/toolbar.png");background-repeat:no-repeat;background-position:0 -16px}.elfinder-ltr .elfinder-navbar-icon{left:14px}.elfinder-rtl .elfinder-navbar-icon{right:14px}.elfinder-tree .elfinder-navbar-root .elfinder-navbar-icon{background-position:0 0}.elfinder-places .elfinder-navbar-root .elfinder-navbar-icon{background-position:0 -48px}.ui-state-active .elfinder-navbar-icon,.elfinder-droppable-active .elfinder-navbar-icon,.ui-state-hover .elfinder-navbar-icon{background-position:0 -32px}.elfinder-navbar-subtree{display:none}.elfinder-ltr .elfinder-navbar-subtree{margin-left:12px}.elfinder-rtl .elfinder-navbar-subtree{margin-right:12px}.elfinder-navbar-spinner{width:14px;height:14px;position:absolute;display:block;top:50%;margin-top:-7px;background:url("../img/spinner-mini.gif") center center no-repeat}.elfinder-ltr .elfinder-navbar-spinner{left:0;margin-left:-2px}.elfinder-rtl .elfinder-navbar-spinner{right:0;margin-right:-2px}.elfinder-navbar .elfinder-perms{top:50%;margin-top:-8px}.elfinder-navbar .elfinder-lock{top:-2px}.elfinder-ltr .elfinder-navbar .elfinder-perms{left:18px}.elfinder-rtl .elfinder-navbar .elfinder-perms{right:18px}.elfinder-ltr .elfinder-navbar .elfinder-lock{left:18px}.elfinder-rtl .elfinder-navbar .elfinder-lock{right:18px}.elfinder-ltr .elfinder-navbar .elfinder-symlink{left:8px}.elfinder-rtl .elfinder-navbar .elfinder-symlink{right:8px}.elfinder-navbar .ui-resizable-handle{width:12px;background:url('../img/resize.png') center center no-repeat}.elfinder-nav-handle-icon{position:absolute;top:50%;margin:-8px 2px 0;opacity:.5;filter:Alpha(Opacity=50)}.elfinder-places{border:1px solid transparent}.elfinder-places.elfinder-droppable-active{border:1px solid #8cafed}.elfinder-quicklook{position:absolute;background:url("../img/quicklook-bg.png");display:none;overflow:hidden;border-radius:7px;-moz-border-radius:7px;-webkit-border-radius:7px;padding:20px 0 40px}.elfinder-quicklook .ui-resizable-se{width:14px;height:14px;right:5px;bottom:3px;background:url("../img/toolbar.png") 0 -496px no-repeat}.elfinder-quicklook-fullscreen{border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;-webkit-background-clip:padding-box;padding:0;background:#000;z-index:90000;display:block}.elfinder-quicklook-fullscreen .elfinder-quicklook-titlebar{display:none}.elfinder-quicklook-fullscreen .elfinder-quicklook-preview{border:0 solid}.elfinder-quicklook-titlebar{text-align:center;background:#777;position:absolute;left:0;top:0;width:100%;height:20px;-moz-border-radius-topleft:7px;-webkit-border-top-left-radius:7px;border-top-left-radius:7px;-moz-border-radius-topright:7px;-webkit-border-top-right-radius:7px;border-top-right-radius:7px;cursor:move}.elfinder-quicklook-title{color:#fff;white-space:nowrap;overflow:hidden;padding:2px 0}.elfinder-quicklook-titlebar .ui-icon{position:absolute;left:4px;top:50%;margin-top:-8px;width:16px;height:16px;cursor:default}.elfinder-quicklook-preview{overflow:hidden;position:relative;border:0 solid;border-left:1px solid transparent;border-right:1px solid transparent;height:100%}.elfinder-quicklook-info-wrapper{position:absolute;width:100%;left:0;top:50%;margin-top:-50px}.elfinder-quicklook-info{padding:0 12px 0 112px}.elfinder-quicklook-info .elfinder-quicklook-info-data:first-child{color:#fff;font-weight:700;padding-bottom:.5em}.elfinder-quicklook-info-data{padding-bottom:.2em;color:#fff}.elfinder-quicklook .elfinder-cwd-icon{position:absolute;left:32px;top:50%;margin-top:-20px}.elfinder-quicklook-preview img{display:block;margin:0 auto}.elfinder-quicklook-navbar{position:absolute;left:50%;bottom:4px;width:140px;height:32px;padding:0;margin-left:-70px;border:1px solid transparent;border-radius:19px;-moz-border-radius:19px;-webkit-border-radius:19px}.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar{width:188px;margin-left:-94px;padding:5px;border:1px solid #eee;background:#000}.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-icon-close,.elfinder-quicklook-fullscreen .elfinder-quicklook-navbar-separator{display:inline}.elfinder-quicklook-navbar-icon{width:32px;height:32px;margin:0 7px;float:left;background:url("../img/quicklook-icons.png") 0 0 no-repeat}.elfinder-quicklook-navbar-icon-fullscreen{background-position:0 -64px}.elfinder-quicklook-navbar-icon-fullscreen-off{background-position:0 -96px}.elfinder-quicklook-navbar-icon-prev{background-position:0 0}.elfinder-quicklook-navbar-icon-next{background-position:0 -32px}.elfinder-quicklook-navbar-icon-close{background-position:0 -128px;display:none}.elfinder-quicklook-navbar-separator{width:1px;height:32px;float:left;border-left:1px solid #fff;display:none}.elfinder-quicklook-preview-text-wrapper{width:100%;height:100%;background:#fff;color:#222;overflow:auto}pre.elfinder-quicklook-preview-text{margin:0;padding:3px 9px}.elfinder-quicklook-preview-html,.elfinder-quicklook-preview-pdf{width:100%;height:100%;background:#fff;border:0 solid;margin:0}.elfinder-quicklook-preview-flash{width:100%;height:100%}.elfinder-quicklook-preview-audio{width:100%;position:absolute;bottom:0;left:0}embed.elfinder-quicklook-preview-audio{height:30px;background:0 0}.elfinder-quicklook-preview-video{width:100%;height:100%}.elfinder-statusbar{text-align:center;font-weight:400;padding:.2em .5em;border-right:0 solid transparent;border-bottom:0 solid transparent;border-left:0 solid transparent}.elfinder-statusbar a{text-decoration:none}.elfinder-path{max-width:30%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis}.elfinder-ltr .elfinder-path{float:left}.elfinder-rtl .elfinder-path{float:right}.elfinder-stat-size{white-space:nowrap}.elfinder-ltr .elfinder-stat-size{float:right}.elfinder-rtl .elfinder-stat-size{float:left}.elfinder-stat-selected{white-space:nowrap;overflow:hidden}.elfinder-toolbar{padding:4px 0 3px;border-left:0 solid transparent;border-top:0 solid transparent;border-right:0 solid transparent}.elfinder-buttonset{margin:1px 4px;float:left;background:0 0;padding:0;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.elfinder .elfinder-button{width:16px;height:16px;margin:0;padding:4px;float:left;overflow:hidden;position:relative;border:0 solid;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.elfinder .ui-icon-search{cursor:pointer}.elfinder-button:first-child{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.elfinder-button:last-child{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.elfinder-toolbar-button-separator{float:left;padding:0;height:24px;border-top:0 solid;border-right:0 solid;border-bottom:0 solid;width:0}.elfinder .elfinder-button.ui-state-disabled{opacity:1;filter:Alpha(Opacity=100)}.elfinder .elfinder-button.ui-state-disabled .elfinder-button-icon{opacity:.4;filter:Alpha(Opacity=40)}.elfinder-rtl .elfinder-buttonset{float:right}.elfinder-button-icon{width:16px;height:16px;display:block;background:url('../img/toolbar.png') no-repeat}.elfinder-button-icon-home{background-position:0 0}.elfinder-button-icon-back{background-position:0 -112px}.elfinder-button-icon-forward{background-position:0 -128px}.elfinder-button-icon-up{background-position:0 -144px}.elfinder-button-icon-reload{background-position:0 -160px}.elfinder-button-icon-open{background-position:0 -176px}.elfinder-button-icon-mkdir{background-position:0 -192px}.elfinder-button-icon-mkfile{background-position:0 -208px}.elfinder-button-icon-rm{background-position:0 -224px}.elfinder-button-icon-copy{background-position:0 -240px}.elfinder-button-icon-cut{background-position:0 -256px}.elfinder-button-icon-paste{background-position:0 -272px}.elfinder-button-icon-getfile{background-position:0 -288px}.elfinder-button-icon-duplicate{background-position:0 -304px}.elfinder-button-icon-rename{background-position:0 -320px}.elfinder-button-icon-edit{background-position:0 -336px}.elfinder-button-icon-quicklook{background-position:0 -352px}.elfinder-button-icon-upload{background-position:0 -368px}.elfinder-button-icon-download{background-position:0 -384px}.elfinder-button-icon-info{background-position:0 -400px}.elfinder-button-icon-extract{background-position:0 -416px}.elfinder-button-icon-archive{background-position:0 -432px}.elfinder-button-icon-view{background-position:0 -448px}.elfinder-button-icon-view-list{background-position:0 -464px}.elfinder-button-icon-help{background-position:0 -480px}.elfinder-button-icon-resize{background-position:0 -512px}.elfinder-button-icon-search{background-position:0 -561px}.elfinder-button-icon-sort{background-position:0 -577px}.elfinder-button-icon-rotate-r{background-position:0 -625px}.elfinder-button-icon-rotate-l{background-position:0 -641px}.elfinder-button-icon-netmount{background-position:0 -688px}.elfinder-button-icon-netunmount{background-position:0 -96px}.elfinder .elfinder-menubutton{overflow:visible}.elfinder-button-menu{position:absolute;left:0;top:25px;padding:3px 0}.elfinder-button-menu-item{white-space:nowrap;cursor:default;padding:5px 19px;position:relative}.elfinder-button-menu .ui-state-hover{border:0 solid}.elfinder-button-menu-item-separated{border-top:1px solid #ccc}.elfinder-button-menu-item .ui-icon{width:16px;height:16px;position:absolute;left:2px;top:50%;margin-top:-8px;display:none}.elfinder-button-menu-item-selected .ui-icon{display:block}.elfinder-button-menu-item-selected-asc .ui-icon-arrowthick-1-n,.elfinder-button-menu-item-selected-desc .ui-icon-arrowthick-1-s{display:none}.elfinder-button form{position:absolute;top:0;right:0;opacity:0;filter:Alpha(Opacity=0);cursor:pointer}.elfinder .elfinder-button form input{background:0 0;cursor:default}.elfinder .elfinder-button-search{border:0 solid;background:0 0;padding:0;margin:1px 4px;height:auto;min-height:26px;float:right;width:202px}.elfinder-ltr .elfinder-button-search{float:right;margin-right:10px}.elfinder-rtl .elfinder-button-search{float:left;margin-left:10px}.elfinder-button-search input{width:160px;height:22px;padding:0 20px;line-height:22px;border:1px solid #aaa;-moz-border-radius:12px;-webkit-border-radius:12px;border-radius:12px;outline:0 solid}.elfinder-rtl .elfinder-button-search input{direction:rtl}.elfinder-button-search .ui-icon{position:absolute;height:18px;top:50%;margin:-9px 4px 0;opacity:.6;filter:Alpha(Opacity=60)}.elfinder-ltr .elfinder-button-search .ui-icon-search{left:0}.elfinder-rtl .elfinder-button-search .ui-icon-search,.elfinder-ltr .elfinder-button-search .ui-icon-close{right:0}.elfinder-rtl .elfinder-button-search .ui-icon-close{left:0} \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/theme.css b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/theme.css new file mode 100644 index 00000000..add4bee5 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/css2/theme.css @@ -0,0 +1,50 @@ +/** + * MacOS X like theme for elFinder. + * Required jquery ui "smoothness" theme. + * + * @author Dmitry (dio) Levashov + **/ + +/* dialogs */ +.std42-dialog, .std42-dialog .ui-widget-content { background-color:#ededed; background-image:none; background-clip: content-box; } + +/* navbar */ +.elfinder .elfinder-navbar { background:#dde4eb; } +.elfinder-navbar .ui-state-hover { background:transparent; border-color:transparent; } +.elfinder-navbar .ui-state-active { background: #3875d7; border-color:#3875d7; color:#fff; } +.elfinder-navbar .elfinder-droppable-active {background:#A7C6E5 !important;} +/* disabled elfinder */ +.elfinder-disabled .elfinder-navbar .ui-state-active { background: #dadada; border-color:#aaa; color:#fff; } + + +/* current directory */ +/* selected file in "icons" view */ +.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover { background:#ccc; } +/* list view*/ +.elfinder-cwd table tr:nth-child(odd) { background-color:#edf3fe; } +.elfinder-cwd table tr { border-top:1px solid #fff; } + +/* common selected background/color */ +.elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, +.elfinder-cwd table td.ui-state-hover, +.elfinder-button-menu .ui-state-hover { background: #3875d7; color:#fff;} +/* disabled elfinder */ +.elfinder-disabled .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, +.elfinder-disabled .elfinder-cwd table td.ui-state-hover { background:#dadada;} + +/* statusbar */ +.elfinder .elfinder-statusbar { color:#555; } +.elfinder .elfinder-statusbar a { text-decoration:none; color:#555;} + + +.std42-dialog .elfinder-help, .std42-dialog .elfinder-help .ui-widget-content { background:#fff;} + +/* contextmenu */ +.elfinder-contextmenu .ui-state-hover { background: #3875d7; color:#fff; } +.elfinder-contextmenu .ui-state-hover .elfinder-contextmenu-arrow { background-image:url('../img/arrows-active.png'); } + + + + + + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/elfinder.html b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/elfinder.html new file mode 100644 index 00000000..e67963f0 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/elfinder.html @@ -0,0 +1,40 @@ + + + + + elFinder 2.0 + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/arrows-active.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/arrows-active.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad71094510812c07d2ec89aad82bcfe2479281d GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<9!3HG593zhdsR^Dgjv*eMZ>OH-JZvD~a{Nf_ zj|XAfmZnMvC~A6q)nM(>H?!bw%qTJXw!5p+BgtN0#beXfZ|kjIDM1Jqs=Z-AKRa({Z3?#JN>k)`(*^kZ492SelF{r5}E+%mQYv# literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/arrows-normal.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/arrows-normal.png new file mode 100644 index 0000000000000000000000000000000000000000..9d8b4d2a876a7be2702e8abb83300ff6c9d3128b GIT binary patch literal 312 zcmV-80muG{P)HUC(lv0BbVz-RnQx=HjbzPrhAt3;qbJ36>U<%=!=c@n!(D(h(7;{|(AfkiT`Wt{t z2E>{Hz%HtxD^YmD(~V^&Dk z+T$NIpB^H*yC2vxAcWXeRrLj613Vt_9$*R~qR-g<;3;;bJzu{dcyM@>v|_jb0000< KMNUMnLSTY0K7$7U literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/crop.gif b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/crop.gif new file mode 100644 index 0000000000000000000000000000000000000000..72ea7ccb5321d5384d70437cfaac73011237901e GIT binary patch literal 329 zcmZ?wbhEHb9b#5NV>2k zBC~b@b~P=nNfWAe-b%_i6tS^-1y(h@EsB~1TqDA_h@fkxG$bHgvj}VxE1JLgr!*!^ ILUxTc0Q$^Q5C8xG literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/dialogs.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/dialogs.png new file mode 100644 index 0000000000000000000000000000000000000000..20de35740ea3afe68006830421c5bde82a075d12 GIT binary patch literal 18556 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 P00000NkvXXu0mjfl(f}E literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/icons-small.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/icons-small.png new file mode 100644 index 0000000000000000000000000000000000000000..95849dce253939f3d48151a439a9a15a5c34ced6 GIT binary patch literal 7365 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 OBn4SjnHnjx(EkTc+D(1{ literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/logo.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c1036de6b29c5c57aaf5d55daf531e2315f3b89b GIT binary patch literal 14681 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%0DF7 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 HOn?3#bu^kZ literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/progress.gif b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/progress.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bab11e356eb9e8ebef0f8a26f33e35d4a05c4de GIT binary patch literal 1727 zcmZ?wbhEHb6lUOHxT?=kaOx|oMxw>EXH0S-!E3(9FMXs?@|-vDka)(u&I50a`(9`@ zz2Np(Y25p+;M5P(DK8`wR=dpmk$3oqanC#Zna}#ypR=3(jl+6c`r&Wsd%sI$+%xEW zE0cG@eCqS^Df|7_JZM^cx?sa|$*glx8-KK(ey87YE9>Z&wAD{c`d(;O-bvc^ChgGs z+Ot1|Vo&I`z5f6IKLd$C@jthpYe=xOV}PrXo&hr>P&-g4!Z$#{C9xzCNZZ&~6eK2R zrKPiFn46pHC>R+S8t5As=^Gm98k$=f8(A3`C_sS{(6*wKG^-#NH>h1eo~=?w zNlAf~zJ7Umxn8-kUVc%!zM-Y1CCCgTBVC{h-Qvo;lEez#ykcdT2`;I{$wiq3C7Jno z3Lp~`lk!VTY?Xj6g?J&i0B&qvu^!kvddc~@`W1-<`i6Q2ATPlb`ugHmnwtw(U0f2B zif}JhgNs8d3sUuiQj7CTi;`1;%9TM@6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fK zRKYhfIWrH$2dnq>werj>E=kNwPW5!LRRWrzmzkMjWoT&TXklsLXzplcVQA=T;ACp% z&>2=9ZF3nBND}m`vLFjeDsTY(KatnYqyQCInmZhe+73JqDfW2&$ ziQ6p}IL(9VO~LIJOPqT3fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tQr6R`}^nj zub)4@fBX97^QVs=-oJbM=Jl(WFP=Yp`sDGWhY#-GyL;#Mt(!NlU%Ptc@}-Lx&YwGb z=JctPCypOGdgSn-g9rBS+q-A?uAMu!Z`-%OrteG>WPn$Yr@}!9q`ulo&y1P0%+S^)NnwuIM>g#H2s;eq1%F9Yiii-*h^7C?Y zva>QX($i8?l9Lh>;^SgtqN5@s!oxyCf`bAB{QZ1=yuCa<+}&JVoShsU?CorAtgS39 z%*{+qjE#U5iuTT4?zT}@R*SxHerUQSj>T@l6DaKib(T{}Cz zH4+aDIOV$7rDP9A+@I-Jg1YMd~wW-TFa8LTsbsky)VzgErB!6 zN_)9&ic3}zZca2@udl?y6t~{}$NxGuVczBz-WDlw9-giq9(I8VlO}dEGBZz`$vAt? zoatCCi#*U$prO*rbwcG6ONQ0#`Rxf_wE^?|o3>nDsI`v4)2&HS*h{)K>g}Q)V-_cs zdj=9>-~S}(-8cEi#?jQ=1hlZ7mtBCJr%$|}XF~TB0mkV-`)1CbJ!3vr+ma46Z4mI1 z=;sW|&=BDWkZ&l_3JshSaq#iuf`Fx~k2_yDI88~2(`~I;uZVPO%)U$kj)~Rt5)7B{ xa5u0u@Cx&`whMDharE{{NpTCXPoB!oBhE8p*32o4^A`ZEU9@z`5=KV`YXH7|U6ud< literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/quicklook-bg.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/quicklook-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..aedeadd63ec33a3fc583d4ddb5838df4b921689b GIT binary patch literal 78 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/toolbar.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/toolbar.png new file mode 100644 index 0000000000000000000000000000000000000000..1e45f01016e7030a25ab27bc10b5f4eb5a13330d GIT binary patch literal 18217 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 literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_ftp.png b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_ftp.png new file mode 100644 index 0000000000000000000000000000000000000000..605729d3e38e5b783de2849f24adb0ca7bc99615 GIT binary patch literal 526 zcmV+p0`dKcP)}-7=Z~S$)lxCr$f+s64*9o z&}y~%5=0`Azy#1r|1!{Zof?fskEm2Clt?7{3@pngnTdU+xC84E$z+n6%_c#scny%C zR;&39=JWY{;1WPP-}i*>9$*yiBC$8KQ0 z-^?r%rK&1u6DqWf)&LSk5onrrCGO)Ry)ozfk%%|29mlzzPN%c|eh)>FL!Q^7v;f9R zk*f%4SWimV4VceociZiILKtJta5x-^6Vf!500iYZ!VUqt1oV0~1i@gm*}OTbFuMJI z-#>PC({z0F5=yBX1Oa|PGs5p3aM=Oox~}J=mxv_W^Sps&S_`StoAthw|@# cJo@;vgzx z;hcJ}Zf?$Pr|%s9FeRZ6e&_qXbME*5yGl#T1%yIJL3EW6#Q)JBLQDuu9GOf8RaI5N z$;ruyY&MHrE{9^Vgr%hn$z{0R1}w{h*XxDP=f&XQjUi3bq$gI~+L~TlbJ~Ow4qrPo zWJCRN43CV#tTy&P_&g?mIW@)0!GHX+d2es;?Ql2@0k*zb!ilDn zXusS6A$N6mgXsn`&Z^Y&`Ml(UI7$+g#Jqt9JQ#a~@h9WB(svUZ8ygUJ2f3ixuOBc! zKmUfrnOz5Jpy3oIo<7Fh_umlm>vx|p`}wWpLKhB%F646;J1{hSzmx3F?mAG;Umu=U zHP&{pX)hv!=zkd9)9ZsZxZB@_KwTY1?%WbncqU6A<93skVXh|zqS5F?DwV>wxu19* z`-r~Q)38hxMztF?wf;kTz-?Fs8=DoE$Lc%?))-h^v8jPMaHT8_%RAWTz#<1b^d%CB zylQT4?xE4i+LxD?X`za=NN%inJV^U|h#hDm6CVpAer9xZw5M_tQ').append(node.contents()), + + /** + * Store node inline styles + * + * @see this.destroy + * @type String + **/ + prevStyle = node.attr('style'), + + /** + * Instance ID. Required to get/set cookie + * + * @type String + **/ + id = node.attr('id') || '', + + /** + * Events namespace + * + * @type String + **/ + namespace = 'elfinder-'+(id || Math.random().toString().substr(2, 7)), + + /** + * Mousedown event + * + * @type String + **/ + mousedown = 'mousedown.'+namespace, + + /** + * Keydown event + * + * @type String + **/ + keydown = 'keydown.'+namespace, + + /** + * Keypress event + * + * @type String + **/ + keypress = 'keypress.'+namespace, + + /** + * Is shortcuts/commands enabled + * + * @type Boolean + **/ + enabled = true, + + /** + * Store enabled value before ajax requiest + * + * @type Boolean + **/ + prevEnabled = true, + + /** + * List of build-in events which mapped into methods with same names + * + * @type Array + **/ + events = ['enable', 'disable', 'load', 'open', 'reload', 'select', 'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'dragstart', 'dragstop'], + + /** + * Rules to validate data from backend + * + * @type Object + **/ + rules = {}, + + /** + * Current working directory hash + * + * @type String + **/ + cwd = '', + + /** + * Current working directory options + * + * @type Object + **/ + cwdOptions = { + path : '', + url : '', + tmbUrl : '', + disabled : [], + separator : '/', + archives : [], + extract : [], + copyOverwrite : true, + uploadMaxSize : 0, + tmb : false // old API + }, + + /** + * Files/dirs cache + * + * @type Object + **/ + files = {}, + + /** + * Selected files hashes + * + * @type Array + **/ + selected = [], + + /** + * Events listeners + * + * @type Object + **/ + listeners = {}, + + /** + * Shortcuts + * + * @type Object + **/ + shortcuts = {}, + + /** + * Buffer for copied files + * + * @type Array + **/ + clipboard = [], + + /** + * Copied/cuted files hashes + * Prevent from remove its from cache. + * Required for dispaly correct files names in error messages + * + * @type Array + **/ + remember = [], + + /** + * Queue for 'open' requests + * + * @type Array + **/ + queue = [], + + /** + * Net drivers names + * + * @type Array + **/ + netDrivers = [], + + /** + * Commands prototype + * + * @type Object + **/ + base = new self.command(self), + + /** + * elFinder node width + * + * @type String + * @default "auto" + **/ + width = 'auto', + + /** + * elFinder node height + * + * @type Number + * @default 400 + **/ + height = 400, + + beeper = $(document.createElement('audio')).hide().appendTo('body')[0], + + syncInterval, + + open = function(data) { + if (data.init) { + // init - reset cache + files = {}; + } else { + // remove only files from prev cwd + for (var i in files) { + if (files.hasOwnProperty(i) + && files[i].mime != 'directory' + && files[i].phash == cwd + && $.inArray(i, remember) === -1) { + delete files[i]; + } + } + } + + cwd = data.cwd.hash; + cache(data.files); + if (!files[cwd]) { + cache([data.cwd]); + } + self.lastDir(cwd); + }, + + /** + * Store info about files/dirs in "files" object. + * + * @param Array files + * @return void + **/ + cache = function(data) { + var l = data.length, f; + + while (l--) { + f = data[l]; + if (f.name && f.hash && f.mime) { + if (!f.phash) { + var name = 'volume_'+f.name, + i18 = self.i18n(name); + + if (name != i18) { + f.i18 = i18; + } + } + files[f.hash] = f; + } + } + }, + + /** + * Exec shortcut + * + * @param jQuery.Event keydown/keypress event + * @return void + */ + execShortcut = function(e) { + var code = e.keyCode, + ctrlKey = !!(e.ctrlKey || e.metaKey); + + if (enabled) { + + $.each(shortcuts, function(i, shortcut) { + if (shortcut.type == e.type + && shortcut.keyCode == code + && shortcut.shiftKey == e.shiftKey + && shortcut.ctrlKey == ctrlKey + && shortcut.altKey == e.altKey) { + e.preventDefault() + e.stopPropagation(); + shortcut.callback(e, self); + self.debug('shortcut-exec', i+' : '+shortcut.description); + } + }); + + // prevent tab out of elfinder + if (code == 9 && !$(e.target).is(':input')) { + e.preventDefault(); + } + + } + }, + date = new Date(), + utc, + i18n + ; + + + /** + * Protocol version + * + * @type String + **/ + this.api = null; + + /** + * elFinder use new api + * + * @type Boolean + **/ + this.newAPI = false; + + /** + * elFinder use old api + * + * @type Boolean + **/ + this.oldAPI = false; + + /** + * User os. Required to bind native shortcuts for open/rename + * + * @type String + **/ + this.OS = navigator.userAgent.indexOf('Mac') !== -1 ? 'mac' : navigator.userAgent.indexOf('Win') !== -1 ? 'win' : 'other'; + + /** + * User browser UA. + * jQuery.browser: version deprecated: 1.3, removed: 1.9 + * + * @type Object + **/ + this.UA = (function(){ + var webkit = !document.uniqueID && !window.opera && !window.sidebar && window.localStorage && typeof window.orientation == "undefined"; + return { + // Browser IE <= IE 6 + ltIE6:typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined", + // Browser IE <= IE 7 + ltIE7:typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined", + // Browser IE <= IE 8 + ltIE8:typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined", + IE:document.uniqueID, + Firefox:window.sidebar, + Opera:window.opera, + Webkit:webkit, + Chrome:webkit && window.chrome, + Safari:webkit && !window.chrome, + Mobile:typeof window.orientation != "undefined", + Touch:typeof window.ontouchstart != "undefined" + }; + })(); + + /** + * Configuration options + * + * @type Object + **/ + this.options = $.extend(true, {}, this._options, opts||{}); + + if (opts.ui) { + this.options.ui = opts.ui; + } + + if (opts.commands) { + this.options.commands = opts.commands; + } + + if (opts.uiOptions && opts.uiOptions.toolbar) { + this.options.uiOptions.toolbar = opts.uiOptions.toolbar; + } + + $.extend(this.options.contextmenu, opts.contextmenu); + + + /** + * Ajax request type + * + * @type String + * @default "get" + **/ + this.requestType = /^(get|post)$/i.test(this.options.requestType) ? this.options.requestType.toLowerCase() : 'get', + + /** + * Any data to send across every ajax request + * + * @type Object + * @default {} + **/ + this.customData = $.isPlainObject(this.options.customData) ? this.options.customData : {}; + + /** + * Any custom headers to send across every ajax request + * + * @type Object + * @default {} + */ + this.customHeaders = $.isPlainObject(this.options.customHeaders) ? this.options.customHeaders : {}; + + /** + * Any custom xhrFields to send across every ajax request + * + * @type Object + * @default {} + */ + this.xhrFields = $.isPlainObject(this.options.xhrFields) ? this.options.xhrFields : {}; + + /** + * ID. Required to create unique cookie name + * + * @type String + **/ + this.id = id; + + /** + * URL to upload files + * + * @type String + **/ + this.uploadURL = opts.urlUpload || opts.url; + + /** + * Events namespace + * + * @type String + **/ + this.namespace = namespace; + + /** + * Interface language + * + * @type String + * @default "en" + **/ + this.lang = this.i18[this.options.lang] && this.i18[this.options.lang].messages ? this.options.lang : 'en'; + + i18n = this.lang == 'en' + ? this.i18['en'] + : $.extend(true, {}, this.i18['en'], this.i18[this.lang]); + + /** + * Interface direction + * + * @type String + * @default "ltr" + **/ + this.direction = i18n.direction; + + /** + * i18 messages + * + * @type Object + **/ + this.messages = i18n.messages; + + /** + * Date/time format + * + * @type String + * @default "m.d.Y" + **/ + this.dateFormat = this.options.dateFormat || i18n.dateFormat; + + /** + * Date format like "Yesterday 10:20:12" + * + * @type String + * @default "{day} {time}" + **/ + this.fancyFormat = this.options.fancyDateFormat || i18n.fancyDateFormat; + + /** + * Today timestamp + * + * @type Number + **/ + this.today = (new Date(date.getFullYear(), date.getMonth(), date.getDate())).getTime()/1000; + + /** + * Yesterday timestamp + * + * @type Number + **/ + this.yesterday = this.today - 86400; + + utc = this.options.UTCDate ? 'UTC' : ''; + + this.getHours = 'get'+utc+'Hours'; + this.getMinutes = 'get'+utc+'Minutes'; + this.getSeconds = 'get'+utc+'Seconds'; + this.getDate = 'get'+utc+'Date'; + this.getDay = 'get'+utc+'Day'; + this.getMonth = 'get'+utc+'Month'; + this.getFullYear = 'get'+utc+'FullYear'; + + /** + * Css classes + * + * @type String + **/ + this.cssClass = 'ui-helper-reset ui-helper-clearfix ui-widget ui-widget-content ui-corner-all elfinder elfinder-'+(this.direction == 'rtl' ? 'rtl' : 'ltr')+' '+this.options.cssClass; + + /** + * Method to store/fetch data + * + * @type Function + **/ + this.storage = (function() { + try { + return 'localStorage' in window && window['localStorage'] !== null ? self.localStorage : self.cookie; + } catch (e) { + return self.cookie; + } + })(); + + this.viewType = this.storage('view') || this.options.defaultView || 'icons'; + + this.sortType = this.storage('sortType') || this.options.sortType || 'name'; + + this.sortOrder = this.storage('sortOrder') || this.options.sortOrder || 'asc'; + + this.sortStickFolders = this.storage('sortStickFolders'); + + if (this.sortStickFolders === null) { + this.sortStickFolders = !!this.options.sortStickFolders; + } else { + this.sortStickFolders = !!this.sortStickFolders + } + + this.sortRules = $.extend(true, {}, this._sortRules, this.options.sortsRules); + + $.each(this.sortRules, function(name, method) { + if (typeof method != 'function') { + delete self.sortRules[name]; + } + }); + + this.compare = $.proxy(this.compare, this); + + /** + * Delay in ms before open notification dialog + * + * @type Number + * @default 500 + **/ + this.notifyDelay = this.options.notifyDelay > 0 ? parseInt(this.options.notifyDelay) : 500; + + /** + * Base draggable options + * + * @type Object + **/ + this.draggable = { + appendTo : 'body', + addClasses : true, + delay : 30, + distance : 8, + revert : true, + refreshPositions : true, + cursor : 'move', + cursorAt : {left : 50, top : 47}, + drag : function(e, ui) { + if (! ui.helper.data('locked')) { + ui.helper.toggleClass('elfinder-drag-helper-plus', e.shiftKey||e.ctrlKey||e.metaKey); + } + }, + start : function(e, ui) { + var targets = $.map(ui.helper.data('files')||[], function(h) { return h || null ;}), + cnt, h; + cnt = targets.length; + while (cnt--) { + h = targets[cnt]; + if (files[h].locked) { + ui.helper.addClass('elfinder-drag-helper-plus').data('locked', true); + break; + } + } + }, + stop : function() { self.trigger('focus').trigger('dragstop'); }, + helper : function(e, ui) { + var element = this.id ? $(this) : $(this).parents('[id]:first'), + helper = $('
'), + icon = function(mime) { return '
'; }, + hashes, l; + + self.trigger('dragstart', {target : element[0], originalEvent : e}); + + hashes = element.is('.'+self.res('class', 'cwdfile')) + ? self.selected() + : [self.navId2Hash(element.attr('id'))]; + + helper.append(icon(files[hashes[0]].mime)).data('files', hashes).data('locked', false); + + if ((l = hashes.length) > 1) { + helper.append(icon(files[hashes[l-1]].mime) + ''+l+''); + } + + return helper; + } + }; + + /** + * Base droppable options + * + * @type Object + **/ + this.droppable = { + // greedy : true, + tolerance : 'pointer', + accept : '.elfinder-cwd-file-wrapper,.elfinder-navbar-dir,.elfinder-cwd-file', + hoverClass : this.res('class', 'adroppable'), + drop : function(e, ui) { + var dst = $(this), + targets = $.map(ui.helper.data('files')||[], function(h) { return h || null }), + result = [], + c = 'class', + cnt, hash, i, h; + + if (dst.is('.'+self.res(c, 'cwd'))) { + hash = cwd; + } else if (dst.is('.'+self.res(c, 'cwdfile'))) { + hash = dst.attr('id'); + } else if (dst.is('.'+self.res(c, 'navdir'))) { + hash = self.navId2Hash(dst.attr('id')); + } + + cnt = targets.length; + + while (cnt--) { + h = targets[cnt]; + // ignore drop into itself or in own location + h != hash && files[h].phash != hash && result.push(h); + } + + if (result.length) { + ui.helper.hide(); + self.clipboard(result, !(e.ctrlKey||e.shiftKey||e.metaKey||ui.helper.data('locked'))); + self.exec('paste', hash); + self.trigger('drop', {files : targets}); + + } + } + }; + + /** + * Return true if filemanager is active + * + * @return Boolean + **/ + this.enabled = function() { + return node.is(':visible') && enabled; + } + + /** + * Return true if filemanager is visible + * + * @return Boolean + **/ + this.visible = function() { + return node.is(':visible'); + } + + /** + * Return root dir hash for current working directory + * + * @return String + */ + this.root = function(hash) { + var dir = files[hash || cwd], i; + + while (dir && dir.phash) { + dir = files[dir.phash] + } + if (dir) { + return dir.hash; + } + + while (i in files && files.hasOwnProperty(i)) { + dir = files[i] + if (!dir.phash && !dir.mime == 'directory' && dir.read) { + return dir.hash + } + } + + return ''; + } + + /** + * Return current working directory info + * + * @return Object + */ + this.cwd = function() { + return files[cwd] || {}; + } + + /** + * Return required cwd option + * + * @param String option name + * @return mixed + */ + this.option = function(name) { + return cwdOptions[name]||''; + } + + /** + * Return file data from current dir or tree by it's hash + * + * @param String file hash + * @return Object + */ + this.file = function(hash) { + return files[hash]; + }; + + /** + * Return all cached files + * + * @return Array + */ + this.files = function() { + return $.extend(true, {}, files); + } + + /** + * Return list of file parents hashes include file hash + * + * @param String file hash + * @return Array + */ + this.parents = function(hash) { + var parents = [], + dir; + + while ((dir = this.file(hash))) { + parents.unshift(dir.hash); + hash = dir.phash; + } + return parents; + } + + this.path2array = function(hash, i18) { + var file, + path = []; + + while (hash && (file = files[hash]) && file.hash) { + path.unshift(i18 && file.i18 ? file.i18 : file.name); + hash = file.phash; + } + + return path; + } + + /** + * Return file path + * + * @param Object file + * @return String + */ + this.path = function(hash, i18) { + return files[hash] && files[hash].path + ? files[hash].path + : this.path2array(hash, i18).join(cwdOptions.separator); + } + + /** + * Return file url if set + * + * @param Object file + * @return String + */ + this.url = function(hash) { + var file = files[hash]; + + if (!file || !file.read) { + return ''; + } + + if (file.url == '1') { + this.request({ + data : {cmd : 'url', target : hash}, + preventFail : true, + options: {async: false} + }) + .done(function(data) { + file.url = data.url || ''; + }) + .fail(function() { + file.url = ''; + }); + } + + if (file.url) { + return file.url; + } + + if (cwdOptions.url) { + return cwdOptions.url + $.map(this.path2array(hash), function(n) { return encodeURIComponent(n); }).slice(1).join('/') + } + + var params = $.extend({}, this.customData, { + cmd: 'file', + target: file.hash + }); + if (this.oldAPI) { + params.cmd = 'open'; + params.current = file.phash; + } + return this.options.url + (this.options.url.indexOf('?') === -1 ? '?' : '&') + $.param(params, true); + } + + /** + * Return thumbnail url + * + * @param String file hash + * @return String + */ + this.tmb = function(hash) { + var file = files[hash], + url = file && file.tmb && file.tmb != 1 ? cwdOptions['tmbUrl'] + file.tmb : ''; + + if (url && (this.UA.Opera || this.UA.IE)) { + url += '?_=' + new Date().getTime(); + } + return url; + } + + /** + * Return selected files hashes + * + * @return Array + **/ + this.selected = function() { + return selected.slice(0); + } + + /** + * Return selected files info + * + * @return Array + */ + this.selectedFiles = function() { + return $.map(selected, function(hash) { return files[hash] ? $.extend({}, files[hash]) : null }); + }; + + /** + * Return true if file with required name existsin required folder + * + * @param String file name + * @param String parent folder hash + * @return Boolean + */ + this.fileByName = function(name, phash) { + var hash; + + for (hash in files) { + if (files.hasOwnProperty(hash) && files[hash].phash == phash && files[hash].name == name) { + return files[hash]; + } + } + }; + + /** + * Valid data for required command based on rules + * + * @param String command name + * @param Object cammand's data + * @return Boolean + */ + this.validResponse = function(cmd, data) { + return data.error || this.rules[this.rules[cmd] ? cmd : 'defaults'](data); + } + + /** + * Return bytes from ini formated size + * + * @param String ini formated size + * @return Integer + */ + this.returnBytes = function(val) { + if (val == '-1') val = 0; + if (val) { + // for ex. 1mb, 1KB + val = val.replace(/b$/i, ''); + var last = val.charAt(val.length - 1).toLowerCase(); + val = val.replace(/[gmk]$/i, ''); + if (last == 'g') { + val = val * 1024 * 1024 * 1024; + } else if (last == 'm') { + val = val * 1024 * 1024; + } else if (last == 'k') { + val = val * 1024; + } + } + return val; + }; + + /** + * Proccess ajax request. + * Fired events : + * @todo + * @example + * @todo + * @return $.Deferred + */ + this.request = function(options) { + var self = this, + o = this.options, + dfrd = $.Deferred(), + // request data + data = $.extend({}, o.customData, {mimes : o.onlyMimes}, options.data || options), + // command name + cmd = data.cmd, + // call default fail callback (display error dialog) ? + deffail = !(options.preventDefault || options.preventFail), + // call default success callback ? + defdone = !(options.preventDefault || options.preventDone), + // options for notify dialog + notify = $.extend({}, options.notify), + // do not normalize data - return as is + raw = !!options.raw, + // sync files on request fail + syncOnFail = options.syncOnFail, + // open notify dialog timeout + timeout, + // request options + options = $.extend({ + url : o.url, + async : true, + type : this.requestType, + dataType : 'json', + cache : false, + // timeout : 100, + data : data, + headers : this.customHeaders, + xhrFields: this.xhrFields + }, options.options || {}), + /** + * Default success handler. + * Call default data handlers and fire event with command name. + * + * @param Object normalized response data + * @return void + **/ + done = function(data) { + data.warning && self.error(data.warning); + + cmd == 'open' && open($.extend(true, {}, data)); + + // fire some event to update cache/ui + data.removed && data.removed.length && self.remove(data); + data.added && data.added.length && self.add(data); + data.changed && data.changed.length && self.change(data); + + // fire event with command name + self.trigger(cmd, data); + + // force update content + data.sync && self.sync(); + }, + /** + * Request error handler. Reject dfrd with correct error message. + * + * @param jqxhr request object + * @param String request status + * @return void + **/ + error = function(xhr, status) { + var error; + + switch (status) { + case 'abort': + error = xhr.quiet ? '' : ['errConnect', 'errAbort']; + break; + case 'timeout': + error = ['errConnect', 'errTimeout']; + break; + case 'parsererror': + error = ['errResponse', 'errDataNotJSON']; + break; + default: + if (xhr.status == 403) { + error = ['errConnect', 'errAccess']; + } else if (xhr.status == 404) { + error = ['errConnect', 'errNotFound']; + } else { + error = 'errConnect'; + } + } + + dfrd.reject(error, xhr, status); + }, + /** + * Request success handler. Valid response data and reject/resolve dfrd. + * + * @param Object response data + * @param String request status + * @return void + **/ + success = function(response) { + if (raw) { + return dfrd.resolve(response); + } + + if (!response) { + return dfrd.reject(['errResponse', 'errDataEmpty'], xhr); + } else if (!$.isPlainObject(response)) { + return dfrd.reject(['errResponse', 'errDataNotJSON'], xhr); + } else if (response.error) { + return dfrd.reject(response.error, xhr); + } else if (!self.validResponse(cmd, response)) { + return dfrd.reject('errResponse', xhr); + } + + response = self.normalize(response); + + if (!self.api) { + self.api = response.api || 1; + self.newAPI = self.api >= 2; + self.oldAPI = !self.newAPI; + } + + if (response.options) { + cwdOptions = $.extend({}, cwdOptions, response.options); + } + + if (response.netDrivers) { + self.netDrivers = response.netDrivers; + } + + if (cmd == 'open' && !!data.init) { + self.uplMaxSize = self.returnBytes(response.uplMaxSize); + self.uplMaxFile = !!response.uplMaxFile? parseInt(response.uplMaxFile) : 20; + } + + dfrd.resolve(response); + response.debug && self.debug('backend-debug', response.debug); + }, + xhr, _xhr + ; + + defdone && dfrd.done(done); + dfrd.fail(function(error) { + if (error) { + deffail ? self.error(error) : self.debug('error', self.i18n(error)); + } + }) + + if (!cmd) { + return dfrd.reject('errCmdReq'); + } + + if (syncOnFail) { + dfrd.fail(function(error) { + error && self.sync(); + }); + } + + if (notify.type && notify.cnt) { + timeout = setTimeout(function() { + self.notify(notify); + dfrd.always(function() { + notify.cnt = -(parseInt(notify.cnt)||0); + self.notify(notify); + }) + }, self.notifyDelay) + + dfrd.always(function() { + clearTimeout(timeout); + }); + } + + // quiet abort not completed "open" requests + if (cmd == 'open') { + while ((_xhr = queue.pop())) { + if (_xhr.state() == 'pending') { + _xhr.quiet = true; + _xhr.abort(); + } + } + } + + delete options.preventFail + + xhr = this.transport.send(options).fail(error).done(success); + + // this.transport.send(options) + + // add "open" xhr into queue + if (cmd == 'open') { + queue.unshift(xhr); + dfrd.always(function() { + var ndx = $.inArray(xhr, queue); + + ndx !== -1 && queue.splice(ndx, 1); + }); + } + + return dfrd; + }; + + /** + * Compare current files cache with new files and return diff + * + * @param Array new files + * @return Object + */ + this.diff = function(incoming) { + var raw = {}, + added = [], + removed = [], + changed = [], + isChanged = function(hash) { + var l = changed.length; + + while (l--) { + if (changed[l].hash == hash) { + return true; + } + } + }; + + $.each(incoming, function(i, f) { + raw[f.hash] = f; + }); + + // find removed + $.each(files, function(hash, f) { + !raw[hash] && removed.push(hash); + }); + + // compare files + $.each(raw, function(hash, file) { + var origin = files[hash]; + + if (!origin) { + added.push(file); + } else { + $.each(file, function(prop) { + if (file[prop] != origin[prop]) { + changed.push(file) + return false; + } + }); + } + }); + + // parents of removed dirs mark as changed (required for tree correct work) + $.each(removed, function(i, hash) { + var file = files[hash], + phash = file.phash; + + if (phash + && file.mime == 'directory' + && $.inArray(phash, removed) === -1 + && raw[phash] + && !isChanged(phash)) { + changed.push(raw[phash]); + } + }); + + return { + added : added, + removed : removed, + changed : changed + }; + } + + /** + * Sync content + * + * @return jQuery.Deferred + */ + this.sync = function() { + var self = this, + dfrd = $.Deferred().done(function() { self.trigger('sync'); }), + opts1 = { + data : {cmd : 'open', init : 1, target : cwd, tree : this.ui.tree ? 1 : 0}, + preventDefault : true + }, + opts2 = { + data : {cmd : 'tree', target : (cwd == this.root())? cwd : this.file(cwd).phash}, + preventDefault : true + }; + + $.when( + this.request(opts1), + this.request(opts2) + ) + .fail(function(error) { + dfrd.reject(error); + error && self.request({ + data : {cmd : 'open', target : self.lastDir(''), tree : 1, init : 1}, + notify : {type : 'open', cnt : 1, hideCnt : true}, + preventDefault : true + }); + }) + .done(function(odata, pdata) { + var diff = self.diff(odata.files.concat(pdata && pdata.tree ? pdata.tree : [])); + + diff.added.push(odata.cwd) + diff.removed.length && self.remove(diff); + diff.added.length && self.add(diff); + diff.changed.length && self.change(diff); + return dfrd.resolve(diff); + }); + + return dfrd; + } + + this.upload = function(files) { + return this.transport.upload(files, this); + } + + /** + * Attach listener to events + * To bind to multiply events at once, separate events names by space + * + * @param String event(s) name(s) + * @param Object event handler + * @return elFinder + */ + this.bind = function(event, callback) { + var i; + + if (typeof(callback) == 'function') { + event = ('' + event).toLowerCase().split(/\s+/); + + for (i = 0; i < event.length; i++) { + if (listeners[event[i]] === void(0)) { + listeners[event[i]] = []; + } + listeners[event[i]].push(callback); + } + } + return this; + }; + + /** + * Remove event listener if exists + * + * @param String event name + * @param Function callback + * @return elFinder + */ + this.unbind = function(event, callback) { + var l = listeners[('' + event).toLowerCase()] || [], + i = l.indexOf(callback); + + i > -1 && l.splice(i, 1); + //delete callback; // need this? + callback = null + return this; + }; + + /** + * Fire event - send notification to all event listeners + * + * @param String event type + * @param Object data to send across event + * @return elFinder + */ + this.trigger = function(event, data) { + var event = event.toLowerCase(), + handlers = listeners[event] || [], i, j; + + this.debug('event-'+event, data) + + if (handlers.length) { + event = $.Event(event); + + for (i = 0; i < handlers.length; i++) { + // to avoid data modifications. remember about "sharing" passing arguments in js :) + event.data = $.extend(true, {}, data); + + try { + if (handlers[i](event, this) === false + || event.isDefaultPrevented()) { + this.debug('event-stoped', event.type); + break; + } + } catch (ex) { + window.console && window.console.log && window.console.log(ex); + } + + } + } + return this; + } + + /** + * Bind keybord shortcut to keydown event + * + * @example + * elfinder.shortcut({ + * pattern : 'ctrl+a', + * description : 'Select all files', + * callback : function(e) { ... }, + * keypress : true|false (bind to keypress instead of keydown) + * }) + * + * @param Object shortcut config + * @return elFinder + */ + this.shortcut = function(s) { + var patterns, pattern, code, i, parts; + + if (this.options.allowShortcuts && s.pattern && $.isFunction(s.callback)) { + patterns = s.pattern.toUpperCase().split(/\s+/); + + for (i= 0; i < patterns.length; i++) { + pattern = patterns[i] + parts = pattern.split('+'); + code = (code = parts.pop()).length == 1 + ? code > 0 ? code : code.charCodeAt(0) + : $.ui.keyCode[code]; + + if (code && !shortcuts[pattern]) { + shortcuts[pattern] = { + keyCode : code, + altKey : $.inArray('ALT', parts) != -1, + ctrlKey : $.inArray('CTRL', parts) != -1, + shiftKey : $.inArray('SHIFT', parts) != -1, + type : s.type || 'keydown', + callback : s.callback, + description : s.description, + pattern : pattern + }; + } + } + } + return this; + } + + /** + * Registered shortcuts + * + * @type Object + **/ + this.shortcuts = function() { + var ret = []; + + $.each(shortcuts, function(i, s) { + ret.push([s.pattern, self.i18n(s.description)]); + }); + return ret; + }; + + /** + * Get/set clipboard content. + * Return new clipboard content. + * + * @example + * this.clipboard([]) - clean clipboard + * this.clipboard([{...}, {...}], true) - put 2 files in clipboard and mark it as cutted + * + * @param Array new files hashes + * @param Boolean cut files? + * @return Array + */ + this.clipboard = function(hashes, cut) { + var map = function() { return $.map(clipboard, function(f) { return f.hash }); } + + if (hashes !== void(0)) { + clipboard.length && this.trigger('unlockfiles', {files : map()}); + remember = []; + + clipboard = $.map(hashes||[], function(hash) { + var file = files[hash]; + if (file) { + + remember.push(hash); + + return { + hash : hash, + phash : file.phash, + name : file.name, + mime : file.mime, + read : file.read, + locked : file.locked, + cut : !!cut + } + } + return null; + }); + this.trigger('changeclipboard', {clipboard : clipboard.slice(0, clipboard.length)}); + cut && this.trigger('lockfiles', {files : map()}); + } + + // return copy of clipboard instead of refrence + return clipboard.slice(0, clipboard.length); + } + + /** + * Return true if command enabled + * + * @param String command name + * @return Boolean + */ + this.isCommandEnabled = function(name) { + return this._commands[name] ? $.inArray(name, cwdOptions.disabled) === -1 : false; + } + + /** + * Exec command and return result; + * + * @param String command name + * @param String|Array usualy files hashes + * @param String|Array command options + * @return $.Deferred + */ + this.exec = function(cmd, files, opts) { + return this._commands[cmd] && this.isCommandEnabled(cmd) + ? this._commands[cmd].exec(files, opts) + : $.Deferred().reject('No such command'); + } + + /** + * Create and return dialog. + * + * @param String|DOMElement dialog content + * @param Object dialog options + * @return jQuery + */ + this.dialog = function(content, options) { + return $('
').append(content).appendTo(node).elfinderdialog(options); + } + + /** + * Return UI widget or node + * + * @param String ui name + * @return jQuery + */ + this.getUI = function(ui) { + return this.ui[ui] || node; + } + + this.command = function(name) { + return name === void(0) ? this._commands : this._commands[name]; + } + + /** + * Resize elfinder node + * + * @param String|Number width + * @param Number height + * @return void + */ + this.resize = function(w, h) { + node.css('width', w).height(h).trigger('resize'); + this.trigger('resize', {width : node.width(), height : node.height()}); + } + + /** + * Restore elfinder node size + * + * @return elFinder + */ + this.restoreSize = function() { + this.resize(width, height); + } + + this.show = function() { + node.show(); + this.enable().trigger('show'); + } + + this.hide = function() { + this.disable().trigger('hide'); + node.hide(); + } + + /** + * Destroy this elFinder instance + * + * @return void + **/ + this.destroy = function() { + if (node && node[0].elfinder) { + this.trigger('destroy').disable(); + listeners = {}; + shortcuts = {}; + $(document).add(node).unbind('.'+this.namespace); + self.trigger = function() { } + node.children().remove(); + node.append(prevContent.contents()).removeClass(this.cssClass).attr('style', prevStyle); + node[0].elfinder = null; + if (syncInterval) { + clearInterval(syncInterval); + } + } + } + + /************* init stuffs ****************/ + + // check jquery ui + if (!($.fn.selectable && $.fn.draggable && $.fn.droppable)) { + return alert(this.i18n('errJqui')); + } + + // check node + if (!node.length) { + return alert(this.i18n('errNode')); + } + // check connector url + if (!this.options.url) { + return alert(this.i18n('errURL')); + } + + $.extend($.ui.keyCode, { + 'F1' : 112, + 'F2' : 113, + 'F3' : 114, + 'F4' : 115, + 'F5' : 116, + 'F6' : 117, + 'F7' : 118, + 'F8' : 119, + 'F9' : 120 + }); + + this.dragUpload = false; + this.xhrUpload = (typeof XMLHttpRequestUpload != 'undefined' || typeof XMLHttpRequestEventTarget != 'undefined') && typeof File != 'undefined' && typeof FormData != 'undefined'; + + // configure transport object + this.transport = {} + + if (typeof(this.options.transport) == 'object') { + this.transport = this.options.transport; + if (typeof(this.transport.init) == 'function') { + this.transport.init(this) + } + } + + if (typeof(this.transport.send) != 'function') { + this.transport.send = function(opts) { return $.ajax(opts); } + } + + if (this.transport.upload == 'iframe') { + this.transport.upload = $.proxy(this.uploads.iframe, this); + } else if (typeof(this.transport.upload) == 'function') { + this.dragUpload = !!this.options.dragUploadAllow; + } else if (this.xhrUpload && !!this.options.dragUploadAllow) { + this.transport.upload = $.proxy(this.uploads.xhr, this); + this.dragUpload = true; + } else { + this.transport.upload = $.proxy(this.uploads.iframe, this); + } + + /** + * Alias for this.trigger('error', {error : 'message'}) + * + * @param String error message + * @return elFinder + **/ + this.error = function() { + var arg = arguments[0]; + return arguments.length == 1 && typeof(arg) == 'function' + ? self.bind('error', arg) + : self.trigger('error', {error : arg}); + } + + // create bind/trigger aliases for build-in events + $.each(['enable', 'disable', 'load', 'open', 'reload', 'select', 'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'dragstart', 'dragstop', 'search', 'searchend', 'viewchange'], function(i, name) { + self[name] = function() { + var arg = arguments[0]; + return arguments.length == 1 && typeof(arg) == 'function' + ? self.bind(name, arg) + : self.trigger(name, $.isPlainObject(arg) ? arg : {}); + } + }); + + // bind core event handlers + this + .enable(function() { + if (!enabled && self.visible() && self.ui.overlay.is(':hidden')) { + enabled = true; + $('texarea:focus,input:focus,button').blur(); + node.removeClass('elfinder-disabled'); + } + }) + .disable(function() { + prevEnabled = enabled; + enabled = false; + node.addClass('elfinder-disabled'); + }) + .open(function() { + selected = []; + }) + .select(function(e) { + selected = $.map(e.data.selected || e.data.value|| [], function(hash) { return files[hash] ? hash : null; }); + }) + .error(function(e) { + var opts = { + cssClass : 'elfinder-dialog-error', + title : self.i18n(self.i18n('error')), + resizable : false, + destroyOnClose : true, + buttons : {} + }; + + opts.buttons[self.i18n(self.i18n('btnClose'))] = function() { $(this).elfinderdialog('close'); }; + + self.dialog(''+self.i18n(e.data.error), opts); + }) + .bind('tree parents', function(e) { + cache(e.data.tree || []); + }) + .bind('tmb', function(e) { + $.each(e.data.images||[], function(hash, tmb) { + if (files[hash]) { + files[hash].tmb = tmb; + } + }) + }) + .add(function(e) { + cache(e.data.added||[]); + }) + .change(function(e) { + $.each(e.data.changed||[], function(i, file) { + var hash = file.hash; + if ((files[hash].width && !file.width) || (files[hash].height && !file.height)) { + files[hash].width = undefined; + files[hash].height = undefined; + } + files[hash] = files[hash] ? $.extend(files[hash], file) : file; + }); + }) + .remove(function(e) { + var removed = e.data.removed||[], + l = removed.length, + rm = function(hash) { + var file = files[hash]; + if (file) { + if (file.mime == 'directory' && file.dirs) { + $.each(files, function(h, f) { + f.phash == hash && rm(h); + }); + } + delete files[hash]; + } + }; + + while (l--) { + rm(removed[l]); + } + + }) + .bind('search', function(e) { + cache(e.data.files); + }) + .bind('rm', function(e) { + var play = beeper.canPlayType && beeper.canPlayType('audio/wav; codecs="1"'); + + play && play != '' && play != 'no' && $(beeper).html('')[0].play() + }) + + ; + + // bind external event handlers + $.each(this.options.handlers, function(event, callback) { + self.bind(event, callback); + }); + + /** + * History object. Store visited folders + * + * @type Object + **/ + this.history = new this.history(this); + + // in getFileCallback set - change default actions on double click/enter/ctrl+enter + if (typeof(this.options.getFileCallback) == 'function' && this.commands.getfile) { + this.bind('dblclick', function(e) { + e.preventDefault(); + self.exec('getfile').fail(function() { + self.exec('open'); + }); + }); + this.shortcut({ + pattern : 'enter', + description : this.i18n('cmdgetfile'), + callback : function() { self.exec('getfile').fail(function() { self.exec(self.OS == 'mac' ? 'rename' : 'open') }) } + }) + .shortcut({ + pattern : 'ctrl+enter', + description : this.i18n(this.OS == 'mac' ? 'cmdrename' : 'cmdopen'), + callback : function() { self.exec(self.OS == 'mac' ? 'rename' : 'open') } + }); + + } + + /** + * Loaded commands + * + * @type Object + **/ + this._commands = {}; + + if (!$.isArray(this.options.commands)) { + this.options.commands = []; + } + // check required commands + $.each(['open', 'reload', 'back', 'forward', 'up', 'home', 'info', 'quicklook', 'getfile', 'help'], function(i, cmd) { + $.inArray(cmd, self.options.commands) === -1 && self.options.commands.push(cmd); + }); + + // load commands + $.each(this.options.commands, function(i, name) { + var cmd = self.commands[name]; + if ($.isFunction(cmd) && !self._commands[name]) { + cmd.prototype = base; + self._commands[name] = new cmd(); + self._commands[name].setup(name, self.options.commandsOptions[name]||{}); + } + }); + + // prepare node + node.addClass(this.cssClass) + .bind(mousedown, function() { + !enabled && self.enable(); + }); + + /** + * UI nodes + * + * @type Object + **/ + this.ui = { + // container for nav panel and current folder container + workzone : $('
').appendTo(node).elfinderworkzone(this), + // container for folders tree / places + navbar : $('
').appendTo(node).elfindernavbar(this, this.options.uiOptions.navbar || {}), + // contextmenu + contextmenu : $('
').appendTo(node).elfindercontextmenu(this), + // overlay + overlay : $('
').appendTo(node).elfinderoverlay({ + show : function() { self.disable(); }, + hide : function() { prevEnabled && self.enable(); } + }), + // current folder container + cwd : $('
').appendTo(node).elfindercwd(this, this.options.uiOptions.cwd || {}), + // notification dialog window + notify : this.dialog('', { + cssClass : 'elfinder-dialog-notify', + position : {top : '12px', right : '12px'}, + resizable : false, + autoOpen : false, + title : ' ', + width : 280 + }), + statusbar : $('
').hide().appendTo(node) + } + + // load required ui + $.each(this.options.ui || [], function(i, ui) { + var name = 'elfinder'+ui, + opts = self.options.uiOptions[ui] || {}; + + if (!self.ui[ui] && $.fn[name]) { + self.ui[ui] = $('<'+(opts.tag || 'div')+'/>').appendTo(node)[name](self, opts); + } + }); + + + + // store instance in node + node[0].elfinder = this; + + // make node resizable + this.options.resizable + && !this.UA.Touch + && $.fn.resizable + && node.resizable({ + handles : 'se', + minWidth : 300, + minHeight : 200 + }); + + if (this.options.width) { + width = this.options.width; + } + + if (this.options.height) { + height = parseInt(this.options.height); + } + + // update size + self.resize(width, height); + + // attach events to document + $(document) + // disable elfinder on click outside elfinder + .bind('click.'+this.namespace, function(e) { enabled && !$(e.target).closest(node).length && self.disable(); }) + // exec shortcuts + .bind(keydown+' '+keypress, execShortcut); + + // attach events to window + self.options.useBrowserHistory && $(window) + .on('popstate', function(ev) { + var target = ev.originalEvent.state && ev.originalEvent.state.thash; + target && !$.isEmptyObject(self.files()) && self.request({ + data : {cmd : 'open', target : target, onhistory : 1}, + notify : {type : 'open', cnt : 1, hideCnt : true}, + syncOnFail : true + }); + }); + + // send initial request and start to pray >_< + this.trigger('init') + .request({ + data : {cmd : 'open', target : self.startDir(), init : 1, tree : this.ui.tree ? 1 : 0}, + preventDone : true, + notify : {type : 'open', cnt : 1, hideCnt : true}, + freeze : true + }) + .fail(function() { + self.trigger('fail').disable().lastDir(''); + listeners = {}; + shortcuts = {}; + $(document).add(node).unbind('.'+this.namespace); + self.trigger = function() { }; + }) + .done(function(data) { + self.load().debug('api', self.api); + data = $.extend(true, {}, data); + open(data); + self.trigger('open', data); + }); + + // update ui's size after init + this.one('load', function() { + node.trigger('resize'); + if (self.options.sync > 1000) { + syncInterval = setInterval(function() { + self.sync(); + }, self.options.sync) + + } + + }); + + // self.timeEnd('load'); + +} + +/** + * Prototype + * + * @type Object + */ +elFinder.prototype = { + + res : function(type, id) { + return this.resources[type] && this.resources[type][id]; + }, + + /** + * Internationalization object + * + * @type Object + */ + i18 : { + en : { + translator : '', + language : 'English', + direction : 'ltr', + dateFormat : 'd.m.Y H:i', + fancyDateFormat : '$1 H:i', + messages : {} + }, + months : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + monthsShort : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + + days : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + daysShort : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] + }, + + /** + * File mimetype to kind mapping + * + * @type Object + */ + kinds : { + 'unknown' : 'Unknown', + 'directory' : 'Folder', + 'symlink' : 'Alias', + 'symlink-broken' : 'AliasBroken', + 'application/x-empty' : 'TextPlain', + 'application/postscript' : 'Postscript', + 'application/vnd.ms-office' : 'MsOffice', + 'application/vnd.ms-word' : 'MsWord', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : 'MsWord', + 'application/vnd.ms-word.document.macroEnabled.12' : 'MsWord', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' : 'MsWord', + 'application/vnd.ms-word.template.macroEnabled.12' : 'MsWord', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'MsWord', + 'application/vnd.ms-excel' : 'MsExcel', + 'application/vnd.ms-excel.sheet.macroEnabled.12' : 'MsExcel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' : 'MsExcel', + 'application/vnd.ms-excel.template.macroEnabled.12' : 'MsExcel', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' : 'MsExcel', + 'application/vnd.ms-excel.addin.macroEnabled.12' : 'MsExcel', + 'application/vnd.ms-powerpoint' : 'MsPP', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' : 'MsPP', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' : 'MsPP', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' : 'MsPP', + 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' : 'MsPP', + 'application/vnd.openxmlformats-officedocument.presentationml.template' : 'MsPP', + 'application/vnd.ms-powerpoint.template.macroEnabled.12' : 'MsPP', + 'application/vnd.ms-powerpoint.addin.macroEnabled.12' : 'MsPP', + 'application/vnd.openxmlformats-officedocument.presentationml.slide' : 'MsPP', + 'application/vnd.ms-powerpoint.slide.macroEnabled.12' : 'MsPP', + 'application/pdf' : 'PDF', + 'application/xml' : 'XML', + 'application/vnd.oasis.opendocument.text' : 'OO', + 'application/vnd.oasis.opendocument.text-template' : 'OO', + 'application/vnd.oasis.opendocument.text-web' : 'OO', + 'application/vnd.oasis.opendocument.text-master' : 'OO', + 'application/vnd.oasis.opendocument.graphics' : 'OO', + 'application/vnd.oasis.opendocument.graphics-template' : 'OO', + 'application/vnd.oasis.opendocument.presentation' : 'OO', + 'application/vnd.oasis.opendocument.presentation-template' : 'OO', + 'application/vnd.oasis.opendocument.spreadsheet' : 'OO', + 'application/vnd.oasis.opendocument.spreadsheet-template' : 'OO', + 'application/vnd.oasis.opendocument.chart' : 'OO', + 'application/vnd.oasis.opendocument.formula' : 'OO', + 'application/vnd.oasis.opendocument.database' : 'OO', + 'application/vnd.oasis.opendocument.image' : 'OO', + 'application/vnd.openofficeorg.extension' : 'OO', + 'application/x-shockwave-flash' : 'AppFlash', + 'application/flash-video' : 'Flash video', + 'application/x-bittorrent' : 'Torrent', + 'application/javascript' : 'JS', + 'application/rtf' : 'RTF', + 'application/rtfd' : 'RTF', + 'application/x-font-ttf' : 'TTF', + 'application/x-font-otf' : 'OTF', + 'application/x-rpm' : 'RPM', + 'application/x-web-config' : 'TextPlain', + 'application/xhtml+xml' : 'HTML', + 'application/docbook+xml' : 'DOCBOOK', + 'application/x-awk' : 'AWK', + 'application/x-gzip' : 'GZIP', + 'application/x-bzip2' : 'BZIP', + 'application/zip' : 'ZIP', + 'application/x-zip' : 'ZIP', + 'application/x-rar' : 'RAR', + 'application/x-tar' : 'TAR', + 'application/x-7z-compressed' : '7z', + 'application/x-jar' : 'JAR', + 'text/plain' : 'TextPlain', + 'text/x-php' : 'PHP', + 'text/html' : 'HTML', + 'text/javascript' : 'JS', + 'text/css' : 'CSS', + 'text/rtf' : 'RTF', + 'text/rtfd' : 'RTF', + 'text/x-c' : 'C', + 'text/x-csrc' : 'C', + 'text/x-chdr' : 'CHeader', + 'text/x-c++' : 'CPP', + 'text/x-c++src' : 'CPP', + 'text/x-c++hdr' : 'CPPHeader', + 'text/x-shellscript' : 'Shell', + 'application/x-csh' : 'Shell', + 'text/x-python' : 'Python', + 'text/x-java' : 'Java', + 'text/x-java-source' : 'Java', + 'text/x-ruby' : 'Ruby', + 'text/x-perl' : 'Perl', + 'text/x-sql' : 'SQL', + 'text/xml' : 'XML', + 'text/x-comma-separated-values' : 'CSV', + 'image/x-ms-bmp' : 'BMP', + 'image/jpeg' : 'JPEG', + 'image/gif' : 'GIF', + 'image/png' : 'PNG', + 'image/tiff' : 'TIFF', + 'image/x-targa' : 'TGA', + 'image/vnd.adobe.photoshop' : 'PSD', + 'image/xbm' : 'XBITMAP', + 'image/pxm' : 'PXM', + 'audio/mpeg' : 'AudioMPEG', + 'audio/midi' : 'AudioMIDI', + 'audio/ogg' : 'AudioOGG', + 'audio/mp4' : 'AudioMPEG4', + 'audio/x-m4a' : 'AudioMPEG4', + 'audio/wav' : 'AudioWAV', + 'audio/x-mp3-playlist' : 'AudioPlaylist', + 'video/x-dv' : 'VideoDV', + 'video/mp4' : 'VideoMPEG4', + 'video/mpeg' : 'VideoMPEG', + 'video/x-msvideo' : 'VideoAVI', + 'video/quicktime' : 'VideoMOV', + 'video/x-ms-wmv' : 'VideoWM', + 'video/x-flv' : 'VideoFlash', + 'video/x-matroska' : 'VideoMKV', + 'video/ogg' : 'VideoOGG' + }, + + /** + * Ajax request data validation rules + * + * @type Object + */ + rules : { + defaults : function(data) { + if (!data + || (data.added && !$.isArray(data.added)) + || (data.removed && !$.isArray(data.removed)) + || (data.changed && !$.isArray(data.changed))) { + return false; + } + return true; + }, + open : function(data) { return data && data.cwd && data.files && $.isPlainObject(data.cwd) && $.isArray(data.files); }, + tree : function(data) { return data && data.tree && $.isArray(data.tree); }, + parents : function(data) { return data && data.tree && $.isArray(data.tree); }, + tmb : function(data) { return data && data.images && ($.isPlainObject(data.images) || $.isArray(data.images)); }, + upload : function(data) { return data && ($.isPlainObject(data.added) || $.isArray(data.added));}, + search : function(data) { return data && data.files && $.isArray(data.files)} + }, + + + + + /** + * Commands costructors + * + * @type Object + */ + commands : {}, + + parseUploadData : function(text) { + var data; + + if (!$.trim(text)) { + return {error : ['errResponse', 'errDataEmpty']}; + } + + try { + data = $.parseJSON(text); + } catch (e) { + return {error : ['errResponse', 'errDataNotJSON']}; + } + + if (!this.validResponse('upload', data)) { + return {error : ['errResponse']}; + } + data = this.normalize(data); + data.removed = $.merge((data.removed || []), $.map(data.added||[], function(f) { return f.hash; })); + return data; + + }, + + iframeCnt : 0, + + uploads : { + // check droped contents + checkFile : function(data, fm) { + if (!!data.checked || data.type == 'files') { + return data.files; + } else if (data.type == 'data') { + var dfrd = $.Deferred(), + files = [], + paths = [], + dirctorys = [], + entries = [], + processing = 0, + + readEntries = function(dirReader) { + var toArray = function(list) { + return Array.prototype.slice.call(list || []); + }; + var readFile = function(fileEntry, callback) { + var dfrd = $.Deferred(); + if (typeof fileEntry == 'undefined') { + dfrd.reject('empty'); + } else if (fileEntry.isFile) { + fileEntry.file(function (file) { + dfrd.resolve(file); + }, function(e){ + dfrd.reject(); + }); + } else { + dfrd.reject('dirctory'); + } + return dfrd.promise(); + }; + + dirReader.readEntries(function (results) { + if (!results.length) { + var len = entries.length - 1; + var read = function(i) { + readFile(entries[i]).done(function(file){ + if (! (fm.OS == 'win' && file.name.match(/^(?:desktop\.ini|thumbs\.db)$/i)) + && + ! (fm.OS == 'mac' && file.name.match(/^\.ds_store$/i))) { + paths.push(entries[i].fullPath); + files.push(file); + } + }).fail(function(e){ + if (e == 'dirctory') { + // dirctory + dirctorys.push(entries[i]); + } else if (e == 'empty') { + // dirctory is empty + } else { + // why fail? + } + }).always(function(){ + processing--; + if (i < len) { + processing++; + read(++i); + } + }); + }; + processing++; + read(0); + processing--; + } else { + entries = entries.concat(toArray(results)); + readEntries(dirReader); + } + }); + }, + + doScan = function(items, isEntry) { + var dirReader, entry; + entries = []; + var length = items.length; + for (var i = 0; i < length; i++) { + if (! isEntry) { + entry = !!items[i].getAsEntry? items[i].getAsEntry() : items[i].webkitGetAsEntry(); + } else { + entry = items[i]; + } + if (entry) { + if (entry.isFile) { + paths.push(''); + files.push(data.files.items[i].getAsFile()); + } else if (entry.isDirectory) { + if (processing > 0) { + dirctorys.push(entry); + } else { + processing = 0; + dirReader = entry.createReader(); + processing++; + readEntries(dirReader); + } + } + } + } + }; + + doScan(data.files.items); + + setTimeout(function wait() { + if (processing > 0) { + setTimeout(wait, 10); + } else { + if (dirctorys.length > 0) { + doScan([dirctorys.shift()], true); + setTimeout(wait, 10); + } else { + dfrd.resolve([files, paths]); + } + } + }, 10); + + return dfrd.promise(); + } else { + var ret = []; + var str = data.files[0]; + if (data.type == 'html') { + var tmp = $("").append($.parseHTML(str)); + $('img[src]', tmp).each(function(){ + var url = $(this).attr('src'); + if (url && $.inArray(url, ret) == -1) ret.push(url); + }); + $('a[href]', tmp).each(function(){ + var loc, + parseUrl = function(url) { + var a = document.createElement('a'); + a.href = url; + return a; + }; + if ($(this).text()) { + loc = parseUrl($(this).attr('href')); + if (loc.href && ! loc.pathname.match(/(?:\.html?|\/[^\/.]*)$/i)) { + if ($.inArray(loc.href, ret) == -1) ret.push(loc.href); + } + } + }); + } else { + var regex, m, url; + regex = /(http[^<>"{}|\\^\[\]`\s]+)/ig; + while (m = regex.exec(str)) { + url = m[1].replace(/&/g, '&'); + if ($.inArray(url, ret) == -1) ret.push(url); + } + } + return ret; + } + }, + // upload transport using iframe + iframe : function(data, fm) { + var self = fm ? fm : this, + input = data.input? data.input : false, + files = !input ? self.uploads.checkFile(data, self) : false, + dfrd = $.Deferred() + .fail(function(error) { + error && self.error(error); + }) + .done(function(data) { + data.warning && self.error(data.warning); + data.removed && self.remove(data); + data.added && self.add(data); + data.changed && self.change(data); + self.trigger('upload', data); + data.sync && self.sync(); + }), + name = 'iframe-'+self.namespace+(++self.iframeCnt), + form = $('
'), + msie = this.UA.IE, + // clear timeouts, close notification dialog, remove form/iframe + onload = function() { + abortto && clearTimeout(abortto); + notifyto && clearTimeout(notifyto); + notify && self.notify({type : 'upload', cnt : -cnt}); + + setTimeout(function() { + msie && $('':""),a._keyEvent=!1,K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='
',m="";if(f||!i)m+=''+g[b]+"";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+=''+c+"";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='",l+=a.yearshtml,a.yearshtml=null}}return l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="
",l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&bd?d:e,e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));return b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth())),this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");return b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10),{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);return typeof a!="string"||a!="isDisabled"&&a!="getDate"&&a!="widget"?a=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b)):this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)}):$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.24",window["DP_jQuery_"+dpuuid]=$})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.progressbar.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("
").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return typeof a!="number"&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.24"})})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.core.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +jQuery.effects||function(a,b){function c(b){var c;return b&&b.constructor==Array&&b.length==3?b:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))?[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)]:(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))?[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))?[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)]:(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))?[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)]:(c=/rgba\(0, 0, 0, 0\)/.exec(b))?e.transparent:e[a.trim(b).toLowerCase()]}function d(b,d){var e;do{e=(a.curCSS||a.css)(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};return a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete,[b,c,d,e]}function l(b){return!b||typeof b=="number"||a.fx.speeds[b]?!0:typeof b=="string"&&!a.effects[b]?!0:!1}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){return a.isFunction(d)&&(e=d,d=null),this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class")||"";a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.24",save:function(a,b){for(var c=0;c
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;try{e.id}catch(f){e=document.body}return b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;return b.parent().is(".ui-effects-wrapper")?(c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus(),c):b},setTransition:function(b,c,d,e){return e=e||{},a.each(c,function(a,c){var f=b.cssUnit(c);f[0]>0&&(e[c]=f[0]*d+f[1])}),e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];return a.fx.off||!i?h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)}):i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="show",this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="hide",this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);return c[1].mode="toggle",this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];return a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])}),d}});var m={};a.each(["Quad","Cubic","Quart","Quint","Expo"],function(a,b){m[b]=function(b){return Math.pow(b,a+2)}}),a.extend(m,{Sine:function(a){return 1-Math.cos(a*Math.PI/2)},Circ:function(a){return 1-Math.sqrt(1-a*a)},Elastic:function(a){return a===0||a===1?a:-Math.pow(2,8*(a-1))*Math.sin(((a-1)*80-7.5)*Math.PI/15)},Back:function(a){return a*a*(3*a-2)},Bounce:function(a){var b,c=4;while(a<((b=Math.pow(2,--c))-1)/11);return 1/Math.pow(4,3-c)-7.5625*Math.pow((b*3-2)/22-a,2)}}),a.each(m,function(b,c){a.easing["easeIn"+b]=c,a.easing["easeOut"+b]=function(a){return 1-c(1-a)},a.easing["easeInOut"+b]=function(a){return a<.5?c(a*2)/2:c(a*-2+2)/-2+1}})}(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.blind.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.bounce.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight(!0)/3:c.outerWidth(!0)/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m
").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.fade.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.fold.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.highlight.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.24 - 2012-09-28 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.pulsate.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show"),e=(b.options.times||5)*2-1,f=b.duration?b.duration/2:a.fx.speeds._default/2,g=c.is(":visible"),h=0;g||(c.css("opacity",0).show(),h=1),(d=="hide"&&g||d=="show"&&!g)&&e--;for(var i=0;i
').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);; \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/index.html b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/jquery.js b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/jquery.js new file mode 100644 index 00000000..b1b47b81 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/jquery/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/main.js b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/main.js new file mode 100644 index 00000000..7bce6a82 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/main.js @@ -0,0 +1,8 @@ +/** + * @package Joomla.Administrator + * @subpackage com_remoteimage + * @copyright Copyright (C) 2014 Asikart. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +var Remoteimage = {}; diff --git a/packages/remoteimage/administrator/components/com_remoteimage/asset/js/remoteimage-admin.js b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/remoteimage-admin.js new file mode 100644 index 00000000..f014edee --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/asset/js/remoteimage-admin.js @@ -0,0 +1,124 @@ +/** + * com_remoteimage + * + * Copyright 2012 Asikart.com + * License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php + * + * Generator: AKHelper + * Author: Asika + */ + +var Remoteimage = { + + /** + * Insert images, this js file will load in every pages if you enabled the com_media replacement. + * + * @param id + * @param imgs + * @param urls + * @param elFinder + * @param option + */ + insertImages: function(id, imgs, urls, elFinder, option) + { + var tags = ''; + + // Handle From Urls + urls = urls.toString().trim(); + + if (urls) + { + urls = urls.split("\n"); + + urls.each(function(e, i) + { + var path = e.split('/'); + var ext = path.getLast().split('.').getLast(); + var img_ext = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg']; + + if (!e.trim()) + { + return; + } + + if (img_ext.contains(ext.toLowerCase())) + { + // Create img element + var img = new Element('img', { + alt: path.getLast(), + src: e + }); + + // Fix Width + if (option.fixAll) + { + img.set('width', option.dW); + } + + tags += option.insert_template_image.replace('{%CONTENT%}', img.outerHTML); + } + else + { + var a = new Element('a', { + href: e, + target: '_blank', + text: path.getLast() + }); + + tags += '  ' + option.insert_template_link.replace('{%CONTENT%}', a.outerHTML) + '  '; + } + + }); + } + else + { + // Insert From Selected + if (imgs.length < 1) + { + return; + } + + imgs.each(function(e, i) + { + var url = elFinder.url(e.hash); + + if (url.indexOf(option.root_uri) == 0) + { + url = url.substr(option.root_uri.length); + } + + if (e.mime.split('/')[0] == 'image') + { + // Create img element + var img = new Element('img', { + alt: e.name, + src: url + }); + + // Fix Width + if (option.fixAll) + { + img.set('width', option.dW); + } + + tags += option.insert_template_image.replace('{%CONTENT%}', img.outerHTML); + } + else + { + + var a = new Element('a', { + href: url, + target: '_blank', + text: e.name + }); + + tags += '  ' + option.insert_template_link.replace('{%CONTENT%}', a.outerHTML) + '  '; + } + + }); + } + + jInsertEditorText(tags, id); + SqueezeBox.close(); + } +}; diff --git a/packages/remoteimage/administrator/components/com_remoteimage/component.php b/packages/remoteimage/administrator/components/com_remoteimage/component.php new file mode 100644 index 00000000..dc6626dd --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/component.php @@ -0,0 +1,37 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+ +
diff --git a/packages/remoteimage/administrator/components/com_remoteimage/etc/config.dist.yml b/packages/remoteimage/administrator/components/com_remoteimage/etc/config.dist.yml new file mode 100644 index 00000000..657071c9 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/etc/config.dist.yml @@ -0,0 +1,3 @@ +systyem: + debug: true + develement: true diff --git a/packages/remoteimage/administrator/components/com_remoteimage/etc/config.json b/packages/remoteimage/administrator/components/com_remoteimage/etc/config.json new file mode 100644 index 00000000..f09ade0b --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/etc/config.json @@ -0,0 +1,6 @@ +{ + "system" : { + "debug" : true, + "development" : true + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/etc/index.html b/packages/remoteimage/administrator/components/com_remoteimage/etc/index.html new file mode 100644 index 00000000..42682b47 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/etc/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/helper/helper.php b/packages/remoteimage/administrator/components/com_remoteimage/helper/helper.php new file mode 100644 index 00000000..727c746a --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/helper/helper.php @@ -0,0 +1,86 @@ +isAdmin()) + { + JHtmlSidebar::addEntry( + JText::_('JCATEGORY'), + 'index.php?option=com_categories&extension=com_remoteimage', + ($vName == 'categories') + ); + } + + foreach (new \DirectoryIterator(JPATH_ADMINISTRATOR . '/components/com_remoteimage/view') as $folder) + { + if ($folder->isDir() && $inflector->isPlural($view = $folder->getBasename())) + { + JHtmlSidebar::addEntry( + JText::sprintf(sprintf('COM_REMOTEIMAGE_%s_TITLE_LIST', strtoupper($folder))), + 'index.php?option=com_remoteimage&view=' . $view, + ($vName == $view) + ); + } + } + + $dispatcher = \JEventDispatcher::getInstance(); + $dispatcher->trigger('onAfterAddSubmenu', array('com_remoteimage', $vName)); + } + + /** + * Gets a list of the actions that can be performed. + * + * @param string $option Action option. + * + * @return JObject + */ + public static function getActions($option = 'com_remoteimage') + { + $user = JFactory::getUser(); + $result = new \JObject; + + $actions = array( + 'core.admin', + 'core.manage', + 'core.create', + 'core.edit', + 'core.edit.own', + 'core.edit.state', + 'core.delete' + ); + + foreach ($actions as $action) + { + $result->set($action, $user->authorise($action, $option)); + } + + return $result; + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/helper/index.html b/packages/remoteimage/administrator/components/com_remoteimage/helper/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/helper/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/images/com_remoteimage_logo.png b/packages/remoteimage/administrator/components/com_remoteimage/images/com_remoteimage_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..890f4a54a930a59bdde8610c845647a0d47700f3 GIT binary patch literal 17787 zcmcF~V{m0(^kr<@HaoWYVs<*VZTm$XCmq|iZFQ24ZQJ(b_n-MRU#I57tygvTsr%}l z+V||W*Ip|^NkIw`4i63l1OyQvEv^Cr0?P2;1q1ed=aCqf?E44TMdFu>s=b+uyP=aQ zh=_^3ktqql*3jHk#njNm({ap{9|S~#5Fjq1=COM23+sV@(A10#NH$??X1Hpu^lYnKu-|Hk`~RwPi39%c7zr%u|HS@V^k3}1MgPVAXVG`;|LFlb zPX^nJzxd-2EmmJSj?UV*KSEaRo-5{Y>DLa}{8$)eDE8~OnW@+>q1}ap`BCN$@29rfl+$+tz(e!*elvUaaH*80PdalRQt|TS~+=f%!!)$o( zc`T6aWOHzSTFBB_kta+eg0?>?`wi%LcsU0)(#*s*Gi=1;ia~gwNcW%N$Yk9_qpRB! z^zi0U~;{o4G4y6+{}U~c727>{w2b~fq8W8cTY5=JohPb?%_ZsIQ)~J)@3HX0iu*T zqd5Hf@-ksdFP83a>z8_Yi0yVKx*CY`xb&`Y009Rad%f>(IA5kfu(`Kd+rFP6SC6~} zP`IR_KW8Yy#RtZaaj~2SOL6WULncf^B0x}2&q3|#hJ0^d9(6N0G9lPc?S`S=%sAmr zY9vrQ!gb-+Xb<{0VD*e}lOv8j{4L6)a---BlLVR<4mhNoD&t~wLY!XG!4zH@B}DQwjq^&bF0J3olWM$)4cWit#K-s@G3 z+}K#rR}<%CDwJ_lILx85NJ?o`FAZ%5cQgimkHx3!Ci@q#1lnw31Y8lD3*9~yVQX(F z`ps%>+c#_xg!!Ba2{c>tDv6`Kak&3)%`Fa>K|=#iQ!&Rc&K~$s$FMLP9)38HauH=yyB>LWgG|9D}sI zlT-}vgD}|?sgadpXz980xLof$xlJc+!b$vqW2uEIs#r%?C$(?~;WF1>U57L)B#m6_Pys2DrryrZ7Pc7qnoIwT7_((%vZjM;IJW)2rKbHc{{`JuED!`M~Mk--~)p@^?6blhLpt_%KGF zwj#P(KCLvpIjuY^WAQ3T8GK$BGiyt93tmZ!*MD0MwC9Qlu&yzrkOU^E|2&)sLuvD2 zl97h_m<0=$xr!xR3zu`VkG;^0E;7BAuu7{#+8!vxc666nZ_8t8AN zTqSr^@@#gR7qpd6EjI_7S3EAcD_yub+$BT9_qEcT6I1l_e=?Yz1y~)OinD%-cNNvv zbr$cnp%*cqLns5o(k;@|!V&ICoYnGJ9_j8s;1H|)17t2y+M>3~b zj;2>C7+P1Mstvr9yR4;7d$rfn>nKFfAlBdZ!p!eOQJZsgv1k_*kg#vur3dUZGhC`G zDan}-h)f&^o{xz~WCNqOZ&4K(GT{YTkA93yxwMN76?ekyQXi`#^~Iu%4j|aavPg|< z|8Z(k?mb$5Ffn=_mL0_15xMIXKruw%wRaY5_ZX8q=vo!7ZS%(%EbKfo;#?5mp9sS)TiQL= zW)~wpAJ6Uw@w#~7(jh>!KorOue4|3?3vqmYAh|0qUqaA`DmND+xRHxxZsP?4DGG>-!4DLcRn(F_Wyf5%AicdT@als^{l>bRL{eQ?zG9 z*TW)?k~uzPU0$u}U`n@w^8>XGoY-VpXyt~++gSa+#^LoPKV8j&J!5$Bg$sk)BUumzhx z($1^Bdl|RKO+~|?@?s#l;z29?1X~MyY?~q7A=6V>OlVf{bS@D^!%|XN8ZvoiND37; zro(UlSqM1bGoR9O^QpGNmM}1T3Gh_av!bP5E1eZ4crNFYHP~g#{;GGxvwt4K#+@# zg~HSHHlnSpjGVNj${-Ct`kilrfDNCb*a7dn2IiD>~q=`;@F@XXL6UF{&<8857zkIyIF1-VCC zdGh?tqo9YtgQ=l%NJzxEnApJJ3D%TtV2^;W%oYnWVTFUDvx}pkDm?w#Cavu{ngnsi z=e5O{rRLS-O?0V(H2ajoQ@QQsq%>z%MaL3*Fog(SeZZ4=^|ZzP@FCI=bc)rI zxpIjrbfgZP3rwX3Tuc+^0qqfedff$QIX{!@CfNdp$F!nN-%jy4m zA4I_q^3QwQmyO_uQJ>#|C}55eJNPvr$^CA={jW z+Fcmtp``{le`#%hIB38m;0!*#$?B3Ra@=pKVG1sS%lsM%saTMioN0dy+vGKyamZ4A z?K|rt*FZ~2b$Q;b(iG2D5;1M5R1Bl&yqqb~Dx{c*LPVGQCmN2xslJT?%VVvYe|QGtOQp+-)=Zz9nTd4W^Y1EZ70MHGboe0%ir^tG2kNh;b;V9=1} zU5~!~aj?o1S~G%K=*E?UVl&e%Q4BP2up5o*C)cm8zmEDkSNR~o{7FuShbCB(IyDxK z{B>`W6updmeVusEqga!NRrOu>XKEG)tQ&Kib?pP78q(yDb@+!jSj~73LMv>`A?=~~ z&(BQ3i{v*J;5hEzFi4Rp!nJUAi};q}$<3;(OhBQ(?5q%!nE2JCe=-3-eYF<($k+Vi zFng$UjgIEcsX=0BCjSFs4ZIw$llHRcgJAZ|_DzPzmyEO-DY61qpt$ZG^Fs!a{R7!F zg7RQG%%?qEBT_0Om0Zk;hyG_^XvNUiw+Z>Z(+`g~i+EA~@7D-0NDgRvZdgh{>iSKC z`O_$8mOR{Sn8QBmWiVz79t&5|M(&?vM7X%Nr!!t^FSzdHd7=&1J59}>xP`y?d_lJx z2g7yc1sZ7CWu_I&2+J>UEKZ5|XIBwdWq)juYHMsyJw85i;^_J#)1UEf(b_gX((*HC zRUj}INq9#q@||~V&R)g?Rh7=9u*AyK3)IE(g3%Dx(J&_-jIrFuF9@1q@6Dy0SGL9g zm#P-ANnEPqVl$0P3Yn!=(XjB_ZynwB|03$K*7ydW8_E^~r4|C5Dx~L)Jc80^jWDd% z-U7TOHTt<#PqCCKxcKBKe$XG()2bjKtz{Rne8c?P*}f#ODp`!%Kg03V$a+36HX*Wb zjbmX_uh31-@nTs7EMiStlp;YVSkcf6*^cy-Y8Kd=Sd2AS*)w23!ryczCSY9G$ry^( zl9m^_hbAN9Of+rm(auih;JLlZd7z;@I4$dOgysVTkm%c&wwh)_MI{u@9Z6_GJnhef z{Sg7;jsh>;dYnIuU0nQEhK$BMCUUZFm9F!d6+laVt#e}<^M6a zBCB6v%rdwf2VBZQ0Q*@aUZoJeoPi5XwOBqa>|ty>wFGY+4hxY&XBufTsq`@|-M7$u zs4$f4q~J6H2KfBhsI zjXb3gW8&p`z!Xb(j%TByc{x{A|JjL9re(~%Hs3{)Y4xE5lBm4QQ!7aOd%$pVhH*6= zcYGcPQc%!VE7;LSj%jH<6(ucMI45Yr=oRQ8*$4jwJHZfIIswGwO><13K|DECrjmft z)b_-lsLhAd)E((1v*f`U1K#nl@^Y3?x4Ww1aR(-S@dI>M<3lC5$uTBp(&T9OmW`~@ zGA0R#2z8UF>JD!M4Tqne3Zj28aQDV7;vT+7Kq-*m?4Z^4uA(Vtqh~l0qcQ!1Hg|Qd z5iRq!(r)HBu)I)VKnsh5Sc=6(B|C34R-an|@$hpmXP-99KFzN}15z{wNSqBuLaZlJ z%GaUQy#T$yjEy6!a|o@@ZLWwQA}&)ZjxHIL^ZMy8K0rAErHjbqur>G-O~`xfKZ|95 zcgT--uGdqItKXPv6Nvap(Hujq3%t6?}DFe z9VcU4Hx7Kxkb~!9q$~)QQ+R4l8heWbx_M^B4ru{~T>&uiDZY#oDOdt7CfQR!NzH&<_nY?atkNgAN0(3Lw`~BT~lk) zcj{7}Hl(KdW%Gx@gizc8Tch~x%r%>}VmkOY3^D376r@H!yAdtn9xEPtbGA0RKsWvU z^7|tSHahsT4Yp_CIfxaR7geTZHKWShr-=khpl&As87PF}ov>(5;6QjRb}%;lYIc%d z{j$4oM^TC$f?XF!wiiKb0L@KtspwAuJ*Tyqf-0GeRET%a1siMEft3;uS<0#+&z8c8 zVF*|rzhWeGOor_!AtarD>K-;~g-{y*hmr4M6@dAn1Z$S@x~BFKAUJ1dpk<-Wud` zR<`o{J^OJ}mryUJ@f4ETkBUa#KSxcEVk`xxdrE~BdTPxO5}|%X7XeFT&dH>s1at2(+l@JpgvX!cogfQ^ix#oVBVd6V1%!a^+(1I_+$*O{T zfME^f3`JqVOaD$@cu-JkG&kZhFt#b}$-p!cL;J@G6xMcLl5FC5wy?IVccy488I}u; z!`)zIULtWb-mYAK8obcetIQ!h<{d3KLgoHg6n)!BXqR5TXJVh^yrmu7c&sv+B4y5tP zdKHQacoylI0|}P?@^bRGqs3GL+L_y~&L=7(F3$Fq<^wh=N@mUQ zldSuz*fc38v*dO^qSNIg&hi{yuOX#xURY1$ia!D~sp9OX%%uCXznP3|k+sN$_(kTs zoy1h!xL>YVbe6lfY16~Wh8V&I5J+$c#*f;E=_5o+-~svixT=xTw<2qQ^0KjkFN|y- z6H75ny$AvQjf3}}S)_X$V9dvC%PAwd2<($ zlrMHF>Ol{l_jRQr$~jxdlmycY8dME98vu)nW`REutODYM`=g$JkdR(q3{OxZhr+G+ zF|fuBm`}pOcD%Bu-FaUye>H5^P)=eA$)G#zQL{NMQYo0wQUHed{jtW>@gIK}f(Pe! zdzG4?@|H@Aj{oXCIM?ITl>Bg4vW;^^Ty!4|44k^uL#Nqyd#WfD{rcPf58ae;Q2Jhn zy`Vu+AVIvw^Z&f(pi{0n>XP4Nu zv1#582WMRAH4oR&Go`{@`H#-(;oVL1Uw4r1N@5VprY^QCFtg4J{DMV0&(Bs(|&{BM?A@PGxQb>Q)1&JxZmc$XnAH3qrt5 zh?9g|P{_%JC{ADHrZ!C756=y0pFocJnSjuFD6j*Db1!z~>*}dn{O7N*utzw`V`Ciy zX<)fqNMduW5Imsucwz>U-#f7~C)qfQkYL*k`TSCF@@?-d?DIT1i2^+GuU7k;I`Vpb z&}15(84f;fmqU@|=#Sfu4le%BjV2!~Bq{Gu#nu2&m0-i??-uSfS=zt3Cbq>JK|1dF zX~#(v3Q|vDQyrM*Q;jm(lnUHNCAOsHKtxe-$Sha#L1SbNZ5KfX_Q z@nok(6^%s2<)=d4;JYl7gakMi+-5|9l|AEa5r-6l6G$jE*_q0QM{MlUScA*= zHJ2S_%?>xwDw_Zly{Wc&1CjpP2*dA0kHH2y1NStjpgx$?ng+IV{Fzfq30l6yAzMQX z`+}OrjR8{egA2t(-bjAsr9`NU=S9tm0v&zCb?t4c+SiShnP!!+n(-ZiKuh2c?m#_y-1 ztfi$nOr%Wxv`Gx5ln5WCq%2O0yetibc+|}-jl2tP8avD}qf8a$&=m-l)4!@}D<+&s z8D;&qPq5g6WWwlbL&@1v)_E9O!CEB;2i^>#C`~;{_Dum$6m+!ex;3`0C& z+1kn!M8+O9oH`4qv5Y(fLZpZ3$;CFj#!Rj_e$G`nUL%}kw8v&vRF_{^T&T6yr3Fwl zMiHhJYoSRn3M}GS%w+Sg&f4PC;~h_FqqcCdAq~!Th9@q0BxrpTk)TWVsnFUkvXW6R zC3HoX!>!@MGxIoQI@Ms8P42X4DL^~@oP=}?fNl@s4yqvOwv@KY7QbVYk&+k#qo`e& zf9&DXYO0=^-qyxq&8f!On98&o$~ObppXZZYCg=NN0y9Gj61Z~~sY=hjN;-=b9ocMP zlS6B}nbh*f0c?%$KyOnIwNG@LXn~EO-ndbz;9;HJ?nzA)fWpiuv(KT2{inSvzkB=< zLP$wk^sI8F2!HsfN-OHG+M??>iRrCkqymhYd{cnmUrRhijD_OU<;LC|Yxsl8&zVB> z37Nsh&`WGHFA`E*T}DkOih;>=YdFnz!c{E;qPqAPVWmxwsy=#SOa@y6&!Pk8AKUVT zdtN;zG06ws?iF2PI`;_LCflN-omb>tTcnyzMC`Wq+aoOfZ&S^EVitwm$3?fs=G2mf zZo|Yy(P_lWFYSDW$}_O3taEmNvL<}ukaQFxM@gwdK~1@(kjDC;QEPokd?XVYEOwhV z4*7N}ngx^kUm8Uv?ZYRhzj!k*92dQt{y7zNWeI7T*~!EMVAcAnCHWfFhCh7t*Sm&4 zi`yy2|DD)|BU0v$0YB#!JG*$E_;A;C865 zuWk#QG%KQ#s?tY&+PkWJ*{A0E;^$gejo|nEnYWgpG-`S=7D3G*XSCzNoROwqeB%E~ z`+#!CgIF(kP4{)=0?B_hb|Hbu8X1U-^1Hmb`@2{GSaxS-lsO|=ri`CV%wQciyYqIW zkg)upPM8Vg#|!iGOan%-Lo(1Yi7c30hU)bI79h_2D=?o`WmgQ<792QHWq|k=I~mz< z#DetVH$}Dg6Vaq5XC8qH6hQ0p0NY?je|a-(@k>J$kBtEemK&0itq@kC$oYGiy{zCz zF#_;r;XAEFsOfUI%!fm>E(t)UYU_0W9n}8O8epVNfNVRxGF9-bD)EA9d4E}E^B20v zbk)+~Ks8?_!ZsA-j@O^<O>Ukxvf5iM*k?aY2Y<w%sKop%6UM2Cf`kpqCI#Kyiy*ZPiax1k9SbN#a)YRO`lxiiXPt00hZ@cbp)R0ED zqhtEIMih+^0kIt_;3oAC-9u=02 zW`;?yAIM&u<1lC{4a?NH>dqm>ggo51JOcR_v~rA_ z|M9z#>)5q9VBhTE_nSL~AoFOYRe3M5m-z;OPVXSPD6FUso~mxsa<_*{8OR^Y+WYO$9i?}1zu6`T*OP_!L~vJ833XfPV``8TqF zZinoH{iqYyqz^$5nyK=NS~(b17(ODzFV+Z*8_dzuyB+kkww=-)FBwAD*eIoBE~4R3 zU|F=C6ZMzdUVk})$Hk4dfvQM2F1N>{veF)gS*yZ8S-FaRx46Y_tjjzC(y3b<+x_sM zvG*(`-N#o`es4l{J`Z=1g^KWcyJf@K{`~Djl1t3hr;QeoZZ5Q7o&*LYtsw?K)tVoR zh9Ib=gZB#a9971{!0w*&>gvkd6$}bqJSM7GNWZc2(0K3;s%dR@k8{%p1;i%?`;)_a zswe&KBMeUpy(#@Hg^*^}dtXwhRRL70B)1mxhIeqy6_Dj>>LK#RT(wF^N!H^42;rm| zC82CHJObT0c;!a>d9{owI@UL@^YNaC+?~^4Y>ehQGEic@u$sqb|F4x-P(3I6gq8DA z-EiY$t^T`gMxfoP?)HzW^ssS~2=^8xgCji}U;aXKx@u;ZGXDX(OVRhOYd}aK+58qQ zbbIz!do52(E$q3nW|(}CxX=SXIidylks>j8uhCY_?r^$$1Tl5`x_D>@l}t=(w~@D! z_bH?t-*F;Kc2!M0NIW9cn+W{{RRKExy1xE>S-LK<32jPq2O_^u8Iq~8J4U4bVv9>| z?E3m+nOoDL2q>Ic1#i=FZ7+O~Hl|)s;l7?mJkyZrLdg~r?Pq(Z=@BVvp=Shdhd$@|+%m8!Ao7p27#eqCM-VXOGB5`*-gf>j<@OMHTYIwFTwLZAP5 z$mqo6SAWvF+B!Y#ZRuL`VZoV|>j@RI;f$YkAgi}%Mn(ELRx?>!wvH$iJt?8VwN)Nn z={y{JA6b~sty=h{g#oRWKzk#@0N`i8sb&NC8+T5P*O!(9Tmb4f zOksa!#Wl#D;!8YXqgFIId%rx)Tg1Ee(96CI#_4-|~71YAx`mP~sm;=tJ z58g^5LP!!i>PygQ5kq%0{;8e+jvNg~HfQze`CH@JQwiYWPe8?@S;ArMmmt8pn@bpu zx+dus>Zon^T}v*(S= zR2`b+ZK+DM_e2MRUUZ1;O-%0h5|aW6iZ4(lkVfpqyrLY1RV$_&Ef7aC7%C6j=*9lx z9PQi$trGG85a6g0U-QJwEA)Bv+IuPwoJu;EwtwB0*twkV(KEif9sDlZSuD44eJcC% ztee^O-LCZ^7bl?Dc?erCboe0?CMkJQe-1yc`@i^|FBd(wpWNeAAHs z+E?92K7>eMpOdWMsXPL5w#u=cRH+)DhO#-mx>dMn8v1*9czBtCO4=eta_UEnmu^S1 z09P7IngXo-F6C}jTHTqEDD<0}#y+}dRno`btdm(BCaFB)e3obmLswsojxB7#h~st(=Jkor zGWqU}=l5jyXf4zMQ3#_AdOMjP+6#4= z9DN%2=$$G@`6)m5J{}Afde07!_A_E8mK6di-L8!;+!v`>hTr&Yck@+*)YR5qem#MJD|jvOZLAJzjFI`P`^SCiHiPVsDcjsDk6N1 zZRr6$a+6ZXk5+ydz3w%4t9~8&^tp>&ZHGor2I|q+Qy!jxeQbUd&uhJAJA)WM|HJP2 zeC@I4a7R7zM08N=_w4_@jPe#e3)`VqMPGgvcg-Wz(jeM%`-V)6n-{-S{e$ z)4pFGK1S(Zf1e$y>|ov}B6>qb&!$XYURXT+rKwnm*9!B>j>Rf&@ek$bkPX0dW~3oaek(hu_56~g-T5&v-fBV%I_mLJ`#C!a9yBR zUtoYm#k9vNzrF^aU45*`kt`->m}~~5;`NH5wS&8v$ea^*x6nitBZ;FT z<{oTj{!zuOn%3;e$+(?)so-?kGYK0z_3o;rDhk!8%3QuUn7Zrf5p;cO-!Ddbsaqtf zpF@X;Q9gV3@(l(zPZr72N=e2Mp{kEtNR|wfx*gYY6&s*eCA(Zn2Uu+{j~?gBXzNgR zsBICFV<{yXmu)iJOeF#(q2Ql&l10nFSD>@6g!JG=>9U^ldoObA(nKoMdiDC9Q?`nHC@&dhO{H9gP_488kfEfzz;`gV22HY#Mg z_=-Xl7#jVAe)s*JIoxWm6&hmt22&6VyT)?5Rm-LENHNfIHs*!t4Yh8|pbsojGkY8T zC2kVsOpPIn2hk%*h5As^Z3)54Bk}ciN|XR&3Y#oU_HI8LHoee=yT)YO6}22@=WE9cFam98dpcESH1Xaq`kZ_6Axq>fR44!wj{Zn7C1 zOSzLC+YiC>J4)gljQ$H7mox}lNuh${&yu@!SZD*ZLu4+$m~b~F4{=t#;)r>jw8mLtubU|Rud$t! zy%*eh#ix@W|70frTP5dy!NMg8@n5sCxV~@hUeo4jOZHH3hy=NVk`SI0p3_4=HKQsX z3CRYxopMypRRds8VNOzcdhC<+-sFEhzfr*hcOQ~ikH>LUW%sQ^bb$9hNS`QDrc}3O zv~9kfSuzD!pAynD9$Zc7Ve+zQ?5Ry{f33N%%<+;AjPHT+`&pe8!ipPdP@od+NDt-pL~W>}N0G^LR0uBEnDwegVj!Qr?y zoVr=N_%)xGyWHppZ;RPCvlFlJbntatz;=j$@dHNq3TZ{T2zhP{~6OdxfD^Av3QxgluKhch~ELBpc)x5l$|2U;vYHPtV z1QaO5p-q@h;@1%nKpw_>e@|`MXQVs?ph`E`%X558Pb>`1sgRY0P{V+}&vZ~T9Hs|? zbbCz=@66OeM5OW&J=$EU49Wye5)OSsfAsSa2+#GmO;{zZxIS&JB0#~Q|406{iJ?Gh z?(j`x_vWU^kOw2}H5$0Yd*k3JaQO#k#=;EkHxmNUF(du93OY^;w8}amaqfcRPMG%f zfHA7)V!I5G=MK$PiIX6}izxKa-(+^X+ZhzXA4X43gi9ZA({CC(*&{(PidMK2)6E4ts4g zWzB}Arm|^-<)V00GH&>D&eGY0!UZctEMi0lJ^Zz-fv~rsmGU4N|Z!&sfR4g!9y(^GT7{?kpCa66|h=^f5olSic%x1S;d*tU0@ktJouxU4hDJ zFYNoB3BYKzVed(sb!)xjV5H;cr;Rg|>nNzrOzCy+93~aD{HPh|nO$^R_@8V%#llcV z|FtZ68&Lhr`64LJks8J72Ruc?SOnyARg2CMjvw=lTIAS1qU98`%dO60bo@P+a@jx2 z32-c?XhPN)<{~K?{|~?v5|Lx)k6zd`xDG1riPM*Eb{fNOVuHRN~ zuj=$EfLNVU%H~0U*gxI0iHXM>(46UXiiB2MXI|G0B)$>YjpBFCglW3j0ts`!o{V4n z(`2k@{fGOVX7EuwaQau)SR-3`1wG)i0=OK6ghZMg*?nS75|n$gF{r3&MzpC9^hK6I zu*6Y1>ANdoTo8)YD9;%mkk>=_KL_397fUo#2;udJJ%5R!F(#2hdWAN6BH9Bq{o111hdDqz z5|S-Q32sLb(GgyX8>2BQH0<mN2Ml| zbB1Jox=dRk=B`cou{9;1?aVbviwSr*1yTiz4UpHyibxSlcY4?)s$NZ@O-&g8gWCNOuQ| zpo}7EOW4)8qr)6@Ezzjvo?Mi{X(M{aMkb4CKX>oQmY6uBC|scV+t|*gnM>NjvEQJ^ zIFNN?1kZ@n&I10<6nr?2z&W&+YMT&(k3?ozoY<87#^XCEZo@V zFc*3npe?wctohv~2hOM}No!&Jt2ThjmtXKG6w@(GL8H%Yx>w)VtJgf%zTsxQL$t*HXXt!oT?i(!(G10FwiS_?1lo;F*+(9vuc7Dg5@7H{t0IL zg;g$%v(NoebHC1bf}-dA1yS1h(i;?}fhFH|rhoYkDrk4~9WI>E7wIO&w6Zb9GYE7| z4a_t&2CRN9<^nIwD7lK&#YnK_YV9$4>V~dTwE^0sXB|(&2vm_fduME%R<5%SPI7Te zA&yt^qCaYGcHXe<<@|5g;K)Q1Gf>H+F`AnZS-NU&sAVHAby8fuC5E;c$&%qEbSYci zqV3)ut2lrJwM>$xC%3ja1A&BT0EKvD`KlUu!CXHM)WG%3yH=HBYpb?GRC6HNMmuYt z(eW19-!pSzggtpvX;U6#}F*J579K`llmFy9@McB>E`gi~bWQ3WYn*M4Y zB&d&3STA>Ns(Xi?^hG0L&sbA1lC+(r+Q}m`@{_KX8ONWeRcX!4`=e>R$S1PWqSUAi z_u3=qT&~u97+ysxBL+Wsy_4q2SRmwF;qEH*aj8j_<{#%p;`+YjR%Rf?c~apDFVhNc-82ZIJVU+;sP z5kv8$pqzs8zq9if5jA%j6^Hs^ec@}3;4rB=3kSTV2 zf=f+b_p2+veF|wceUG19remo2)kH!B;K?9m>cH4Z3+g4QfB_b&su>1FRmHcZ$=p zmEov|+{>5i{;Beg(L1t&?}`OSn)2}NGrDe9TKl+qe;p`dMUiyCCjVG@(tP<_VqT%+ z`q-mm*`EXQ?W+?0wq$kw;oaMrU96Ec#V+Tq8Zy)A_=oy!3d@Dx`^HWlp!m!hPxr{B z!9mY-O?tgYAkzS&iJgV8QMKlw= zEm?|rL_-&GGZ6nL4cd0bku?t5b{)r4?Z%-o`R+b^bWOA=G!qdIW zKm4CMT)$szBK+PQ-59*kO#%|0d#^BEpktyb=H9RGG5be9Pn0mx_~b6jcNP#a=_CZQ zqXJ@3he=0bF?aGYw*w>~LY5iyk>*l{x#lFFobJ9kaD@8zw|d|Y<_>zuISVX`?cYFx zwapatRSBwkIoqAOYw8Tt&813aqo`j%9NaFq_WD>4eKk_=irnSYh!EkDPlGay&2`S7|9P{y|Y4-S*GJq~vsfG_d`4g-S*KBa%Q2jm#$8 z(6KxM^gnB20~nP9 z`Trk-;?tlFHqi1!^~(25P4f(-vqy;eB+1*!=IZNnWtD9q>l$w!H-Zsgg=`yg3vs(X zd&B=_p#XF6acir2x6bzDn(D13r%%%YAJhS58TT{Yf8PRrkLWAT1{u~u-Ar!!@|<$q zh-$G07;NKp8JFd5wp|5%v2w95;ErI;-WV-1UJv1TW7u{E=?J?&9Hjp#xA4pUf;-~r zLf2`HaJ~Rld*bQ5+oAfr=xEHpg^1gzTk(xc3hJ-SAH;{(Y&)u0=*fUbar=!vSj1q( zJltszAcO}4H(0qS%h=w}qnPC5$n)l!##(5%SDUizx-#d&>YFugK_#yCqM`@^k z^&y7{6aXaK&}LLVgws%+?_q^`ZbYvs8QCqg3;zReXvEO;w;Eq>FA1H`gI{YEx@ zx)56O7?cI!k`^=d!6=?O0WUMb_4a|;DV9>(O5-$Cz(vpVc7G5K-Sl1c=LhrSIluy= z>I|JBKact=vx@k>=&0)9M=k{W@Ggrv_+7HLaXos97zo9N!e)O%@9ti&U;moFM75ge zX;0Bl3n(-b`DvK*f62U(QR9+(jmu8fE&X}pb&^E2Y>bys6wqxAjs)fI+X?hefr>Dl`O5HKof0GG1~=>r zU|-RNh%T3N3t9N8WCXkqZ%4(r$xk(k>89{yw!wq}J1rk4G)W!~utICebzeu?WfO&~ zE%UKPgFe)k)H|}mHSO>EJ$Y!z?RXbQEpul9%(HF{lPnHE3q_Y}a7#r{61q&^A%7u7 z0r-XC0>42-_?)61_Kb1TGKoZ`=j0*IR3ZIdSO^W2cj0H{ZK@xh?5@SA>Ty7cb?;ZixXvNY}SQ6e@%%t_r+1i|Gb3-mPS($`>o!pZE3{1Khv+P>3fWW9Ts&pV;{;gs zYdTjjxJ^!HK8RDGpme!*2pq1z;~cr^#c+g8L$Q@5Gor$0V7XLHXkwGb#8eR&Rj3iLu= zoPo`zmo8ID6ou{DPs)v>`9{-n9BbbbUDmk2(ART1v!Yz!D?6o5B9B@syEftAP2;ot zDk;#?N4riFgre8>wm8@Wcn|M53)K{)lcnUriCEDB=|j)wpW_P9_{dl-%Rlh4?D8@K z@kB{@>6`dg(GLn9ZScE%;`Na(#zghP+jwMDMWw=Uu|k1r?(}mQc&LeH89aT-Ll84j z!(H}SPW`>s7aFRx5D0~MpJ3a0|TQ;|NYGpcW?1NDjM)!z> z6~{zry0rJ=6)Gbk$VPfvDP$Bk*pNo|`txWB%1=;=+zs_69Dd|zMaC~rCFYu@%^N3d zptg^Kg>q#f$@4h!G@^>;61c7>6a%qx81D8ycmbm2qbLap08}h%1?*ogxnb2#NU(;D z!(vBT((JUyVON`vCB|yjxF*xhr|l5e!UAq*kKjz4vanHQJ3K!RhAc2YhrNpdbNZx4_V#(R}xzB#|m**%BV!08k=h6k9G3fC; zRgq$|WeF*TcHM`ZV^qO6KUP-igY3i~OWO`rK?iApl%iAS^u(qkWWVo1PThI;x7iuG z!V)e^9;Sgqf=}&^OQ3T4M~1K35z3(XFpm-iuGZUv+7wC*_*c4l{$z2;A+;-e(?SSB zBe#L6VmSu?$xcUOAN#S&9f7Mu{y}v+fiopAD}sPM(k_puw=Xz2z?KzTgPoqTuuZ!# zO)8YwmQS}AsBt-2q?yz_*HH%2KHGSob7ZBvCdxL|;F;H6nYA~=Nwm*-KWND?A08r> zVtj})th!<`!`PYq{h5kMJlfE4*~AV7)=oDLWlD1j&k1bfPc~=D!;3uOefe;4V8KD> z$h!rK(bb*kzZFxv%};TEO+uBHnM3q;Wp**|mxdhDal7y|UYKN*$>~wp<*`u|Qko14 zd>T$8Z-rq0N_yneWoJHXBnLn4rA(&;yuC7LTg;xG9Ny^1s838?fo4ThHYC+ zJN~b&+?D8jd3vVxFoRqmSAQw19xiQt$ND~3D)gDbhIAYs2{hIk=?pq|J;t}IbPd@L>X zbH+_gT%0rWmE&s7Z?7(LZF(%^C!Sa=^i0Ndfz#UkPo7q!Evq!-{uFa=>xD%JePk~+ zcsG2%)|IhCY>S7L&5U&8J$dQri@qM(mfYU?D5)STsvskAuY0v#`?o6#p3X9Tf8X8i zF~{}^(|jJM9)EGvY0`vO?lX86`dcTm5cD^}RgclO&|4<>7+ z?UBj)wDzZR^DJ}c47)qISy6MYS9}xN_}s=NKvr2%cTvVUnJ9VHSkpz?!pyI~u|&;j zyR5sV{rS?h%%9zyURYiByy5U#Y0D%RvDdlhBnlV)Y}s(yE62~Bh4rs4=7`r8JruPRo3YXCpIPnVR*|!gYjwZ#pShB1xX!b`Y*#DC z`j3g*CFOZPhkZGi86mB>W!uC%_vi5(+}V(<0?a*P>S6(}mrb0hZT4*c{rS_MOgiK9 z$OTwU&5GU;V4LaKB!9qA`s&JskM(|^zpwMpo%3wTb_@2_teQzp{7U)OjJbVp3XY$- zc=_^jwTL&1w`A3y`gj1?sEKG}?~Xpeu6)MzM^#!+MftWXvl`P4S(23XoJ@|r6pONH z{hKH;{le9kC*O#bZ+p)1EQEbwb8o_wZ%_QEeqkwcV&Ce{EL&T4<9^X^{q|P^QQmq> zTNB$%vy#jOoOeVl`epHuM|d^Ef%qGF=N(oHyL{bO_Eu_EBF7OXrtnlJ`ke6rIzWV^ jLqe{r|J%>N%uxBJckcZoo9_ZoQ(^FQ^>bP0l+XkK5P&R> literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/images/index.html b/packages/remoteimage/administrator/components/com_remoteimage/images/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/images/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/index.html b/packages/remoteimage/administrator/components/com_remoteimage/index.html new file mode 100644 index 00000000..42682b47 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/install.php b/packages/remoteimage/administrator/components/com_remoteimage/install.php new file mode 100644 index 00000000..a87f0964 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/install.php @@ -0,0 +1,108 @@ +getParent(); + $installer = new JInstaller; + $manifest = $p_installer->manifest; + $path = $p_installer->getPath('source'); + $result = array(); + + $css = << +#ak-install-img +{ +} + +#ak-install-msg +{ +} + +CSS; + + echo $css; + + $installScript = dirname($path) . '/windwalker/src/System/installscript.php'; + + if (!is_file($installScript)) + { + $installScript = JPATH_LIBRARIES . '/windwalker/src/System/installscript.php'; + } + + include $installScript; + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.core.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.core.ini new file mode 100644 index 00000000..bd55c7dd --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.core.ini @@ -0,0 +1,64 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + + +; Message +COM_REMOTEIMAGE_N_ITEMS_ARCHIVED="%d items successfully archived" +COM_REMOTEIMAGE_N_ITEMS_ARCHIVED_1="%d item successfully archived" +COM_REMOTEIMAGE_N_ITEMS_CHECKED_IN_0="No item successfully checked in" +COM_REMOTEIMAGE_N_ITEMS_CHECKED_IN_1="%d item successfully checked in" +COM_REMOTEIMAGE_N_ITEMS_CHECKED_IN_MORE="%d items successfully checked in" +COM_REMOTEIMAGE_N_ITEMS_DELETED="%d items successfully deleted" +COM_REMOTEIMAGE_N_ITEMS_DELETED_1="%d item successfully deleted" +COM_REMOTEIMAGE_N_ITEMS_PUBLISHED="%d items successfully published" +COM_REMOTEIMAGE_N_ITEMS_PUBLISHED_1="%d item successfully published" +COM_REMOTEIMAGE_N_ITEMS_TRASHED="%d items successfully trashed" +COM_REMOTEIMAGE_N_ITEMS_TRASHED_1="%d item successfully trashed" +COM_REMOTEIMAGE_N_ITEMS_UNPUBLISHED="%d items successfully unpublished" +COM_REMOTEIMAGE_N_ITEMS_UNPUBLISHED_1="%d item successfully unpublished" +COM_REMOTEIMAGE_NO_ITEM_SELECTED="No items selected" +COM_REMOTEIMAGE_SAVE_SUCCESS="Item successfully saved" +COM_REMOTEIMAGE_REBUILD_SUCCESS="Rebuild success." +COM_REMOTEIMAGE_REBUILD_FAILURE="Rebuild failure." + + +; List interface +COM_REMOTEIMAGE_TITLE_LIST="Liste" +COM_REMOTEIMAGE_TITLE_ITEM_EDIT="Editieren" +COM_REMOTEIMAGE_MANAGERS_ID="ID" +COM_REMOTEIMAGE_REBUILD="Erneuern" +COM_REMOTEIMAGE_BATCH_OPTIONS="Batch Optionen" +COM_REMOTEIMAGE_BATCH_TIP="If choosing to copy an item, any other actions selected will be applied to the copied item. Otherwise, all actions are applied to the selected item." + + +; Edit interface +COM_REMOTEIMAGE_EDIT_FIELDS_ADVANCED="Erweitert" +COM_REMOTEIMAGE_EDIT_FIELDS_BASIC="Standard" +COM_REMOTEIMAGE_EDIT_FIELDS_RULES="Zugriff" +COM_REMOTEIMAGE_EDIT_FIELDSET_CREATED="Erstellt" +COM_REMOTEIMAGE_EDIT_FIELDSET_INFORMATION="Information" +COM_REMOTEIMAGE_EDIT_FIELDSET_PUBLISH="Veröffentlichen" +COM_REMOTEIMAGE_EDIT_FIELDSET_RULES="Zugriffsrechte" +COM_REMOTEIMAGE_EDIT_FIELDSET_TEXT="Text" + +COM_REMOTEIMAGE_CREATED_BY="Ersteller" +COM_REMOTEIMAGE_CREATED_BY_DESC="Ersteller" +COM_REMOTEIMAGE_CREATED_DESC="Select created time." +COM_REMOTEIMAGE_FULLTEXT="Inhalt" +COM_REMOTEIMAGE_FULLTEXT_DESC="Geben SIe hier den Inhalt ein." +COM_REMOTEIMAGE_IMAGES="Bild" +COM_REMOTEIMAGE_IMAGES_DESC="Hier klicken um Bilder hoch zu laden." +COM_REMOTEIMAGE_INTROTEXT="Introduction" +COM_REMOTEIMAGE_INTROTEXT_DESC="Type youre intro here." +COM_REMOTEIMAGE_TITLE_UNCATEGORISED="Keine Kategorie" +COM_REMOTEIMAGE_URL="URL" +COM_REMOTEIMAGE_URL_DESC="Hier die URL einfügen." +COM_REMOTEIMAGE_PARENT_ITEM="Parent Item" +COM_REMOTEIMAGE_PARENT_ITEM_DESC="Select parent item." + + +; View list +COM_REMOTEIMAGE_MORE_LINKS="Weiter Links" + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.ini new file mode 100644 index 00000000..e217a558 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.ini @@ -0,0 +1,78 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +; Main information +COM_REMOTEIMAGE="RemoteImage" +COM_REMOTEIMAGE_COMPONENT_LABEL="Grundeinstellung" +COM_REMOTEIMAGE_ACCESS_HEADING="Zugriff" + +COM_REMOTEIMAGE_COMPONENT_LABEL="Grundeinstellung" +COM_REMOTEIMAGE_TITLE_LIST="Liste" + + + +; Config +COM_REMOTEIMAGE_CONNECTION_FTP="FTP Verbindung" +COM_REMOTEIMAGE_CONNECTION_FTP_DESC="Aktivieren oder deaktivieren der FTP Funktion von RemoteImage." +COM_REMOTEIMAGE_CONNECTION_LOCAL="Lokale Bilder" +COM_REMOTEIMAGE_CONNECTION_LOCAL_DESC="Aktivieren oder deaktivieren der Lokalen Bilder." +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM="Standard Höhe" +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM_DESC="Standard Höhe, wenn Bilder eingefügt werden." +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM="Standard Breite" +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM_DESC="Standard Breite, wenn Bilder eingefügt werden.." +COM_REMOTEIMAGE_FTP_HOST="FTP Host" +COM_REMOTEIMAGE_FTP_HOST_DESC="FTP host, eg: yourftp.de" +COM_REMOTEIMAGE_FTP_PASSWORD="FTP Passwort" +COM_REMOTEIMAGE_FTP_PASSWORD_DESC="FTP Passwort" +COM_REMOTEIMAGE_FTP_PORT="FTP Port" +COM_REMOTEIMAGE_FTP_PORT_DESC="FTP Port, Standard 21." +COM_REMOTEIMAGE_FTP_ROOT="FTP Root Pfad" +COM_REMOTEIMAGE_FTP_ROOT_DESC="Einstellung des Root Pfades(Hauptpfad) vom FTP , auf darunterliegende Verzeichnisse kann nicht zugegeriffen werden." +COM_REMOTEIMAGE_FTP_URL="FTP Bilder URL" +COM_REMOTEIMAGE_FTP_URL_DESC="Die URL vom FTP um Bilder zu zeigen." +COM_REMOTEIMAGE_FTP_USER="FTP Benutzer" +COM_REMOTEIMAGE_FTP_USER_DESC="FTP Benutzer." +COM_REMOTEIMAGE_FTP_ACTIVE_MODE="Aktiver Modus" +COM_REMOTEIMAGE_FTP_ACTIVE_MODE_DESC="Aktiver Modus kann hier aktiviert werden." + + +;_manager +COM_REMOTEIMAGE_TITLE_MANAGER="Asikart RemoteImage: Bilder Manager" +COM_REMOTEIMAGE_INSERT_IMAGES="Einfügen" +COM_REMOTEIMAGE_MANAGER="Manager" +COM_REMOTEIMAGE_MAX_WIDTH_HEIGHT="Max. Breite Höhe" +COM_REMOTEIMAGE_MAX_WIDTH="Max. Breite" +COM_REMOTEIMAGE_IMAGE_BUTTON="Entfernte und Lokale Bilder" +COM_REMOTEIMAGE_FIX_ALL_IMAGE_WIDTH="Setze alle Bilder auf Max. Breite" +COM_REMOTEIMAGE_UPLOAD_MAX="Maximale Dateigröße die hochgeladen werden darf:" +COM_REMOTEIMAGE_UPLOAD_NUM="Maximale Anzahl an Dateien die hochgeladen werden dürfen:" + +; 1.1.0 +COM_REMOTEIMAGE_CONFIGURATION="RemoteImage Konfiguration" +COM_CONFIG_INTEGRATE_FIELDSET_LABEL="Integration" + +COM_REMOTEIMAGE_LOCAL_ROOT="Lokaler Root Pfad" +COM_REMOTEIMAGE_LOCAL_ROOT_DESC="Lokaler Hauptpfad für Bilder, Standard ist 'images'. Anmerkung: Wenn der Pfad außerhalb von Images liegt, könnte das ein Sicherheitsproblem darstellen." +COM_REMOTEIMAGE_ONLYIMAGE="Nur Bilder" +COM_REMOTEIMAGE_ONLYIMAGE_DESC="Nur Bilder anzeigen, es werden keine anderen Dateitypen angezeigt." +COM_REMOTEIMAGE_SAFEMODE="Sicherheitsmodus" +COM_REMOTEIMAGE_SAFEMODE_DESC="Wenn der Sicherheitsmodus aktviert ist, werden Funktionen wie packen,entpachen und umbennen deaktiviert." +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE="Template für das einfügen von Bildern" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE_DESC="Template für das einfügen von Bildern, benutze {%CONTENT%} um den <img> tag zu ersetzen." +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK="Template für das einfügen von Links" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK_DESC="Template für das einfügen von Links, benutze {%CONTENT%} um den <a> tag zu ersetzen." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER="Ersetze Media Manager" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER_DESC="Ersetzt den Joomla! core com_media durch RemoteImage." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD="Ersetzte Media Selektor" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD_DESC="Ersetzt die core media selektor Funktion durch RemoteImage." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE="Ersetzte einfügen von Bilder in Artikeln" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE_DESC="Ersetzt den Bild einfügen knopf durch RemoteImage." +COM_REMOTEIMAGE_INSERT_FROM_URL="Von URL einfügen" +COM_REMOTEIMAGE_INSERT_FROM_URL_DESC="Fügen Sie hier den Pfad zu den externen Bildern ein, für mehr Bilder drücken Sie die Eingabetaste, ein Bild pro Zeile." + + +; 1.1.1 +COM_REMOTEIMAGE_SYSTEM_PLUGIN_NEED_ENABLED="Sie haben die com_media Ersetzen Funktion aktiviert, aber das System Plugin ist deaktviert. " +COM_REMOTEIMAGE_GO_TO_PLUGINS="Bitte aktivieren Sie das Systemplugin unter Erweiterungen -> Plugins." diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.sys.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.sys.ini new file mode 100644 index 00000000..5ff85a52 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/de-DE.com_remoteimage.sys.ini @@ -0,0 +1,10 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +COM_REMOTEIMAGE="RemoteImage" +REMOTEIMAGE="RemoteImage" +COM_REMOTEIMAGE_XML_DESCRIPTION="" +COM_REMOTEIMAGE_INSTALL_MSG="RemoteImage Komponente, Zugriff und Verwaltung von lokalen und auf FTP Servern befindlichen Bildern, einfügen von Bildern im Editor." +COM_REMOTEIMAGE_MANAGERS="Manager" \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/index.html b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/de-DE/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.ini new file mode 100644 index 00000000..dc23a2f8 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.ini @@ -0,0 +1,93 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +; Main information +COM_REMOTEIMAGE="RemoteImage" +COM_REMOTEIMAGE_COMPONENT_LABEL="Basic" +COM_REMOTEIMAGE_ACCESS_HEADING="Access" + +COM_REMOTEIMAGE_COMPONENT_LABEL="Basic" +COM_REMOTEIMAGE_TITLE_LIST="List" + + + +; Config +COM_REMOTEIMAGE_CONNECTION_FTP="FTP Connection" +COM_REMOTEIMAGE_CONNECTION_FTP_DESC="Enable or disable FTP loading remote images." +COM_REMOTEIMAGE_CONNECTION_LOCAL="Local Images" +COM_REMOTEIMAGE_CONNECTION_LOCAL_DESC="Enable or disable local images." +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM="Default Height" +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM_DESC="Default hight when inset images." +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM="Deafult Width" +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM_DESC="Default width when inset images." +COM_REMOTEIMAGE_FTP_HOST="FTP Host" +COM_REMOTEIMAGE_FTP_HOST_DESC="FTP host, eg: yourftp.com" +COM_REMOTEIMAGE_FTP_PASSWORD="FTP Password" +COM_REMOTEIMAGE_FTP_PASSWORD_DESC="FTP Password" +COM_REMOTEIMAGE_FTP_PORT="FTP Port" +COM_REMOTEIMAGE_FTP_PORT_DESC="FTP Port, default 21." +COM_REMOTEIMAGE_FTP_ROOT="FTP Root Path" +COM_REMOTEIMAGE_FTP_ROOT_DESC="Set FTP login root path, user can not access parent dir." +COM_REMOTEIMAGE_FTP_URL="FTP Image URL" +COM_REMOTEIMAGE_FTP_URL_DESC="The URL about your FTP to show image." +COM_REMOTEIMAGE_FTP_USER="FTP User" +COM_REMOTEIMAGE_FTP_USER_DESC="FTP user account." +COM_REMOTEIMAGE_FTP_ACTIVE_MODE="Active Mode" +COM_REMOTEIMAGE_FTP_ACTIVE_MODE_DESC="Enable active mode or use passive mode." + + +;_manager +COM_REMOTEIMAGE_TITLE_MANAGER="Asikart RemoteImage: Image Manager" +COM_REMOTEIMAGE_INSERT_IMAGES="Insert" +COM_REMOTEIMAGE_MANAGER="Manager" +COM_REMOTEIMAGE_MAX_WIDTH_HEIGHT="Max Width Height" +COM_REMOTEIMAGE_MAX_WIDTH="Max Width" +COM_REMOTEIMAGE_IMAGE_BUTTON="Remote and Local Images" +COM_REMOTEIMAGE_FIX_ALL_IMAGE_WIDTH="Fix all images as Max Width" +COM_REMOTEIMAGE_UPLOAD_MAX="Upload Max Size:" +COM_REMOTEIMAGE_UPLOAD_NUM="Upload Max Number:" + +; 1.1.0 +COM_REMOTEIMAGE_CONFIGURATION="RemoteImage Configuration" +COM_CONFIG_INTEGRATE_FIELDSET_LABEL="Integrate" + +COM_REMOTEIMAGE_LOCAL_ROOT="Local Root Path" +COM_REMOTEIMAGE_LOCAL_ROOT_DESC="Local images root path, default is 'images'. Note if set this path out of images, may have security issuse." +COM_REMOTEIMAGE_ONLYIMAGE="Only Images" +COM_REMOTEIMAGE_ONLYIMAGE_DESC="Only show image files, do not show other file types." +COM_REMOTEIMAGE_SAFEMODE="Safe Mode" +COM_REMOTEIMAGE_SAFEMODE_DESC="If Safe Mode enabled, will disable archive, extract and rename commands, to prevent someone may upload a fake image and rename to php to hack your site." +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE="Template of Insert Images" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE_DESC="Custom template of insert images, use {%CONTENT%} to replace with <img> tag." +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK="Template of Insert Links" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK_DESC="Custom template of insert links, use {%CONTENT%} to replace with <a> tag." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER="Replace Media Manager" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER_DESC="Replace Joomla! core com_media page." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD="Replace Media Selector" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD_DESC="Replace core media selector formfield." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE="Replace Insert Image in Article" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE_DESC="Replace the image selector of insert image to article button." +COM_REMOTEIMAGE_INSERT_FROM_URL="Insert From URL" +COM_REMOTEIMAGE_INSERT_FROM_URL_DESC="Paste image URL in textarea, you can press Enter to add a line, one line per image." + + +; 1.1.1 +COM_REMOTEIMAGE_SYSTEM_PLUGIN_NEED_ENABLED="You enabled the com_media replace function, but not enable system plugin yet, RemoteImage need system plugin to redirect com_media pages." +COM_REMOTEIMAGE_GO_TO_PLUGINS="Go to plugin manager to enable system redirect plugin." + +; 2.0.0 +COM_REMOTEIMAGE_MANAGER_DESC="Add a manager page in frontend." +COM_REMOTEIMAGE_FRONTEND_ACCESS="Frontend accessing" +COM_REMOTEIMAGE_FRONTEND_ACCESS_DESC="Can access Remoteimage in frontend (Default is only allow Super User)." + +; 2.0.3 +COM_REMOTEIMAGE_IMAGE_RESIZE_ENABLED="Auto-Resize" +COM_REMOTEIMAGE_IMAGE_RESIZE_ENABLED_DESC="Automatically resize images which uploaded." +COM_REMOTEIMAGE_IMAGE_MAX_WIDTH="Max width." +COM_REMOTEIMAGE_IMAGE_MAX_WIDTH_DESC="Width which the images resized." +COM_REMOTEIMAGE_IMAGE_MAX_HEIGHT="Max height." +COM_REMOTEIMAGE_IMAGE_MAX_HEIGHT_DESC="Height which the images resized." +COM_REMOTEIMAGE_IMAGE_JPEG_QUALITY="JPEG quality" +COM_REMOTEIMAGE_IMAGE_JPEG_QUALITY_DESC="The quality of the resized JPEG images." diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.sys.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.sys.ini new file mode 100644 index 00000000..40a9528c --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/en-GB.com_remoteimage.sys.ini @@ -0,0 +1,10 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +COM_REMOTEIMAGE="RemoteImage" +REMOTEIMAGE="RemoteImage" +COM_REMOTEIMAGE_XML_DESCRIPTION="" +COM_REMOTEIMAGE_INSTALL_MSG="RemoteImage Component, access and manage images from FTP or local folders, and insert images to editor." +COM_REMOTEIMAGE_MANAGERS="Managers" \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/index.html b/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/en-GB/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.ini new file mode 100644 index 00000000..a241f454 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.ini @@ -0,0 +1,90 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +; Main information +COM_REMOTEIMAGE="RemoteImage" +COM_REMOTEIMAGE_COMPONENT_LABEL="Général" +COM_REMOTEIMAGE_ACCESS_HEADING="Access" + +COM_REMOTEIMAGE_COMPONENT_LABEL="Général" +COM_REMOTEIMAGE_TITLE_LIST="List" + +; Config +COM_REMOTEIMAGE_CONNECTION_FTP="Images par FTP" +COM_REMOTEIMAGE_CONNECTION_FTP_DESC="Permet le support des fichiers par FTP." +COM_REMOTEIMAGE_CONNECTION_LOCAL="Images locales" +COM_REMOTEIMAGE_CONNECTION_LOCAL_DESC="Permet le support des fichiers locaux." +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM="Hauteur par defaut" +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM_DESC="Hauteur par défaut des images intégrées." +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM="Largeur par defaut" +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM_DESC="Largeur par défaut des images intégrées." +COM_REMOTEIMAGE_FTP_HOST="Hôte FTP" +COM_REMOTEIMAGE_FTP_HOST_DESC="Hôte FTP, ex.: yourftp.com" +COM_REMOTEIMAGE_FTP_PASSWORD="Mot de passe FTP" +COM_REMOTEIMAGE_FTP_PASSWORD_DESC="Mot de passe FTP" +COM_REMOTEIMAGE_FTP_PORT="Port FTP" +COM_REMOTEIMAGE_FTP_PORT_DESC="Port FTP, 21 par défault." +COM_REMOTEIMAGE_FTP_ROOT="Répertoire racine FTP" +COM_REMOTEIMAGE_FTP_ROOT_DESC="Le répertoire racine FTP." +COM_REMOTEIMAGE_FTP_URL="URL FTP Image" +COM_REMOTEIMAGE_FTP_URL_DESC="The URL about your FTP to show image." +COM_REMOTEIMAGE_FTP_USER="Login FTP" +COM_REMOTEIMAGE_FTP_USER_DESC="Le login du compte FTP." +COM_REMOTEIMAGE_FTP_ACTIVE_MODE="Mode FTP actif" +COM_REMOTEIMAGE_FTP_ACTIVE_MODE_DESC="Mode FTP actif ou passif." + +;_manager +COM_REMOTEIMAGE_TITLE_MANAGER="Asikart RemoteImage: Image Manager" +COM_REMOTEIMAGE_INSERT_IMAGES="Insérer" +COM_REMOTEIMAGE_MANAGER="Manager" +COM_REMOTEIMAGE_MAX_WIDTH_HEIGHT="Max Width Height" +COM_REMOTEIMAGE_MAX_WIDTH="Largeur max." +COM_REMOTEIMAGE_IMAGE_BUTTON="Images locales et distantes" +COM_REMOTEIMAGE_FIX_ALL_IMAGE_WIDTH="Fixer la largeur max. de toutes les images" +COM_REMOTEIMAGE_UPLOAD_MAX="Taille maximum pour l\'upload:" +COM_REMOTEIMAGE_UPLOAD_NUM="Nombre maximum d\'uploads:" + +; 1.1.0 +COM_REMOTEIMAGE_CONFIGURATION="Configuration RemoteImage" +COM_CONFIG_INTEGRATE_FIELDSET_LABEL="Intégrer" + +COM_REMOTEIMAGE_LOCAL_ROOT="Répertoire racine local" +COM_REMOTEIMAGE_LOCAL_ROOT_DESC="Le répertoire racine local contenant les fichiers, par défault 'images'. Changer ce chemin peut créer des failles de sécurité." +COM_REMOTEIMAGE_ONLYIMAGE="Images seulement" +COM_REMOTEIMAGE_ONLYIMAGE_DESC="Ne montrer que les fichiers images." +COM_REMOTEIMAGE_SAFEMODE="Mode protégé" +COM_REMOTEIMAGE_SAFEMODE_DESC="Le mode protégé désactive l'archivage, l'extraction et la commande de renommage pour des raisons de sécurité." +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE="Template d'insertion d'images" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE_DESC="Le templace pour insérer une image. A utiliser pour remplacer le tag img." +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK="Template d'insertion de liens" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK_DESC="Le templace pour insérer une image. A utiliser pour remplacer le tag a." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER="Remplacer Media Manager" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER_DESC="Remplacer Joomla! core com_media page." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD="Remplacer Media Selector" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD_DESC="Remplacer core media selector formfield." +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE="Remplacer Insérer Image dans Article" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE_DESC="Remplacer le sélecteur d'images de l'éditeur d'article." +COM_REMOTEIMAGE_INSERT_FROM_URL="Insérer depuis une URL" +COM_REMOTEIMAGE_INSERT_FROM_URL_DESC="Coller l'URL de l'image dans la zone de texte. Vous pouvez presser Entrée pour ajouter une ligne, une ligne par image." + + +; 1.1.1 +COM_REMOTEIMAGE_SYSTEM_PLUGIN_NEED_ENABLED="Vous avez ajouté la fonction com_media replace, mais pas encore activé le plugin système. RemoteImage a besoin du plugin système pour rediriger les pages com_media." +COM_REMOTEIMAGE_GO_TO_PLUGINS="Allez au gestionnaire des plug-ins pour activer le plugin de redirection système." + +; 2.0.0 +COM_REMOTEIMAGE_MANAGER_DESC="Ajouter un manager au Frontend." +COM_REMOTEIMAGE_FRONTEND_ACCESS="Accès depuis le Frontend" +COM_REMOTEIMAGE_FRONTEND_ACCESS_DESC="Accès à Remoteimage depuis le Frontend (par défault seulement possible pour le super user)." + +; 2.0.3 +COM_REMOTEIMAGE_IMAGE_RESIZE_ENABLED="Auto-redimensionnement" +COM_REMOTEIMAGE_IMAGE_RESIZE_ENABLED_DESC="Retaille automatiquement les images téléchargées dont les dimensions excèdent les valeurs suivantes." +COM_REMOTEIMAGE_IMAGE_MAX_WIDTH="Largeur max." +COM_REMOTEIMAGE_IMAGE_MAX_WIDTH_DESC="La largeur à laquelle sont retaillées les images téléchargées qui sont plus larges." +COM_REMOTEIMAGE_IMAGE_MAX_HEIGHT="Hauteur max." +COM_REMOTEIMAGE_IMAGE_MAX_HEIGHT_DESC="La hauteur à laquelle sont retaillées les images téléchargées quit sont plus hautes." +COM_REMOTEIMAGE_IMAGE_JPEG_QUALITY="Qualité de réencodage JPEG" +COM_REMOTEIMAGE_IMAGE_JPEG_QUALITY_DESC="La qualité de réencodage JPEG des images retaillées." diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.sys.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.sys.ini new file mode 100644 index 00000000..44b040ec --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/fr-FR/fr-FR.com_remoteimage.sys.ini @@ -0,0 +1,10 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +COM_REMOTEIMAGE="RemoteImage" +REMOTEIMAGE="RemoteImage" +COM_REMOTEIMAGE_XML_DESCRIPTION="" +COM_REMOTEIMAGE_INSTALL_MSG="Le composant RemoteImage permet d'accéder et de gérer des fichiers par FTP ou en local avec des fonctions avancées d'édition d'images." +COM_REMOTEIMAGE_MANAGERS="Managers" diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/index.html b/packages/remoteimage/administrator/components/com_remoteimage/language/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/index.html b/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.ini new file mode 100644 index 00000000..50724c29 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.ini @@ -0,0 +1,92 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +; Main information +COM_REMOTEIMAGE="RemoteImage 遠近端圖片管理器" +COM_REMOTEIMAGE_CONFIGURATION="RemoteImage 元件設定" +COM_REMOTEIMAGE_COMPONENT_LABEL="基礎設定" +COM_REMOTEIMAGE_COMPONENT_DESC="這裡是基礎設定" +COM_REMOTEIMAGE_ACCESS_HEADING="Access" +COM_REMOTEIMAGE_TITLE_LIST="列表管理" + + +; Config +COM_REMOTEIMAGE_CONNECTION_FTP="FTP 遠端圖片" +COM_REMOTEIMAGE_CONNECTION_FTP_DESC="是否啟動 FTP 讀取遠端圖片。" +COM_REMOTEIMAGE_CONNECTION_LOCAL="本地端圖片" +COM_REMOTEIMAGE_CONNECTION_LOCAL_DESC="是否啟動本地端圖片。" +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM="預設圖片高度" +COM_REMOTEIMAGE_DEFAULT_HEIGHT_MIDIUM_DESC="插入圖片時,預設的最大高度,可在插入時調整。" +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM="預設圖片寬度" +COM_REMOTEIMAGE_DEFAULT_WIDTH_MIDIUM_DESC="插入圖片時,預設的最大寬度,可在插入時調整。" +COM_REMOTEIMAGE_FTP_HOST="FTP 主機" +COM_REMOTEIMAGE_FTP_HOST_DESC="FTP 主機位置,例如: yourftp.com" +COM_REMOTEIMAGE_FTP_PASSWORD="FTP 密碼" +COM_REMOTEIMAGE_FTP_PASSWORD_DESC="FTP 密碼" +COM_REMOTEIMAGE_FTP_PORT="FTP Port" +COM_REMOTEIMAGE_FTP_PORT_DESC="FTP 連練端口,預設通常為 21" +COM_REMOTEIMAGE_FTP_ROOT="FTP 根目錄" +COM_REMOTEIMAGE_FTP_ROOT_DESC="通常是 / ,但也可以設定內層目錄,使用者無法向上存取其他目錄。" +COM_REMOTEIMAGE_FTP_URL="FTP 網址" +COM_REMOTEIMAGE_FTP_URL_DESC="讀取圖片用的網誌,必須跟 FTP 位置相關連才能正常取得圖片。" +COM_REMOTEIMAGE_FTP_USER="FTP 使用者帳號" +COM_REMOTEIMAGE_FTP_USER_DESC="輸入使用者帳號" +COM_REMOTEIMAGE_FTP_ACTIVE_MODE="主動模式" +COM_REMOTEIMAGE_FTP_ACTIVE_MODE_DESC="是否開啟主動模式" + + + +; manager +COM_REMOTEIMAGE_TITLE_MANAGER="Asikart RemoteImage: 圖片管理" +COM_REMOTEIMAGE_INSERT_IMAGES="插入圖片" +COM_REMOTEIMAGE_MANAGER="圖片管理" +COM_REMOTEIMAGE_MAX_WIDTH_HEIGHT="最大長寬" +COM_REMOTEIMAGE_MAX_WIDTH="最大寬度" +COM_REMOTEIMAGE_IMAGE_BUTTON="插入遠近端圖片" +COM_REMOTEIMAGE_FIX_ALL_IMAGE_WIDTH="固定所有圖片為最大寬度" +COM_REMOTEIMAGE_UPLOAD_MAX="上傳大小限制:" +COM_REMOTEIMAGE_UPLOAD_NUM="上傳數量限制:" + + +; 1.1.0 +COM_CONFIG_INTEGRATE_FIELDSET_LABEL="整合" + +COM_REMOTEIMAGE_LOCAL_ROOT="本地端起始路徑" +COM_REMOTEIMAGE_LOCAL_ROOT_DESC="選擇本地端的起始目錄,預設為 images 。注意,設為 / 網站根目錄可能會有安全性問題!" +COM_REMOTEIMAGE_ONLYIMAGE="只顯示圖片" +COM_REMOTEIMAGE_ONLYIMAGE_DESC="只顯示圖片,不顯示其他檔案類型。" +COM_REMOTEIMAGE_SAFEMODE="安全模式" +COM_REMOTEIMAGE_SAFEMODE_DESC="啟動安全模式後,會禁止壓縮 / 解壓縮以及重新命名功能,以避免有心人上傳假圖片並改名成 php 來入侵網站。" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE="插入圖片模版" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_IMAGE_DESC="自定插入圖片時的模版,{%CONTENT%} 代表 <img> 圖片本身。" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK="插入連結模版" +COM_REMOTEIMAGE_INTEGRATE_INSERT_TEMPLATE_LINK_DESC="自定插入連結時的模版,{%CONTENT%} 代表 $lt;a> 連結本身。" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER="取代媒體管理" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_MANAGER_DESC="取代內建的 com_media 媒體管理。" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD="取代圖片選擇器" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_MEDIA_FORMFIELD_DESC="取代內建的 FormField 圖片選擇器。" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE="取代文章的插入圖片" +COM_REMOTEIMAGE_INTEGRATE_OVERRIDE_INSERT_IMAGE_ARTICLE_DESC="取代內建的插入圖片功能。" +COM_REMOTEIMAGE_INSERT_FROM_URL="從網址插入" +COM_REMOTEIMAGE_INSERT_FROM_URL_DESC="貼上網址在文字欄位中,可用 Enter 換行,一行一張圖片網址。" + +; 1.1.1 +COM_REMOTEIMAGE_SYSTEM_PLUGIN_NEED_ENABLED="您啟動了覆蓋媒體管理的功能,但尚未啟動系統外掛,因此覆蓋功能無法運作。" +COM_REMOTEIMAGE_GO_TO_PLUGINS="立即前往外掛管理啟動系統外掛。" + +; 2.0.0 +COM_REMOTEIMAGE_MANAGER_DESC="在前台新增管理頁面." +COM_REMOTEIMAGE_FRONTEND_ACCESS="前台存取權" +COM_REMOTEIMAGE_FRONTEND_ACCESS_DESC="是否有權使用前台存取 Remoteimage (預設只允許超級管理員)。" + +; 2.0.3 +COM_REMOTEIMAGE_IMAGE_RESIZE_ENABLED="上傳後自動縮圖" +COM_REMOTEIMAGE_IMAGE_RESIZE_ENABLED_DESC="避免原始圖片過大,自動縮成一定大小的 JPG 檔" +COM_REMOTEIMAGE_IMAGE_MAX_WIDTH="縮圖寬度" +COM_REMOTEIMAGE_IMAGE_MAX_WIDTH_DESC="預設縮圖寬度 (px)" +COM_REMOTEIMAGE_IMAGE_MAX_HEIGHT="縮圖高度" +COM_REMOTEIMAGE_IMAGE_MAX_HEIGHT_DESC="預設縮圖高度 (px)" +COM_REMOTEIMAGE_IMAGE_JPEG_QUALITY="縮圖 JPG 品質" +COM_REMOTEIMAGE_IMAGE_JPEG_QUALITY_DESC="縮圖 JPG 品質,最大 100" diff --git a/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.sys.ini b/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.sys.ini new file mode 100644 index 00000000..99741a54 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/language/zh-TW/zh-TW.com_remoteimage.sys.ini @@ -0,0 +1,11 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +COM_REMOTEIMAGE="RemoteImage 遠近端圖片管理器" +REMOTEIMAGE="RemoteImage 遠近端圖片管理器" +COM_REMOTEIMAGE_XML_DESCRIPTION="" +COM_REMOTEIMAGE_INSTALL_MSG="RemoteImage 遠近端圖片管理器,可以管理 FTP 或本地端的圖片,並插入圖片在編輯器中。" +COM_REMOTEIMAGE_MANAGERS="Managers" + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/remoteimage.php b/packages/remoteimage/administrator/components/com_remoteimage/remoteimage.php new file mode 100644 index 00000000..f92c219b --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/remoteimage.php @@ -0,0 +1,14 @@ +execute(); diff --git a/packages/remoteimage/administrator/components/com_remoteimage/remoteimage.xml b/packages/remoteimage/administrator/components/com_remoteimage/remoteimage.xml new file mode 100644 index 00000000..9481d546 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/remoteimage.xml @@ -0,0 +1,62 @@ + + + com_remoteimage + 2014-1-11 + Copyright (C) 2014. All rights reserved. + GNU General Public License version 2 or later; see LICENSE.txt + Asika + asika32764@gmail.com + http://asikart.com + 2.0.10 + COM_REMOTEIMAGE_XML_DESCRIPTION + + install.php + + + asset + images + view + component.php + index.html + remoteimage.php + router.php + routing.json + + + + COM_REMOTEIMAGE + + + asset + etc + helper + images + language + src + view + access.xml + component.php + composer.json + config.xml + index.html + install.php + remoteimage.php + + + + + + + + + plg_editors-xtd_remoteimage + plg_system_remoteimage + + + + https://raw.githubusercontent.com/lyrasoft/remoteimage/staging/update.xml + + + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/MySQLStorage.sql b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/MySQLStorage.sql new file mode 100644 index 00000000..67a33ecd --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.minimal.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.minimal.php new file mode 100644 index 00000000..9aad2daa --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.minimal.php @@ -0,0 +1,61 @@ + 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.php new file mode 100644 index 00000000..9aad2daa --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/connector.php @@ -0,0 +1,61 @@ + 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinder.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinder.class.php new file mode 100644 index 00000000..4a301289 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinder.class.php @@ -0,0 +1,1971 @@ + 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, 'chunk' => false, 'cid' => false), + 'get' => array('target' => true, 'conv' => false), + '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), + 'url' => array('target' => true, 'options' => false), + 'callback' => array('node' => true, 'json' => false, 'bind' => false, 'done' => 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(); + + /** + * URL for callback output window for CORS + * redirect to this URL when callback output + * + * @var string URL + */ + protected $callbackWindowURL = ''; + + // 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_CONV_UTF8 = 'errConvUTF8'; + const ERROR_NOT_UTF8_CONTENT = 'errNotUTF8Content'; + const ERROR_NETMOUNT = 'errNetMount'; + const ERROR_NETUNMOUNT = 'errNetUnMount'; + 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); + $this->netVolumesSessionKey = !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes'; + $this->callbackWindowURL = (isset($opts['callbackWindowURL']) ? $opts['callbackWindowURL'] : ''); + + 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 root - file's owner (public func of volume()) + * + * @param string file hash + * @return elFinderStorageDriver + * @author Naoki Sawada + */ + public function getVolume($hash) { + return $this->volume($hash); + } + + /** + * 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_array($handler,array($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[$this->netVolumesSessionKey]) && is_array($_SESSION[$this->netVolumesSessionKey]) ? $_SESSION[$this->netVolumesSessionKey] : array(); + } + + /** + * Save network volumes config. + * + * @param array $volumes volumes config + * @return void + * @author Dmitry (dio) Levashov + */ + protected function saveNetVolumes($volumes) { + $_SESSION[$this->netVolumesSessionKey] = $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']; + + if ($protocol === 'netunmount') { + if (isset($_SESSION) && is_array($_SESSION) && isset($_SESSION[$this->netVolumesSessionKey][$args['host']])) { + $res = true; + $netVolumes = $this->getNetVolumes(); + $key = $args['host']; + $volume = $this->volume($args['user']); + if (method_exists($volume, 'netunmount')) { + $res = $volume->netunmount($netVolumes, $key); + } + if ($res) { + unset($netVolumes[$key]); + $this->saveNetVolumes($netVolumes); + return array('sync' => true); + } + } + return array('error' => $this->error(self::ERROR_NETUNMOUNT)); + } + + $driver = isset(self::$netDrivers[$protocol]) ? self::$netDrivers[$protocol] : ''; + $class = 'elfindervolume'.$driver; + + if (!class_exists($class)) { + 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 (method_exists($volume, 'netmountPrepare')) { + $options = $volume->netmountPrepare($options); + if (isset($options['exit'])) { + if ($options['exit'] === 'callback') { + $this->callback($options['out']); + } + return $options; + } + } + + $netVolumes = $this->getNetVolumes(); + if ($volume->mount($options)) { + if (! $key = @ $volume->netMountKey) { + $key = md5($protocol . '-' . join('-', $options)); + } + $options['driver'] = $driver; + $options['netkey'] = $key; + $netVolumes[$key] = $options; + $this->saveNetVolumes($netVolumes); + $rootstat = $volume->file($volume->root()); + $rootstat['netkey'] = $key; + return array('added' => array($rootstat)); + } else { + if (! $key = @ $volume->netMountKey) { + $key = md5($protocol . '-' . join('-', $options)); + } + if (isset($netVolumes[$key])) { + unset($netVolumes[$key]); + $this->saveNetVolumes($netVolumes); + } + 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 + * @param resource $fp + * @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', $fp = null ) { + $method = (function_exists('curl_exec') && !ini_get('safe_mode'))? 'curl_get_contents' : 'fsock_get_contents'; + return $this->$method( $url, $timeout, $redirect_max, $ua, $fp ); + } + + /** + * 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 + * @param resource $outfp + * @return string or bool(false) + * @retval string contents + * @retval false error + * @author Naoki Sawada + **/ + protected function curl_get_contents( &$url, $timeout, $redirect_max, $ua, $outfp ){ + $ch = curl_init(); + curl_setopt( $ch, CURLOPT_URL, $url ); + curl_setopt( $ch, CURLOPT_HEADER, false ); + if ($outfp) { + curl_setopt( $ch, CURLOPT_FILE, $outfp ); + } else { + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); + curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true ); + } + curl_setopt( $ch, CURLOPT_LOW_SPEED_LIMIT, 1 ); + curl_setopt( $ch, CURLOPT_LOW_SPEED_TIME, $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 ); + $url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); + curl_close( $ch ); + return $outfp? $outfp : $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 + * @param resource $outfp + * @return string or bool(false) + * @retval string contents + * @retval false error + * @author Naoki Sawada + */ + protected function fsock_get_contents( &$url, $timeout, $redirect_max, $ua, $outfp ) { + + $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 = ''; + $header = ''; + while($_response !== "\r\n"){ + $_response = fgets($fp, $readsize); + $header .= $_response; + }; + + $rccd = array_pad(explode(' ',$header,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',$header,$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; + } + fclose($fp); + return $this->fsock_get_contents( $url, $timeout, $redirect_max, $ua, $outfp ); + } + } + + $body = ''; + if (!$outfp) { + $outfp = fopen('php://temp', 'rwb'); + $body = true; + } + while(fwrite($outfp, fread($fp, $readsize))) { + if ($timeout) { + $_status = socket_get_status($fp); + if ($_status['timed_out']) { + fclose($outfp); + fclose($fp); + return false; // Request Time-out + } + } + } + if ($body) { + rewind($outfp); + $body = stream_get_contents($outfp); + fclose($outfp); + $outfp = null; + } + + fclose($fp); + + return $outfp? $outfp : $body; // Data + } + + /** + * Parse Data URI scheme + * + * @param string $str + * @param array $extTable + * @return array + * @author Naoki Sawada + */ + protected function parse_data_scheme( $str, $extTable ) { + $data = $name = ''; + if ($fp = fopen('data://'.substr($str, 5), 'rb')) { + if ($data = stream_get_contents($fp)) { + $meta = stream_get_meta_data($fp); + $ext = isset($extTable[$meta['mediatype']])? '.' . $extTable[$meta['mediatype']] : ''; + $name = substr(md5($data), 0, 8) . $ext; + } + fclose($fp); + } + return array($data, $name); + } + + /** + * Detect file type extension by local path + * + * @param string $path Local path + * @return string file type extension with dot + * @author Naoki Sawada + */ + protected function detectFileExtension($path) { + static $type, $finfo, $extTable; + if (!$type) { + $keys = array_keys($this->volumes); + $volume = $this->volumes[$keys[0]]; + $extTable = array_flip(array_unique($volume->getMimeTable())); + + if (class_exists('finfo')) { + $tmpFileInfo = @explode(';', @finfo_file(finfo_open(FILEINFO_MIME), __FILE__)); + } else { + $tmpFileInfo = false; + } + $regexp = '/text\/x\-(php|c\+\+)/'; + if ($tmpFileInfo && preg_match($regexp, array_shift($tmpFileInfo))) { + $type = 'finfo'; + $finfo = finfo_open(FILEINFO_MIME); + } elseif (function_exists('mime_content_type') + && preg_match($regexp, array_shift(explode(';', mime_content_type(__FILE__))))) { + $type = 'mime_content_type'; + } elseif (function_exists('getimagesize')) { + $type = 'getimagesize'; + } else { + $type = 'none'; + } + } + + $mime = ''; + if ($type === 'finfo') { + $mime = @finfo_file($finfo, $path); + } elseif ($type === 'mime_content_type') { + $mime = mime_content_type($path); + } elseif ($type === 'getimagesize') { + if ($img = @getimagesize($path)) { + $mime = $img['mime']; + } + } + + if ($mime) { + $mime = explode(';', $mime); + $mime = trim($mime[0]); + + if (in_array($mime, array('application/x-empty', 'inode/x-empty'))) { + // finfo return this mime for empty files + $mime = 'text/plain'; + } elseif ($mime == 'application/x-zip') { + // http://elrte.org/redmine/issues/163 + $mime = 'application/zip'; + } + } + + return ($mime && isset($extTable[$mime]))? ('.' . $extTable[$mime]) : ''; + } + + /** + * Check chunked upload files + * + * @param string $tmpname uploaded temporary file path + * @param string $chunk uploaded chunk file name + * @param string $cid uploaded chunked file id + * @param string $tempDir temporary dirctroy path + * @return array (string JoinedTemporaryFilePath, string FileName) or (empty, empty) + * @author Naoki Sawada + */ + private function checkChunkedFile($tmpname, $chunk, $cid, $tempDir) { + if (preg_match('/^(.+)(\.\d+_(\d+))\.part$/s', $chunk, $m)) { + $encname = md5($cid . '_' . $m[1]); + $part = $tempDir . '/ELF' . $encname . $m[2]; + if (is_null($tmpname)) { + // chunked file upload fail + foreach(glob($tempDir . '/ELF' . $encname . '*') as $cf) { + @unlink($cf); + } + return; + } + if (move_uploaded_file($tmpname, $part)) { + @chmod($part, 0600); + $total = $m[3]; + $parts = array(); + for ($i = 0; $i <= $total; $i++) { + $name = $tempDir . '/ELF' . $encname . '.' . $i . '_' . $total; + if (is_readable($name)) { + $parts[] = $name; + } else { + $parts = null; + break; + } + } + if ($parts) { + $check = $tempDir . '/ELF' . $encname; + if (!is_file($check)) { + touch($check); + if ($resfile = tempnam($tempDir, 'ELF')) { + $target = fopen($resfile, 'wb'); + foreach($parts as $f) { + $fp = fopen($f, 'rb'); + while (!feof($fp)) { + fwrite($target, fread($fp, 8192)); + } + fclose($fp); + unlink($f); + } + fclose($target); + unlink($check); + return array($resfile, $m[1]); + } + unlink($check); + } + } + } + } + return array('', ''); + } + + /** + * Get temporary dirctroy path + * + * @param string $volumeTempPath + * @return string + * @author Naoki Sawada + */ + private function getTempDir($volumeTempPath = null) { + $testDirs = array(); + if (function_exists('sys_get_temp_dir')) { + $testDirs[] = sys_get_temp_dir(); + } + if ($volumeTempPath) { + $testDirs[] = rtrim(realpath($volumeTempPath), DIRECTORY_SEPARATOR); + } + $tempDir = ''; + $test = DIRECTORY_SEPARATOR . microtime(true); + foreach($testDirs as $testDir) { + if (!$testDir) continue; + $testFile = $testDir.$test; + if (touch($testFile)) { + unlink($testFile); + $tempDir = $testDir; + $gc = time() - 3600; + foreach(glob($tempDir . '/ELF*') as $cf) { + if (filemtime($cf) < $gc) { + @unlink($cf); + } + } + break; + } + } + return $tempDir; + } + + /** + * 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(); + $chunk = $args['chunk']? $args['chunk'] : ''; + $cid = $args['cid']? (int)$args['cid'] : ''; + + if (!$volume) { + return array('error' => $this->error(self::ERROR_UPLOAD, self::ERROR_TRGDIR_NOT_FOUND, '#'.$target), 'header' => $header); + } + + // regist Shutdown function + $GLOBALS['elFinderTempFiles'] = array(); +// if (version_compare(PHP_VERSION, '5.3.0', '>=')) { +// $shutdownfunc = function(){ // <- Parse error on PHP < 5.3 ;-( +// foreach(array_keys($GLOBALS['elFinderTempFiles']) as $f){ +// @unlink($f); +// } +// }; +// } else { + $shutdownfunc = create_function('', ' + foreach(array_keys($GLOBALS[\'elFinderTempFiles\']) as $f){ + @unlink($f); + } + '); +// } + register_shutdown_function($shutdownfunc); + + // file extentions table by MIME + $extTable = array_flip(array_unique($volume->getMimeTable())); + + if (empty($files)) { + if (isset($args['upload']) && is_array($args['upload']) && ($tempDir = $this->getTempDir($volume->getTempPath()))) { + $names = array(); + foreach($args['upload'] as $i => $url) { + // check chunked file upload commit + if ($args['chunk']) { + if ($url === 'chunkfail' && $args['mimes'] === 'chunkfail') { + $this->checkChunkedFile(null, $chunk, $cid, $tempDir); + if (preg_match('/^(.+)(\.\d+_(\d+))\.part$/s', $chunk, $m)) { + $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $m[1], self::ERROR_UPLOAD_TRANSFER); + } + return $result; + } else { + $tmpfname = $tempDir . '/' . $args['chunk']; + $files['tmp_name'][$i] = $tmpfname; + $files['name'][$i] = $url; + $files['error'][$i] = 0; + $GLOBALS['elFinderTempFiles'][$tmpfname] = true; + break; + } + } + + $tmpfname = $tempDir . DIRECTORY_SEPARATOR . 'ELF_FATCH_' . md5($url.microtime(true)); + + // check is data: + if (substr($url, 0, 5) === 'data:') { + list($data, $args['name'][$i]) = $this->parse_data_scheme($url, $extTable); + } else { + $fp = fopen($tmpfname, 'wb'); + $data = $this->get_remote_contents($url, 30, 5, 'Mozilla/5.0', $fp); + } + 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]; + } + if ((is_resource($data) && fclose($data)) || file_put_contents($tmpfname, $data)) { + $GLOBALS['elFinderTempFiles'][$tmpfname] = true; + $_name = preg_replace('/[\/\\?*:|"<>]/', '_', $_name); + list($_a, $_b) = array_pad(explode('.', $_name, 2), 2, ''); + if ($_b === '') { + if ($_ext) { + rename($tmpfname, $tmpfname . $_ext); + $tmpfname = $tmpfname . $_ext; + } + $_b = $this->detectFileExtension($tmpfname); + $_name = $_a.$_b; + } else { + $_b = '.'.$_b; + } + if (isset($names[$_name])) { + $_name = $_a.'_'.$names[$_name]++.$_b; + } else { + $names[$_name] = 1; + } + $files['tmp_name'][$i] = $tmpfname; + $files['name'][$i] = $_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] : ''; + if ($name === 'blob') { + if ($chunk) { + if ($tempDir = $this->getTempDir($volume->getTempPath())) { + list($tmpname, $name) = $this->checkChunkedFile($tmpname, $chunk, $cid, $tempDir); + if ($name) { + $result['_chunkmerged'] = basename($tmpname); + $result['_name'] = $name; + } + } else { + $result['warning'] = $this->error(self::ERROR_UPLOAD_FILE, $chunk, self::ERROR_UPLOAD_TRANSFER); + $this->uploadDebug = 'Upload error: unable open tmp file'; + } + return $result; + } else { + // for form clipboard with Google Chrome + $type = $files['type'][$i]; + $ext = isset($extTable[$type])? '.' . $extTable[$type] : ''; + $name = substr(md5(basename($tmpname)), 0, 8) . $ext; + } + } + + // 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($GLOBALS['elFinderTempFiles'][$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($GLOBALS['elFinderTempFiles'][$tmpname]);; + continue; + } + break; + } + + fclose($fp); + if (! is_uploaded_file($tmpname) && @ unlink($tmpname)) unset($GLOBALS['elFinderTempFiles'][$tmpname]); + $result['added'][] = $file; + } + if ($GLOBALS['elFinderTempFiles']) { + foreach(array_keys($GLOBALS['elFinderTempFiles']) as $_temp) { + @ unlink($_temp); + } + } + $result['removed'] = $volume->removed(); + 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())); + } + + if ($args['conv'] && function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding')) { + $mime = isset($file['mime'])? $file['mime'] : ''; + if ($mime && strtolower(substr($mime, 0, 4)) === 'text') { + if ($enc = mb_detect_encoding ( $content , mb_detect_order(), true)) { + if (strtolower($enc) !== 'utf-8') { + $content = mb_convert_encoding($content, 'UTF-8', $enc); + } + } + } + } + + $json = json_encode($content); + + if ($json === false || strlen($json) < strlen($content)) { + if ($args['conv']) { + return array('error' => $this->error(self::ERROR_CONV_UTF8,self::ERROR_NOT_UTF8_CONTENT, $volume->path($target))); + } else { + return array('doconv' => true); + } + } + + 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())); + } + + /** + * Return content URL + * + * @param array $args command arguments + * @return array + * @author Naoki Sawada + **/ + protected function url($args) { + $target = $args['target']; + $options = isset($args['options'])? $args['options'] : array(); + if (($volume = $this->volume($target)) != false) { + $url = $volume->getContentUrl($target, $options); + return $url ? array('url' => $url) : array(); + } + return array(); + } + + /** + * Output callback result with JavaScript that control elFinder + * or HTTP redirect to callbackWindowURL + * + * @param array command arguments + * @author Naoki Sawada + */ + protected function callback($args) { + $checkReg = '/[^a-zA-Z0-9;._-]/'; + $node = (isset($args['node']) && !preg_match($checkReg, $args['node']))? $args['node'] : ''; + $json = (isset($args['json']) && @json_decode($args['json']))? $args['json'] : '{}'; + $bind = (isset($args['bind']) && !preg_match($checkReg, $args['bind']))? $args['bind'] : ''; + $done = (!empty($args['done'])); + + while( ob_get_level() ) { + if (! ob_end_clean()) { + break; + } + } + + if ($done || ! $this->callbackWindowURL) { + $script = ''; + if ($node) { + $script .= ' + var w = window.opener || weindow.parent || window + var elf = w.document.getElementById(\''.$node.'\').elfinder; + if (elf) { + var data = '.$json.'; + data.warning && elf.error(data.warning); + data.removed && data.removed.length && elf.remove(data); + data.added && data.added.length && elf.add(data); + data.changed && data.changed.length && elf.change(data);'; + if ($bind) { + $script .= ' + elf.trigger(\''.$bind.'\', data);'; + } + $script .= ' + data.sync && elf.sync(); + }'; + } + $script .= 'window.close();'; + + $out = 'Close this window'; + + header('Content-Type: text/html; charset=utf-8'); + header('Content-Length: '.strlen($out)); + header('Cache-Control: private'); + header('Pragma: no-cache'); + + echo $out; + + } else { + $url = $this->callbackWindowURL; + $url .= ((strpos($url, '?') === false)? '?' : '&') + . '&node=' . rawurlencode($node) + . (($json !== '{}')? ('&json=' . rawurlencode($json)) : '') + . ($bind? ('&bind=' . rawurlencode($bind)) : '') + . '&done=1'; + + header('Location: ' . $url); + + } + exit(); + } + + /***************************************************************************/ + /* 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderConnector.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderConnector.class.php new file mode 100644 index 00000000..4982b433 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderConnector.class.php @@ -0,0 +1,163 @@ +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; + if ($isPost && !$src && $rawPostData = @file_get_contents('php://input')) { + // for support IE XDomainRequest() + $parts = explode('&', $rawPostData); + foreach($parts as $part) { + list($key, $value) = array_pad(explode('=', $part), 2, ''); + $src[$key] = rawurldecode($value); + } + $_POST = $src; + $_REQUEST = array_merge_recursive($src, $_REQUEST); + } + $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, $this->input_filter($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)); + } + } + + } + + /** + * Remove null & stripslashes applies on "magic_quotes_gpc" + * + * @param mixed $args + * @return mixed + * @author Naoki Sawada + */ + private function input_filter($args) { + static $magic_quotes_gpc = NULL; + + if ($magic_quotes_gpc === NULL) + $magic_quotes_gpc = (version_compare(PHP_VERSION, '5.4', '<') && get_magic_quotes_gpc()); + + if (is_array($args)) { + return array_map(array(& $this, 'input_filter'), $args); + } + $res = str_replace("\0", '', $args); + $magic_quotes_gpc && ($res = stripslashes($res)); + return $res; + } +}// END class diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDriver.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDriver.class.php new file mode 100644 index 00000000..4d15603f --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDriver.class.php @@ -0,0 +1,3741 @@ + 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, + // URL of volume icon (16x16 pixel image file) + 'icon' => '', + // 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 $disabled = 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 + * @param bool|null $lineal only lineal parents + * @return array + * @author Dmitry (dio) Levashov + **/ + public function parents($hash, $lineal = false) { + 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 (!$lineal && ($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); + } + + $path = $this->decode($dst); + + if (!$dir['write'] || !$this->allowCreate($path, $name, true)) { + return $this->setError(elFinder::ERROR_PERM_DENIED); + } + + $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, false)) { + 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, ($file['mime'] === 'directory'))) { + 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, ($file['mime'] === 'directory'))) { + 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 content URL (for netmout volume driver) + * If file.url == 1 requests from JavaScript client with XHR + * + * @param string $hash file hash + * @param array $options options array + * @return boolean|string + * @author Naoki Sawada + */ + public function getContentUrl($hash, $options = array()) { + if (($file = $this->file($hash)) == false || !$file['url'] || $file['url'] == 1) { + return false; + } + return $file['url']; + } + + /** + * 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 + * @param bool $isDir path is directory (true: directory, false: file) + * @return bool + * @author Dmitry (dio) Levashov + **/ + protected function attr($path, $name, $val=null, $isDir=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, $isDir); + + 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, $isDir = null) { + $path = $this->_joinPath($dir, $name); + $perm = null; + + if ($this->access) { + $perm = call_user_func($this->access, 'write', $path, $this->options['accessControlData'], $this, $isDir); + 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; + } + if (! empty($this->options['icon'])) { + $stat['icon'] = $this->options['icon']; + } + } 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'; + } + + $isDir = ($stat['mime'] === 'directory'); + + $stat['read'] = intval($this->attr($path, 'read', isset($stat['read']) ? !!$stat['read'] : null, $isDir)); + $stat['write'] = intval($this->attr($path, 'write', isset($stat['write']) ? !!$stat['write'] : null, $isDir)); + if ($root) { + $stat['locked'] = 1; + } elseif ($this->attr($path, 'locked', !empty($stat['locked']), $isDir)) { + $stat['locked'] = 1; + } else { + unset($stat['locked']); + } + + if ($root) { + unset($stat['hidden']); + } elseif ($this->attr($path, 'hidden', !empty($stat['hidden']), $isDir) + || !$this->mimeAccepted($stat['mime'])) { + $stat['hidden'] = $root ? 0 : 1; + } else { + unset($stat['hidden']); + } + + if ($stat['read'] && empty($stat['hidden'])) { + + if ($isDir) { + // 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']); + } + + if (isset($this->options['netkey']) && $path === $this->root) { + $stat['netkey'] = $this->options['netkey']; + } + + 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; + } + + // Imagick::FILTER_BOX faster than FILTER_LANCZOS so use for createTmb + // resize bench: http://app-mgng.rhcloud.com/9 + // resize sample: http://www.dylanbeattie.net/magick/filters/result.html + $filter = ($destformat === 'png' /* createTmb */)? Imagick::FILTER_BOX : Imagick::FILTER_LANCZOS; + $img->resizeImage($size_w, $size_h, $filter, 1); + + $result = $img->writeImage($path); + $img->destroy(); + + 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); + + $img->destroy(); + + 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); + $img->destroy(); + 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); + $img->destroy(); + 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); + } + + /** + * Get server side available archivers + * + * @param bool $use_cache + * @return array + */ + protected function getArchivers($use_cache = true) { + if (!function_exists('proc_open')) { + return array(); + } + + if ($use_cache && isset($_SESSION['ELFINDER_ARCHIVERS_CACHE']) && is_array($_SESSION['ELFINDER_ARCHIVERS_CACHE'])) { + return $_SESSION['ELFINDER_ARCHIVERS_CACHE']; + } + + $arcs = array( + 'create' => array(), + 'extract' => array() + ); + + $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'); + 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 = $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); + $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); + $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 = $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); + $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'); + } + } else if (substr(PHP_OS,0,3) === 'WIN') { + // check `7z` for Windows server. + unset($o); + $this->procExec('7z', $o, $c); + if ($c == 0) { + $arcs['create']['application/x-7z-compressed'] = array('cmd' => '7z', 'argc' => 'a -mx0', 'ext' => '7z'); + $arcs['extract']['application/x-7z-compressed'] = array('cmd' => '7z', 'argc' => 'x -y', 'ext' => '7z'); + + if (empty($arcs['create']['application/x-gzip'])) { + $arcs['create']['application/x-gzip'] = array('cmd' => '7z', 'argc' => 'a -tgzip -mx0', 'ext' => 'tar.gz'); + } + if (empty($arcs['extract']['application/x-gzip'])) { + $arcs['extract']['application/x-gzip'] = array('cmd' => '7z', 'argc' => 'x -tgzip -y', 'ext' => 'tar.gz'); + } + if (empty($arcs['create']['application/x-bzip2'])) { + $arcs['create']['application/x-bzip2'] = array('cmd' => '7z', 'argc' => 'a -tbzip2 -mx0', 'ext' => 'tar.bz'); + } + if (empty($arcs['extract']['application/x-bzip2'])) { + $arcs['extract']['application/x-bzip2'] = array('cmd' => '7z', 'argc' => 'x -tbzip2 -y', 'ext' => 'tar.bz'); + } + if (empty($arcs['create']['application/zip'])) { + $arcs['create']['application/zip'] = array('cmd' => '7z', 'argc' => 'a -tzip -l -mx0', 'ext' => 'zip'); + } + if (empty($arcs['extract']['application/zip'])) { + $arcs['extract']['application/zip'] = array('cmd' => '7z', 'argc' => 'x -tzip -y', 'ext' => 'zip'); + } + if (empty($arcs['create']['application/x-tar'])) { + $arcs['create']['application/x-tar'] = array('cmd' => '7z', 'argc' => 'a -ttar -l -mx0', 'ext' => 'tar'); + } + if (empty($arcs['extract']['application/x-tar'])) { + $arcs['extract']['application/x-tar'] = array('cmd' => '7z', 'argc' => 'x -ttar -y', 'ext' => 'tar'); + } + if (empty($arcs['create']['application/x-rar'])) { + $arcs['create']['application/x-rar'] = array('cmd' => '7z', 'argc' => 'a -trar -l -mx0', 'ext' => 'rar'); + } + if (empty($arcs['extract']['application/x-rar'])) { + $arcs['extract']['application/x-rar'] = array('cmd' => '7z', 'argc' => 'x -trar -y', 'ext' => 'rar'); + } + } + } + + $_SESSION['ELFINDER_ARCHIVERS_CACHE'] = $arcs; + return $arcs; + } + + /**==================================* 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDropbox.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDropbox.class.php new file mode 100644 index 00000000..8996e37d --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeDropbox.class.php @@ -0,0 +1,1531 @@ +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']) || !class_exists('PDO')) { + return array('exit' => true, 'body' => '{msg:errNetMountNoDriver}'); + } + + if (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) { + $this->oauth = new Dropbox_OAuth_Curl($options['consumerKey'], $options['consumerSecret']); + } else { + 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 = $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&node='.$options['id'].$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 = ''; + $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']); + + $out = array( + 'node' => $_GET['node'], + 'json' => '{"protocol": "dropbox", "mode": "done"}', + 'bind' => 'netmount' + ); + + return array('exit' => 'callback', 'out' => $out); + } + } + 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($netVolumes, $key) { + $count = 0; + $dropboxUid = ''; + if (isset($netVolumes[$key])) { + $dropboxUid = $netVolumes[$key]['dropboxUid']; + } + foreach($netVolumes as $volume) { + if (@$volume['host'] === 'dropbox' && @$volume['dropboxUid'] === $dropboxUid) { + $count++; + } + } + if ($count === 1) { + $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 (!class_exists('PDO')) { + return $this->setError('PHP PDO class is require.'); + } + + 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 (defined('ELFINDER_DROPBOX_USE_CURL_PUT')) { + $this->oauth = new Dropbox_OAuth_Curl($this->options['consumerKey'], $this->options['consumerSecret']); + } else { + 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 + try { + $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'); + } + } catch (PDOException $e) { + return $this->setError('PDO connection failed: '.$e->getMessage()); + } + + $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 (!empty($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(); + $sth = $this->DB->prepare('select dat from '.$this->DB_TableName.' WHERE path LIKE ? AND fname LIKE ?'); + $sth->execute(array('%'.(($path === $this->root)? '' : strtolower($path)), '%'.strtolower($q).'%')); + $res = $sth->fetchAll(PDO::FETCH_COLUMN); + if ($res) { + foreach($res as $raw) { + $raw = unserialize($raw); + if ($stat = $this->parseRaw($raw)) { + if (!isset($this->cache[$raw['path']])) { + $stat = $this->updateCache($raw['path'], $stat); + } + if ($stat['mime'] !== 'directory' || $this->mimeAccepted($stat['mime'], $mimes)) { + $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; + } + } + if ($url) { + list($url) = explode('?', $url); + } + 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 (($mode == 'rb' || $mode == 'r')) { + try { + $res = $this->dropbox->media($path); + $url = parse_url($res['url']); + $fp = stream_socket_client('ssl://'.$url['host'].':443'); + fputs($fp, "GET {$url['path']} HTTP/1.0\r\n"); + fputs($fp, "Host: {$url['host']}\r\n"); + fputs($fp, "\r\n"); + while(trim(fgets($fp)) !== ''){}; + return $fp; + } catch (Dropbox_Exception $e) { + return false; + } + } + + 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) { + $this->deltaCheck(); + if ($this->dir($this->encode($path))) { + return $path; + } + 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTP.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTP.class.php new file mode 100644 index 00000000..1887de92 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTP.class.php @@ -0,0 +1,1430 @@ + '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 = ''; + + /** + * Net mount key + * + * @var string + **/ + public $netMountKey = ''; + + /** + * 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, + 'icon' => (defined('ELFINDER_IMG_PARENT_URL')? (rtrim(ELFINDER_IMG_PARENT_URL, '/').'/') : '').'img/volume_icon_ftp.png' + + ); + $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.'); + } + + // make ney mount key + $this->netMountKey = md5(join('-', array('ftp', $this->options['host'], $this->options['port'], $this->options['path'], $this->options['user']))); + + 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 . '"'); + $descriptorspec = array( + 0 => array("pipe", "r"), // stdin is a pipe that the child will read from + 1 => array("pipe", "w"), // stdout is a pipe that the child will write to + 2 => array("pipe", "w") // stderr is a file to write to + ); + + + $process = proc_open($command, $descriptorspec, $pipes, $cwd); + + if (is_resource($process)) { + fclose($pipes[0]); + fclose($pipes[1]); + $return_value = proc_close($process); + } + + unlink($basename); + $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); + + $descriptorspec = array( + 0 => array("pipe", "r"), // stdin is a pipe that the child will read from + 1 => array("pipe", "w"), // stdout is a pipe that the child will write to + 2 => array("pipe", "w") // stderr is a file to write to + ); + + + $process = proc_open($command, $descriptorspec, $pipes, $cwd); + + if (is_resource($process)) { + fclose($pipes[0]); + fclose($pipes[1]); + $return_value = proc_close($process); + } + + $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, 0700, 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
  • + *
+ */ + protected 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTPIIS.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTPIIS.class.php new file mode 100644 index 00000000..baf780b0 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeFTPIIS.class.php @@ -0,0 +1,134 @@ +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 + $this->options['mode'] = 'active'; + ftp_pasv($this->connect, $this->options['mode'] == 'passive'); + + // enter root folder + if (!ftp_chdir($this->connect, $this->root)) + { + $this->umount(); + return $this->setError('Unable to open root folder.'); + } + + $stat = array(); + $stat['name'] = $this->root; + $stat['mime'] = 'directory'; + $this->filesCache[$this->root] = $stat; + $this->cacheDir($this->root); + + return true; + } + + /** + * Parse line from ftp_rawlist() output and return file stat (array) + * + * @param string $raw line from ftp_rawlist() output + * @return array + **/ + protected function parseRaw($raw) { + $info = preg_split("/\s+/", $raw, 9); + $stat = array(); + + $stat['name'] = join(" ", array_slice($info, 3, 9)); + $stat['read'] = true; + if ($info[2] == '') + { + $stat['size'] = 0; + $stat['mime'] = 'directory'; + } + else + { + $stat['size'] = $info[2]; + $stat['mime'] = $this->mimetype($stat['name']); + } + + return $stat; + } + + /** + * Cache dir contents + * + * @param string $path dir path + * @return void + **/ + 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.DIRECTORY_SEPARATOR.$stat['name']; + // $files[] = $stat; + $this->dirsCache[$path][] = $p; + //$stat['name'] = $p; + $this->filesCache[$p] = $stat; + } + } + } + + protected function _stat($path) { + $stat = array(); + + $stat = $this->filesCache[$path]; + + if (empty($stat)) + { + $this->cacheDir($this->_dirname($path)); + $stat = $this->filesCache[$path]; + + } + + return $stat; + } + + + protected function ftp_scan_dir($remote_directory) + { + $buff = ftp_rawlist($this->connect, $remote_directory, true); + $items = array(); + foreach ($buff as $str) { + $info = preg_split("/\s+/", $str, 9); + $remote_file_path = $remote_directory . DIRECTORY_SEPARATOR . join(" ", array_slice($info, 3, 9)); + $item = array(); + $item['type'] = $info[2] == '' ? 'd' : 'f'; + $item['path'] = $remote_file_path; + $items[] = $item; + + if ($item['type'] == 'd') + $items = array_merge($items, $this->ftp_scan_dir($item['path'])); + } + return $items; + } +} // END class + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeLocalFileSystem.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeLocalFileSystem.class.php new file mode 100644 index 00000000..4f2ca4eb --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeLocalFileSystem.class.php @@ -0,0 +1,763 @@ +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) + $this->options['icon'] = (defined('ELFINDER_IMG_PARENT_URL')? (rtrim(ELFINDER_IMG_PARENT_URL, '/').'/') : '').'img/volume_icon_local.png'; + } + + /*********************************************************************/ + /* 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) { + $real_path = realpath($path); + $real_parent = realpath($parent); + if ($real_path && $real_parent) { + return $real_path === $real_parent || strpos($real_path, $real_parent.DIRECTORY_SEPARATOR) === 0; + } + return false; + } + + + + /***************** 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($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); + $stat['write'] = is_writable($path); + 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; + } + + if ($this->_inpath($target, $this->aroot)) { + $atarget = realpath($target); + 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() { + $this->archivers = $this->getArchivers(); + 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) { + $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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeMySQL.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeMySQL.class.php new file mode 100644 index 00000000..d9a7ce1f --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeMySQL.class.php @@ -0,0 +1,961 @@ + 'localhost', + 'user' => '', + 'pass' => '', + 'db' => '', + 'port' => null, + 'socket' => null, + 'files_table' => 'elfinder_file', + 'tmbPath' => '', + 'tmpPath' => '', + 'icon' => (defined('ELFINDER_IMG_PARENT_URL')? (rtrim(ELFINDER_IMG_PARENT_URL, '/').'/') : '').'img/volume_icon_sql.png' + ); + $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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeS3.class.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/elFinderVolumeS3.class.php new file mode 100644 index 00000000..b1e900e1 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/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, $stat) { + 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/mime.types b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/mime.types new file mode 100644 index 00000000..94b99b77 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/AutoResize/plugin.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/AutoResize/plugin.php new file mode 100644 index 00000000..d9f0e676 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Normalizer/plugin.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Normalizer/plugin.php new file mode 100644 index 00000000..9f5e78c7 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Normalizer/plugin.php @@ -0,0 +1,121 @@ += 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' => array( + * '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 true; + } + + 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/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Sanitizer/plugin.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Sanitizer/plugin.php new file mode 100644 index 00000000..9f548caf --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Sanitizer/plugin.php @@ -0,0 +1,100 @@ + array( + * 'mkdir.pre mkfile.pre rename.pre' => array( + * 'Plugin.Sanitizer.cmdPreprocess' + * ), + * 'upload.presave' => array( + * 'Plugin.Sanitizer.onUpLoadPreSave' + * ) + * ), + * // global configure (optional) + * 'plugin' => array( + * 'Sanitizer' => array( + * 'enable' => true, + * 'targets' => array('\\','/',':','*','?','"','<','>','|'), // target chars + * 'replace' => '_' // replace to this + * ) + * ), + * // each volume configure (optional) + * 'roots' => array( + * array( + * 'driver' => 'LocalFileSystem', + * 'path' => '/path/to/files/', + * 'URL' => 'http://localhost/to/files/' + * 'plugin' => array( + * 'Sanitizer' => array( + * 'enable' => true, + * 'targets' => array('\\','/',':','*','?','"','<','>','|'), // target chars + * 'replace' => '_' // replace to this + * ) + * ) + * ) + * ) + * ); + * + * @package elfinder + * @author Naoki Sawada + * @license New BSD + */ +class elFinderPluginSanitizer +{ + private $opts = array(); + + public function __construct($opts) { + $defaults = array( + 'enable' => true, // For control by volume driver + 'targets' => array('\\','/',':','*','?','"','<','>','|'), // target chars + 'replace' => '_' // replace to this + ); + + $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->sanitizeFileName($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->sanitizeFileName($path, $opts, array('/')); + } + $name = $this->sanitizeFileName($name, $opts); + return true; + } + + private function getOpts($volume) { + $opts = $this->opts; + if (is_object($volume)) { + $volOpts = $volume->getOptionsPlugin('Sanitizer'); + if (is_array($volOpts)) { + $opts = array_merge($this->opts, $volOpts); + } + } + return $opts; + } + + private function sanitizeFileName($filename, $opts, $allows = array()) { + $targets = $allows? array_diff($opts['targets'], $allows) : $opts['targets']; + return str_replace($targets, $opts['replace'], $filename); + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Watermark/logo.png b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Watermark/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ca6fe8a2d66890a7232f7d4bb81178858f51c111 GIT binary patch literal 12806 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 M#O1|mL=1!e2j3r+761SM literal 0 HcmV?d00001 diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Watermark/plugin.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/plugins/Watermark/plugin.php new file mode 100644 index 00000000..84b9bb43 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Elfinder/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/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/RemoteimageComponent.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/RemoteimageComponent.php new file mode 100644 index 00000000..7af10e14 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/RemoteimageComponent.php @@ -0,0 +1,80 @@ +container->registerServiceProvider(new RemoteimageProvider); + + // Load language + $lang = $this->container->get('language'); + + LanguageHelper::loadAll($lang->getTag(), $this->option); + + // Load asset + $asset = $this->container->get('helper.asset'); + + $asset->windwalker(); + + // Register tasks + TaskMapper::register($this); + + include_once JPATH_ADMINISTRATOR . '/includes/toolbar.php'; + + parent::prepare(); + } + + /** + * Post execute hook. + * + * @param mixed $result The return value of this component. + * + * @return mixed The return value of this component. + */ + protected function postExecute($result) + { + // Debug profiler + if (JDEBUG) + { + $result .= "
" . ProfilerHelper::render('Windwalker', true); + } + + return parent::postExecute($result); + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/TaskMapper.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/TaskMapper.php new file mode 100644 index 00000000..c72ef41f --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/TaskMapper.php @@ -0,0 +1,31 @@ +registerTask('manager.connect', '\\Remoteimage\\Controller\\ManagerController'); + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/index.html b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Component/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Config/Config.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Config/Config.php new file mode 100644 index 00000000..503b8ec9 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Config/Config.php @@ -0,0 +1,41 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Controller/ManagerController.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Controller/ManagerController.php new file mode 100644 index 00000000..7012fc4a --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Controller/ManagerController.php @@ -0,0 +1,161 @@ +get('Safemode', true); + $host = $params->get('Ftp_Host', '127.0.0.1'); + $port = $params->get('Ftp_Port', 21); + $user = $params->get('Ftp_User'); + $pass = $params->get('Ftp_Password'); + $active = $params->get('Ftp_Active', 'passive'); + $url = $params->get('Ftp_Url'); + $root = $params->get('Ftp_Root', '/'); + $local_root = $params->get('Local_Root', 'images'); + //Patch + $image_resize_enabled = $params->get('Image_Resize_Enabled', true); + $image_max_width = $params->get('Image_Max_Width', 1024); + $image_max_height = $params->get('Image_Max_Height', 1024); + $image_jpeg_quality = $params->get('Image_JPEG_Quality', 95); + // End patch + + $roots = array(); + + if ($params->get('Connection_Local', 1)) + { + $roots[] = array( + 'driver' => 'LocalFileSystem', + //'alias' => $local_root, + 'path' => JPATH_ROOT . '/' . trim($local_root, '/'), + 'URL' => \JURI::root() . trim($local_root, '/'), + 'accessControl' => array(__CLASS__, 'access'), + 'uploadDeny' => array('text/x-php'), + 'icon' => \JURI::root() . 'administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_local.png', + 'tmbPath' => JPATH_ROOT . '/cache/elfinderThumbs', + 'tmbURL' => \JURI::root() . '/cache/elfinderThumbs', + 'tmbPathMode' => 0755, + 'tmp' => JPATH_ROOT . '/cache/elfinderTemps', + ); + } + + if ($params->get('Connection_Ftp', 0)) + { + $roots[] = array( + 'driver' => 'FTP', + 'alias' => $host, + 'host' => $host, + 'user' => $user, + 'pass' => $pass, + 'port' => $port, + 'mode' => $active, + 'path' => $root, + 'timeout' => 10, + 'owner' => true, + 'tmbPath' => JPATH_ROOT . '/cache/elfinderThumbs', + 'tmbURL' => \JURI::root() . '/cache/elfinderThumbs', + 'tmp' => JPATH_ROOT . '/cache/elfinderTemps', + 'tmbPathMode' => 0755, + 'dirMode' => 0755, + 'fileMode' => 0644, + 'URL' => $url, + 'checkSubfolders' => false, + 'uploadDeny' => array('text/x-php'), + 'icon' => \JURI::root() . 'administrator/components/com_remoteimage/asset/js/elfinder/img/volume_icon_ftp.png' + ); + } + + // Safe Mode + if ($safemode) + { + foreach ($roots as &$root): + $root['disabled'] = array('archive', 'extract', 'rename', 'mkfile'); + endforeach; + } +//Patch + $lResizePluginOption = array(); + + $lResizePluginOption['enable'] = $image_resize_enabled; + + if ($image_max_width > 0) { + $lResizePluginOption['maxWidth'] = $image_max_width; + } + + if ($image_max_height > 0) { + $lResizePluginOption['maxHeight'] = $image_max_height; + } + + if ($image_jpeg_quality > 0) { + $lResizePluginOption['quality'] = $image_jpeg_quality; + } + + + $opts = array( + 'plugin' => array( + 'AutoResize' => $lResizePluginOption + ), + 'bind' => array( + 'upload.presave' => array( + 'Plugin.AutoResize.onUpLoadPreSave' + ) + ), + // 'debug' => true, + 'roots' => $roots + ); + + // Run elFinder + $connector = new \elFinderConnector(new \elFinder($opts)); + $connector->run(); + + exit(); + } +// End patch + /** + * Simple function to demonstrate how to control file access using "accessControl" callback. + * This method will disable accessing files/folders starting from '.' (dot) + * + * @param string $attr attribute name (read|write|locked|hidden) + * @param string $path file path relative to volume root directory started with directory separator + * @param array $data The data. + * @param string $volume Volume. + * + * @return bool|null + */ + public static function access($attr, $path, $data, $volume) + { + return strpos(basename($path), '.') === 0 // if file/folder begins with '.' (dot) + ? !($attr == 'read' || $attr == 'write') // set read+write to false, other (locked+hidden) set to true + : null; // else elFinder decide it itself + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/LiteListener.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/LiteListener.php new file mode 100644 index 00000000..53d2def4 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/LiteListener.php @@ -0,0 +1,370 @@ +text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return void + */ + public function onContentPrepare($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + + // Do some stuff + } + + /** + * Remoteimage after display title method + * Method is called by the view and the results are imploded and displayed in a placeholder + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article The content object. Note $article->text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return string + */ + public function onContentAfterTitle($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + /** + * Remoteimage before display content method + * Method is called by the view and the results are imploded and displayed in a placeholder + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article The content object. Note $article->text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return string + */ + public function onContentBeforeDisplay($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + /** + * Remoteimage after display content method + * Method is called by the view and the results are imploded and displayed in a placeholder + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article The content object. Note $article->text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return string + */ + public function onContentAfterDisplay($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + /** + * Remoteimage before save content method + * Method is called right before content is saved into the database. + * Article object is passed by reference, so any changes will be saved! + * NOTE: Returning false will abort the save with an error. + *You can set the error by calling $article->setError($message) + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article A JTableContent object. + * @param bool $isNew If the content is just about to be created. + * + * @return bool If false, abort the save. + */ + public function onContentBeforeSave($context, $article, $isNew) + { + $app = JFactory::getApplication(); + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remoteimage after save content method + * Article is passed by reference, but after the save, so no changes will be saved. + * Method is called right after the content is saved + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article A JTableContent object. + * @param boolean $isNew If the content is just about to be created. + * + * @return boolean + */ + public function onContentAfterSave($context, $article, $isNew) + { + $app = JFactory::getApplication(); + + // Do some stuff + + return true; + } + + /** + * Remoteimage before delete method. + * + * @param string $context The context for the content passed to the plugin. + * @param object $data The data relating to the content that is to be deleted. + * + * @return boolean False to abort. + */ + public function onContentBeforeDelete($context, $data) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remoteimage after delete method. + * + * @param string $context The context for the content passed to the plugin. + * @param object $data The data relating to the content that is to be deleted. + * + * @return boolean + */ + public function onContentAfterDelete($context, $data) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remoteimage on change state method. + * + * @param string $context The context for the content passed to the plugin. + * @param array $pks A list of primary key ids of the content that has changed state. + * @param int $value The value of the state that the content has been changed to. + * + * @return boolean + */ + public function onContentChangeState($context, $pks, $value) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + + + // Form Events + // ==================================================================================== + + /** + * Pre process form hook. + * + * @param JForm $form The form to be altered. + * @param array $data The associated data for the form. + * + * @return boolean + */ + public function onContentPrepareForm($form, $data) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + // User Events + // ==================================================================================== + + /** + * Utility method to act on a user after it has been saved. + * + * @param array $user Holds the new user data. + * @param boolean $isNew True if a new user is stored. + * @param boolean $success True if user was succesfully stored in the database. + * @param string $msg Message. + * + * @return boolean + */ + public function onUserBeforeSave($user, $isNew, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Utility method to act on a user after it has been saved. + * + * @param array $user Holds the new user data. + * @param boolean $isNew True if a new user is stored. + * @param boolean $success True if user was succesfully stored in the database. + * @param string $msg Message. + * + * @return boolean + */ + public function onUserAfterSave($user, $isNew, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * This method should handle any login logic and report back to the subject + * + * @param array $user Holds the user data + * @param array $options Array holding options (remember, autoregister, group) + * + * @return boolean True on success + */ + public function onUserLogin($user, $options = array()) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * This method should handle any logout logic and report back to the subject + * + * @param array $user Holds the user data. + * @param array $options Array holding options (client, ...). + * + * @return object True on success + */ + public function onUserLogout($user, $options = array()) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Utility method to act on a user before it has been saved. + * + * @param array $user Holds the new user data. + * @param boolean $isnew True if a new user is stored. + * @param boolean $success True if user was succesfully stored in the database. + * @param string $msg Message. + * + * @return boolean + */ + public function onUserBeforeDelete($user, $isnew, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remove all sessions for the user name + * + * @param array $user Holds the user data + * @param boolean $success True if user was succesfully stored in the database + * @param string $msg Message + * + * @return boolean + */ + public function onUserAfterDelete($user, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Prepare content data. + * + * @param string $context The context for the data + * @param int $data The user id + * + * @return boolean + */ + public function onContentPrepareData($context, $data) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * resultBool + * + * @param array $result + * + * @return bool + */ + public function resultBool($result = array()) + { + if (in_array(false, $result)) + { + return false; + } + + return true; + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/index.html b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Lite/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/ProListener.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/ProListener.php new file mode 100644 index 00000000..e966f74c --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/ProListener.php @@ -0,0 +1,407 @@ +text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return void + */ + public function onContentPrepare($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + + // Do some stuff + } + + /** + * Remoteimage after display title method + * Method is called by the view and the results are imploded and displayed in a placeholder + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article The content object. Note $article->text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return string + */ + public function onContentAfterTitle($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + /** + * Remoteimage before display content method + * Method is called by the view and the results are imploded and displayed in a placeholder + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article The content object. Note $article->text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return string + */ + public function onContentBeforeDisplay($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + /** + * Remoteimage after display content method + * Method is called by the view and the results are imploded and displayed in a placeholder + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article The content object. Note $article->text is also available. + * @param object $params The content params. + * @param int $page The 'page' number. + * + * @return string + */ + public function onContentAfterDisplay($context, $article, $params, $page = 0) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + /** + * Remoteimage before save content method + * Method is called right before content is saved into the database. + * Article object is passed by reference, so any changes will be saved! + * NOTE: Returning false will abort the save with an error. + *You can set the error by calling $article->setError($message) + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article A JTableContent object. + * @param bool $isNew If the content is just about to be created. + * + * @return bool If false, abort the save. + */ + public function onContentBeforeSave($context, $article, $isNew) + { + $app = JFactory::getApplication(); + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remoteimage after save content method + * Article is passed by reference, but after the save, so no changes will be saved. + * Method is called right after the content is saved + * + * @param string $context The context of the content being passed to the plugin. + * @param object $article A JTableContent object. + * @param boolean $isNew If the content is just about to be created. + * + * @return boolean + */ + public function onContentAfterSave($context, $article, $isNew) + { + $app = JFactory::getApplication(); + + // Do some stuff + + return true; + } + + /** + * Remoteimage before delete method. + * + * @param string $context The context for the content passed to the plugin. + * @param object $data The data relating to the content that is to be deleted. + * + * @return boolean False to abort. + */ + public function onContentBeforeDelete($context, $data) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remoteimage after delete method. + * + * @param string $context The context for the content passed to the plugin. + * @param object $data The data relating to the content that is to be deleted. + * + * @return boolean + */ + public function onContentAfterDelete($context, $data) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remoteimage on change state method. + * + * @param string $context The context for the content passed to the plugin. + * @param array $pks A list of primary key ids of the content that has changed state. + * @param int $value The value of the state that the content has been changed to. + * + * @return boolean + */ + public function onContentChangeState($context, $pks, $value) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + + + // Form Events + // ==================================================================================== + + /** + * Pre process form hook. + * + * @param \JForm $form The form to be altered. + * @param array $data The associated data for the form. + * + * @return boolean + */ + public function onContentPrepareForm($form, $data) + { + $app = JFactory::getApplication(); + $result = null; + + // Do some stuff + + return $result; + } + + // User Events + // ==================================================================================== + + /** + * Utility method to act on a user after it has been saved. + * + * @param array $user Holds the new user data. + * @param boolean $isNew True if a new user is stored. + * @param boolean $success True if user was succesfully stored in the database. + * @param string $msg Message. + * + * @return boolean + */ + public function onUserBeforeSave($user, $isNew, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Utility method to act on a user after it has been saved. + * + * @param array $user Holds the new user data. + * @param boolean $isNew True if a new user is stored. + * @param boolean $success True if user was succesfully stored in the database. + * @param string $msg Message. + * + * @return boolean + */ + public function onUserAfterSave($user, $isNew, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * This method should handle any login logic and report back to the subject + * + * @param array $user Holds the user data + * @param array $options Array holding options (remember, autoregister, group) + * + * @return boolean True on success + */ + public function onUserLogin($user, $options = array()) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * This method should handle any logout logic and report back to the subject + * + * @param array $user Holds the user data. + * @param array $options Array holding options (client, ...). + * + * @return object True on success + */ + public function onUserLogout($user, $options = array()) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Utility method to act on a user before it has been saved. + * + * @param array $user Holds the new user data. + * @param boolean $isnew True if a new user is stored. + * @param boolean $success True if user was succesfully stored in the database. + * @param string $msg Message. + * + * @return boolean + */ + public function onUserBeforeDelete($user, $isnew, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Remove all sessions for the user name + * + * @param array $user Holds the user data + * @param boolean $success True if user was succesfully stored in the database + * @param string $msg Message + * + * @return boolean + */ + public function onUserAfterDelete($user, $success, $msg) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * Prepare content data. + * + * @param string $context The context for the data + * @param int $data The user id + * + * @return boolean + */ + public function onContentPrepareData($context, $data) + { + $result = array(); + + // Do some stuff + + return $this->resultBool($result); + } + + /** + * resultBool + * + * @param array $result + * + * @return bool + */ + public function resultBool($result = array()) + { + if (in_array(false, $result)) + { + return false; + } + + return true; + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/index.html b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/Pro/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/index.html b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Listener/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Provider/RemoteimageProvider.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Provider/RemoteimageProvider.php new file mode 100644 index 00000000..8ca40ab2 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Provider/RemoteimageProvider.php @@ -0,0 +1,34 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Router/Route.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Router/Route.php new file mode 100644 index 00000000..791958b1 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/Router/Route.php @@ -0,0 +1,44 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/View/ManagerView.php b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/View/ManagerView.php new file mode 100644 index 00000000..ddabe3d9 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/View/ManagerView.php @@ -0,0 +1,155 @@ +engine = new PhpEngine; + + parent::__construct($model, $container, $config, $paths); + } + + /** + * Prepare data hook. + * + * @return void + */ + protected function prepareData() + { + $input = $this->container->get('input'); + $data = $this->getData(); + + $data->params = $params = \Windwalker\System\ExtensionHelper::getParams('com_remoteimage'); + + $lang = $this->container->get('language'); + $data->langCode = $lang->getTag(); + $data->langCode = str_replace('-', '_', $data->langCode); + + $this->prepareScript(); + + if ('component' == $input->get('tmpl')) + { + $params->set('isModal', true); + $data->modal = true; + } + else + { + $params->set('isModal', false); + $data->modal = false; + } + + $params->set('tabs', $data->modal); + $params->set('height', $data->modal ? $input->get('height', 380) : 520); + $params->set('fieldId', $input->get('fieldid')); + $params->set('insertId', $input->get('insert_id')); + + $data->uploadMax = ini_get('upload_max_filesize'); + $data->uploadNum = ini_get('max_file_uploads'); + + $this->setTitle(\JText::_('COM_REMOTEIMAGE_TITLE_MANAGER')); + \JToolbarHelper::preferences('com_remoteimage'); + } + + /** + * Display elFinder script. + * + * @return void + */ + protected function prepareScript() + { + $lang_code = $this->data->langCode; + + // Include elFinder and JS + // ================================================================================ + + $asset = $this->container->get('helper.asset'); + + // JQuery + $asset->mootools(); + $asset->jquery(); + $asset->bootstrap(); + + // ElFinder includes + $asset->addCss('js/jquery-ui/css/smoothness/jquery-ui-1.8.24.custom.css'); + $asset->addCss('js/elfinder/css/elfinder.min.css'); + $asset->addCss('js/elfinder/css/theme.css'); + $asset->addCss('remoteimage.css'); + + $asset->addJs('js/jquery/jquery-ui.min.js'); + $asset->addJs('js/elfinder/js/elfinder.full.js'); + + $iso639_1_lang_code = substr($lang_code, 0, 2); + if (is_file(REMOTEIMAGE_ADMIN . '/asset/js/elfinder/js/i18n/elfinder.' . $iso639_1_lang_code . '.js')) + { + $asset->addJs("js/elfinder/js/i18n/elfinder.$iso639_1_lang_code.js"); + } + } +} diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/index.html b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/Remoteimage/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/index.html b/packages/remoteimage/administrator/components/com_remoteimage/src/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/src/init.php b/packages/remoteimage/administrator/components/com_remoteimage/src/init.php new file mode 100644 index 00000000..ca50e2e7 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/src/init.php @@ -0,0 +1,17 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/view/manager/html.php b/packages/remoteimage/administrator/components/com_remoteimage/view/manager/html.php new file mode 100644 index 00000000..1b9330f2 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/view/manager/html.php @@ -0,0 +1,19 @@ + diff --git a/packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/default.php b/packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/default.php new file mode 100644 index 00000000..4f132d1a --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/default.php @@ -0,0 +1,244 @@ +data; +$date = JFactory::getDate('now', JFactory::getConfig()->get('offset')); +$doc = JFactory::getDocument(); +$uri = \JUri::getInstance(); +$user = JFactory::getUser(); +$app = JFactory::getApplication(); + + +// PARAMS +/** + * @var $lang string + * @var $params Joomla\Registry\Registry + */ +$lang = $data->langCode; +$lang = substr($data->langCode, 0, 2); +$params = $data->params; +$safemode = $params->get('Safemode', true); +$onlyimage = $params->get('Onlyimage', false); +$tabs = $params->get('tabs', false); +$height = $params->get('height', 350); + +// System Info +$sysinfo = JText::_('COM_REMOTEIMAGE_UPLOAD_MAX') . ' ' . $data->uploadMax; +$sysinfo .= ' | ' . JText::_('COM_REMOTEIMAGE_UPLOAD_NUM') . ' ' . $data->uploadNum; + + +// Is FormField +$fieldid = $params->get('fieldId'); +?> + + + + +
+ + 'panel-elfinder')) : ''; ?> + + + +
+
+ +
+
+ + + modal): ?> + + + +

+ + + + + + + modal): ?> +
+
+
+ + +    + + +
+ +
+ + + + + +
+
+
+ + +
diff --git a/packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/index.html b/packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/administrator/components/com_remoteimage/view/manager/tmpl/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/asset/css/index.html b/packages/remoteimage/components/com_remoteimage/asset/css/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/asset/css/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/asset/css/main.css b/packages/remoteimage/components/com_remoteimage/asset/css/main.css new file mode 100644 index 00000000..7ae77ea5 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/asset/css/main.css @@ -0,0 +1,33 @@ +/*! + * com_remoteimage + * + * Copyright 2014 SMS Taiwan + * License GNU General Public License version 2 or later; see LICENSE.txt. + */ + + +/* GLOBAL */ + + +/* BODY */ + + +/* TYPO */ + + +/* LAYOUT */ + + +/* CONTENT */ + + +/* FILTER */ + + +/* TABLE */ + + +/* FORM */ + + +/* FOOTER */ diff --git a/packages/remoteimage/components/com_remoteimage/asset/index.html b/packages/remoteimage/components/com_remoteimage/asset/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/asset/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/asset/js/index.html b/packages/remoteimage/components/com_remoteimage/asset/js/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/asset/js/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/asset/js/main.js b/packages/remoteimage/components/com_remoteimage/asset/js/main.js new file mode 100644 index 00000000..8d43866b --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/asset/js/main.js @@ -0,0 +1,8 @@ +/** +* @package Joomla.Site +* @subpackage com_remoteimage +* @copyright Copyright (C) 2014 Asikart. All rights reserved. +* @license GNU General Public License version 2 or later; see LICENSE.txt +*/ + +var Remoteimage = {}; \ No newline at end of file diff --git a/packages/remoteimage/components/com_remoteimage/component.php b/packages/remoteimage/components/com_remoteimage/component.php new file mode 100644 index 00000000..dc6626dd --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/component.php @@ -0,0 +1,37 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/index.html b/packages/remoteimage/components/com_remoteimage/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/remoteimage.php b/packages/remoteimage/components/com_remoteimage/remoteimage.php new file mode 100644 index 00000000..f92c219b --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/remoteimage.php @@ -0,0 +1,14 @@ +execute(); diff --git a/packages/remoteimage/components/com_remoteimage/router.php b/packages/remoteimage/components/com_remoteimage/router.php new file mode 100644 index 00000000..7e074db5 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/router.php @@ -0,0 +1,114 @@ +build($query['view'], $query); + + unset($query['view']); + } + + return $segments; + } +} + +if (!function_exists('RemoteimageParseRoute')) +{ + /** + * RemoteimageParseRoute + * + * @param array $segments + * + * @return array + */ + function RemoteimageParseRoute($segments) + { + $router = CmsRouter::getInstance('com_remoteimage'); + + $segments = implode('/', $segments); + + // OK, let's fetch view name. + $view = $router->getView(str_replace(':', '-', $segments)); + + if ($view) + { + return array('view' => $view); + } + + return array(); + } +} + +if (class_exists('JComponentRouterBase')) +{ + class RemoteimageRouter extends JComponentRouterBase + { + /** + * Build method for URLs + * This method is meant to transform the query parameters into a more human + * readable form. It is only executed when SEF mode is switched on. + * + * @param array &$query An array of URL arguments + * + * @return array The URL arguments to use to assemble the subsequent URL. + * + * @since 2.0.8 + */ + public function build(&$query) + { + return RemoteimageBuildRoute($query); + } + + /** + * Parse method for URLs + * This method is meant to transform the human readable URL back into + * query parameters. It is only executed when SEF mode is switched on. + * + * @param array &$segments The segments of the URL to parse. + * + * @return array The URL attributes to be used by the application. + * + * @since 2.0.8 + */ + public function parse(&$segments) + { + return RemoteimageParseRoute($segments); + } + } +} diff --git a/packages/remoteimage/components/com_remoteimage/routing.json b/packages/remoteimage/components/com_remoteimage/routing.json new file mode 100644 index 00000000..52a7e783 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/routing.json @@ -0,0 +1,11 @@ +{ + "managers": { + "pattern": "managers/:id", + "view" : "managers" + }, + + "manager": { + "pattern": "manager/:id/:alias", + "view" : "manager" + } +} \ No newline at end of file diff --git a/packages/remoteimage/components/com_remoteimage/view/index.html b/packages/remoteimage/components/com_remoteimage/view/index.html new file mode 100644 index 00000000..2efb97f3 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/view/index.html @@ -0,0 +1 @@ + diff --git a/packages/remoteimage/components/com_remoteimage/view/manager/html.php b/packages/remoteimage/components/com_remoteimage/view/manager/html.php new file mode 100644 index 00000000..36d45dd2 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/view/manager/html.php @@ -0,0 +1,61 @@ +container->get('app'); + $user = $this->container->get('user'); + + if ($app->isSite() && !$user->authorise('frontend.access', 'com_remoteimage')) + { + throw new \Exception(JText::_('JGLOBAL_RESOURCE_NOT_FOUND'), 404); + } + + parent::prepareRender(); + } + + /** + * Display elFinder script. + * + * @return void + */ + protected function prepareScript() + { + // Include elFinder and JS + // ================================================================================ + + $asset = $this->container->get('helper.asset'); + + $paths = $asset->getPaths(); + + // (3) Find: components/[name]/asset/[type]/[file_name].[type] + $paths->insert('administrator/components/{name}/asset/{type}', 600); + + // (4) Find: components/[name]/asset/[file_name].[type] + $paths->insert('administrator/components/{name}/asset', 500); + + parent::prepareScript(); + } +} diff --git a/packages/remoteimage/components/com_remoteimage/view/manager/index.html b/packages/remoteimage/components/com_remoteimage/view/manager/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/view/manager/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/components/com_remoteimage/view/manager/tmpl/default.php b/packages/remoteimage/components/com_remoteimage/view/manager/tmpl/default.php new file mode 100644 index 00000000..38c18118 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/view/manager/tmpl/default.php @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/remoteimage/components/com_remoteimage/view/manager/tmpl/index.html b/packages/remoteimage/components/com_remoteimage/view/manager/tmpl/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/components/com_remoteimage/view/manager/tmpl/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/index.html b/packages/remoteimage/plugins/editors-xtd/remoteimage/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/install.php b/packages/remoteimage/plugins/editors-xtd/remoteimage/install.php new file mode 100644 index 00000000..90e1f35d --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/install.php @@ -0,0 +1,68 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.ini b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.ini new file mode 100644 index 00000000..b82ed179 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_EDITORS-XTD_REMOTEIMAGE="Button - RemoteImage" +PLG_EDITORS-XTD_REMOTEIMAGE_XML_DESCRIPTION="RemoteImage insert button plugin." +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="RemoteImage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.sys.ini b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.sys.ini new file mode 100644 index 00000000..b82ed179 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/en-GB.plg_editors-xtd_remoteimage.sys.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_EDITORS-XTD_REMOTEIMAGE="Button - RemoteImage" +PLG_EDITORS-XTD_REMOTEIMAGE_XML_DESCRIPTION="RemoteImage insert button plugin." +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="RemoteImage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/index.html b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/en-GB/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/index.html b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/index.html b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.ini b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.ini new file mode 100644 index 00000000..41ec58d6 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_EDITORS-XTD_REMOTEIMAGE="按鈕 - RemoteImage 插入按鈕" +PLG_EDITORS-XTD_REMOTEIMAGE_XML_DESCRIPTION="RemoteImage 遠近端圖片插入按鈕" +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="RemoteImage" diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.sys.ini b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.sys.ini new file mode 100644 index 00000000..9e5360d7 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/language/zh-TW/zh-TW.plg_editors-xtd_remoteimage.sys.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_EDITORS-XTD_REMOTEIMAGE="按鈕 - RemoteImage 插入按鈕" +PLG_EDITORS-XTD_REMOTEIMAGE_XML_DESCRIPTION="RemoteImage 遠近端圖片插入按鈕" +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="RemoteImage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/lib/index.html b/packages/remoteimage/plugins/editors-xtd/remoteimage/lib/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/lib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.php b/packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.php new file mode 100644 index 00000000..daacb94a --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.php @@ -0,0 +1,112 @@ +loadLanguage('com_remoteimage', JPATH_ADMINISTRATOR . '/components/com_remoteimage'); + $this->app = JFactory::getApplication(); + + self::$self = $this; + } + + /** + * Display the button + * + * @param string $name + * @param string $asset + * @param string $author + * + * @return array A two element array of (imageName, textToInsert) + */ + public function onDisplay($name, $asset, $author) + { + $app = JFactory::getApplication(); + $user = JFactory::getUser(); + + if ($app->isSite() && !$user->authorise('frontend.access', 'com_remoteimage')) + { + return array(); + } + + // Add Script + $doc = JFactory::getDocument(); + $doc->addScript(JURI::root(true) . '/administrator/components/com_remoteimage/asset/js/remoteimage-admin.js'); + + // Add Button + $user = JFactory::getUser(); + $extension = $app->input->get('option'); + + if ($asset == '') + { + $asset = $extension; + } + + if ($user->authorise('core.edit', $asset) + || $user->authorise('core.create', $asset) + || (count($user->getAuthorisedCategories($asset, 'core.create')) > 0) + || ($user->authorise('core.edit.own', $asset) && $author == $user->id) + || (count($user->getAuthorisedCategories($extension, 'core.edit')) > 0) + || (count($user->getAuthorisedCategories($extension, 'core.edit.own')) > 0 && $author == $user->id)) + { + $link = 'index.php?option=com_remoteimage&view=manager&tmpl=component&height=420&insert_id=' . $name; + JHtml::_('behavior.modal'); + $button = new JObject; + $button->class = 'btn'; + $button->modal = true; + $button->link = $link; + $button->text = JText::_('COM_REMOTEIMAGE_IMAGE_BUTTON'); + $button->name = 'picture'; + $button->options = "{handler: 'iframe', size: {x: 950, y: 550}}"; + + return $button; + } + else + { + return false; + } + } + + /** + * getInstance + * + * @return PlgButtonRemoteimage + */ + public static function getInstance() + { + return self::$self; + } +} diff --git a/packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.xml b/packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.xml new file mode 100644 index 00000000..40ab2e7e --- /dev/null +++ b/packages/remoteimage/plugins/editors-xtd/remoteimage/remoteimage.xml @@ -0,0 +1,43 @@ + + + plg_editors-xtd_remoteimage + Asika + 2012-11-12 + Copyright (C) 2012 Asikart.com + GNU General Public License version 2 or later; see LICENSE.txt + asika@asikart.com + http://asikart.com + 2.0.9 + PLG_EDITORS-XTD_REMOTEIMAGE_XML_DESCRIPTION + + + + remoteimage.php + index.html + install.php + language + lib + + + + + + diff --git a/packages/remoteimage/plugins/system/remoteimage/index.html b/packages/remoteimage/plugins/system/remoteimage/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/install.php b/packages/remoteimage/plugins/system/remoteimage/install.php new file mode 100644 index 00000000..8066c52a --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/install.php @@ -0,0 +1,68 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.ini b/packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.ini new file mode 100644 index 00000000..73506646 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_SYSTEM_REMOTEIMAGE="System - Remoteimage Redirect" +PLG_SYSTEM_REMOTEIMAGE_XML_DESCRIPTION="This plugin redirect com_media pages when enable replace mode." +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="Remoteimage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.sys.ini b/packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.sys.ini new file mode 100644 index 00000000..73506646 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/en-GB/en-GB.plg_system_remoteimage.sys.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_SYSTEM_REMOTEIMAGE="System - Remoteimage Redirect" +PLG_SYSTEM_REMOTEIMAGE_XML_DESCRIPTION="This plugin redirect com_media pages when enable replace mode." +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="Remoteimage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/en-GB/index.html b/packages/remoteimage/plugins/system/remoteimage/language/en-GB/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/en-GB/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/index.html b/packages/remoteimage/plugins/system/remoteimage/language/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/index.html b/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.ini b/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.ini new file mode 100644 index 00000000..d7ccd0fd --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_SYSTEM_REMOTEIMAGE="系統 - Remoteimage 重導向外掛" +PLG_SYSTEM_REMOTEIMAGE_XML_DESCRIPTION="覆蓋內建媒體管理時,協助轉址用。" +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="Remoteimage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.sys.ini b/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.sys.ini new file mode 100644 index 00000000..d7ccd0fd --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/language/zh-TW/zh-TW.plg_system_remoteimage.sys.ini @@ -0,0 +1,8 @@ +; Asikart Extension +; Copyright (C) 2012 Asikart. All rights reserved. +; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php +; Note : All ini files need to be saved as UTF-8 - No BOM + +PLG_SYSTEM_REMOTEIMAGE="系統 - Remoteimage 重導向外掛" +PLG_SYSTEM_REMOTEIMAGE_XML_DESCRIPTION="覆蓋內建媒體管理時,協助轉址用。" +COM_PLUGINS_REMOTEIMAGE_FIELDSET_LABEL="Remoteimage" \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/lib/index.html b/packages/remoteimage/plugins/system/remoteimage/lib/index.html new file mode 100644 index 00000000..3af63015 --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/lib/index.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/remoteimage/plugins/system/remoteimage/remoteimage.php b/packages/remoteimage/plugins/system/remoteimage/remoteimage.php new file mode 100644 index 00000000..c023ec9b --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/remoteimage.php @@ -0,0 +1,139 @@ +loadLanguage(); + $this->loadLanguage('com_remoteimage', JPATH_ADMINISTRATOR . '/components/com_remoteimage'); + $this->app = JFactory::getApplication(); + + self::$self = $this; + } + + /** + * getInstance + * + * @return PlgSystemRemoteimage + */ + public static function getInstance() + { + return self::$self; + } + + // System Events + // ====================================================================================== + + /** + * onAfterRoute + * + * @throws Exception + * @return void + */ + public function onAfterRoute() + { + $params = JComponentHelper::getParams('com_remoteimage'); + + $user = JFactory::getUser(); + + $auth = ($user->authorise('core.manage', 'com_remoteimage')); + + if ($params->get('Integrate_Override_InsertImageArticle', 1) + || $params->get('Integrate_Override_MediaFormField', 1) + || $params->get('Integrate_Override_MediaManager', 1)) + { + $this->redirectNativeMedia(); + } + } + + /** + * redirectNativeMedia + * + * @return void + * + * @throws Exception + */ + protected function redirectNativeMedia() + { + $app = JFactory::getApplication(); + $user = JFactory::getUser(); + + if ($app->isSite() && !$user->authorise('frontend.access', 'com_remoteimage')) + { + return; + } + + $app = JFactory::getApplication(); + $input = $app->input; + + $uri = JUri::getInstance(); + $option = $input->get('option'); + $view = $input->get('view'); + $tmpl = $input->get('tmpl'); + $fieldid = $input->get('fieldid'); + $params = JComponentHelper::getParams('com_remoteimage'); + + $doc = JFactory::getDocument(); + $doc->addScript(JURI::root(true) . '/administrator/components/com_remoteimage/asset/js/remoteimage-admin.js'); + + // Replace Insert to Article + if ($option == 'com_media' && $view == 'images' && !$fieldid && $tmpl == 'component' && $params->get('Integrate_Override_InsertImageArticle', 1)) + { + $uri->setVar('option', 'com_remoteimage'); + $uri->delVar('view'); + $uri->setVar('insert_id', $input->get('e_name')); + + $app->redirect((string) $uri); + } + + // Replace FormField + if ($option == 'com_media' && $view == 'images' && $fieldid && $tmpl == 'component' && $params->get('Integrate_Override_MediaFormField', 1)) + { + $uri->setVar('option', 'com_remoteimage'); + $uri->delVar('view'); + + $app->redirect((string) $uri); + } + + // Replace Media Manager + if ($option == 'com_media' && ($view == 'image' || !$view) && $params->get('Integrate_Override_MediaManager', 1)) + { + $uri->setVar('option', 'com_remoteimage'); + $uri->delVar('view'); + + $app->redirect((string) $uri); + } + } +} diff --git a/packages/remoteimage/plugins/system/remoteimage/remoteimage.xml b/packages/remoteimage/plugins/system/remoteimage/remoteimage.xml new file mode 100644 index 00000000..bfb3aa1b --- /dev/null +++ b/packages/remoteimage/plugins/system/remoteimage/remoteimage.xml @@ -0,0 +1,48 @@ + + + plg_system_remoteimage + Asika + 2012-11-12 + Copyright (C) 2012 Asikart.com + GNU General Public License version 2 or later; see LICENSE.txt + asika@asikart.com + http://asikart.com + 2.0.9 + PLG_SYSTEM_REMOTEIMAGE_XML_DESCRIPTION + + + install.php + + + + + + remoteimage.php + index.html + install.php + language + lib + + + + + + + + + + +