diff --git a/CHANGELOG b/CHANGELOG index 272f839fb..c3e280963 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,17 @@ +Hubzilla 3.8.3 (2018-11-05) + - Do not count likes in forum notifications if likes notifications are disabled + - Fix typo in spanish translation which broke javascript + - Improve linkinfo charset handling and image detection + - Fix wrong image resize for some external images + - Move blueimp upload lib to composer and update to version 9.25 + - Remove primary/clone counts from admin summary until we have a mechanism to update the fixed counts + - Fix html2markdown() and re-enable previously failing tests + - Improve look of oembed content for Hubzilla links + - Fix forum notifications count not correct + - Fix gallery addon which broke mod apps in some situations + - Fix wiki_list widget not working on every page respectively level + + Hubzilla 3.8.2 (2018-10-29) - Merge unmerged changes from dev into master - Fix issues with forum handling in mod network and ping diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php index 6edced9b5..8ccdaf4f5 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -109,11 +109,9 @@ class Admin extends \Zotlabs\Web\Controller { // available channels, primary and clones $channels = array(); - $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0 and channel_system = 0"); + $r = q("SELECT COUNT(*) AS total FROM channel WHERE channel_removed = 0 and channel_system = 0"); if ($r) { $channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']); - $channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']); - $channels['clones'] = array('label' => t('Clones'), 'val' => $r[0]['clones']); } // We can do better, but this is a quick queue status diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php index a0ad17e68..7c7dc0e88 100644 --- a/Zotlabs/Module/Linkinfo.php +++ b/Zotlabs/Module/Linkinfo.php @@ -228,8 +228,13 @@ class Linkinfo extends \Zotlabs\Web\Controller { $header = $result['header']; $body = $result['body']; + + // Check codepage in HTTP headers or HTML if not exist + $cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : ''); + if(empty($cp)) + $cp = (preg_match('/meta.+content=["|\']text\/html; charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'AUTO'); - $body = mb_convert_encoding($body, 'UTF-8', (preg_match('/meta.+content=["|\']text\/html;\s+charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'UTF-8')); + $body = mb_convert_encoding($body, 'UTF-8', $cp); $body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8"); $doc = new \DOMDocument(); @@ -265,20 +270,43 @@ class Linkinfo extends \Zotlabs\Web\Controller { $attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"); switch (strtolower($attr["name"])) { - case 'generator': - $siteinfo['generator'] = $attr['content']; - break; case "fulltitle": - $siteinfo["title"] = $attr["content"]; + $siteinfo["title"] = trim($attr["content"]); break; case "description": - $siteinfo["text"] = $attr["content"]; + $siteinfo["text"] = trim($attr["content"]); + break; + case "thumbnail": + $siteinfo["image"] = $attr["content"]; + break; + case "twitter:image": + $siteinfo["image"] = $attr["content"]; + break; + case "twitter:image:src": + $siteinfo["image"] = $attr["content"]; + break; + case "twitter:card": + if (($siteinfo["type"] == "") || ($attr["content"] == "photo")) { + $siteinfo["type"] = $attr["content"]; + } + break; + case "twitter:description": + $siteinfo["text"] = trim($attr["content"]); + break; + case "twitter:title": + $siteinfo["title"] = trim($attr["content"]); break; case "dc.title": - $siteinfo["title"] = $attr["content"]; + $siteinfo["title"] = trim($attr["content"]); break; case "dc.description": - $siteinfo["text"] = $attr["content"]; + $siteinfo["text"] = trim($attr["content"]); + break; + case "keywords": + $keywords = explode(",", $attr["content"]); + break; + case "news_keywords": + $keywords = explode(",", $attr["content"]); break; } } diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 294e11c52..b93faa612 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -258,6 +258,10 @@ class Network extends \Zotlabs\Web\Controller { } elseif($pf && $unseen && $nouveau) { + $vnotify = get_pconfig(local_channel(), 'system', 'vnotify'); + if(! ($vnotify & VNOTIFY_LIKE)) + $likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; + // This is for nouveau view public forum cid queries (if a forum notification is clicked) $p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'", intval(local_channel()), @@ -269,7 +273,7 @@ class Network extends \Zotlabs\Web\Controller { if($p_str) $p_sql = " OR item.parent IN ( $p_str ) "; - $sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 "; + $sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 $likes_sql "; } else { // This is for threaded view cid queries (e.g. if a forum is selected from the forum filter) diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index f97f31ff7..78bfb1f09 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -612,9 +612,9 @@ class Photos extends \Zotlabs\Web\Controller { nav_set_selected('Photos'); - $o = ' - - '; + $o = ' + + '; $o .= " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/blueimp_upload/basic-plus.html b/library/blueimp_upload/basic-plus.html deleted file mode 100644 index acee24843..000000000 --- a/library/blueimp_upload/basic-plus.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - -jQuery File Upload Demo - Basic Plus version - - - - - - - - - - - -
-

jQuery File Upload Demo

-

Basic Plus version

- -
-
-

File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

-
-
- - - - Add files... - - - -
-
- -
-
-
- -
-
-
-
-

Demo Notes

-
-
-
    -
  • The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
  • -
  • Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
  • -
  • Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
  • -
  • You can drag & drop files from your desktop on this webpage (see Browser support).
  • -
  • Please refer to the project website and documentation for more information.
  • -
  • Built with the Bootstrap CSS framework and Icons from Glyphicons.
  • -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/blueimp_upload/basic.html b/library/blueimp_upload/basic.html deleted file mode 100644 index 232a24624..000000000 --- a/library/blueimp_upload/basic.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - -jQuery File Upload Demo - Basic version - - - - - - - - - - - -
-

jQuery File Upload Demo

-

Basic version

- -
-
-

File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
- Supports cross-domain, chunked and resumable file uploads.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

-
-
- - - - Select files... - - - -
-
- -
-
-
- -
-
-
-
-

Demo Notes

-
-
-
    -
  • The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
  • -
  • Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
  • -
  • Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
  • -
  • You can drag & drop files from your desktop on this webpage (see Browser support).
  • -
  • Please refer to the project website and documentation for more information.
  • -
  • Built with the Bootstrap CSS framework and Icons from Glyphicons.
  • -
-
-
-
- - - - - - - - - - - - diff --git a/library/blueimp_upload/bower-version-update.js b/library/blueimp_upload/bower-version-update.js deleted file mode 100755 index 09ce3927e..000000000 --- a/library/blueimp_upload/bower-version-update.js +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var path = require('path'); -var packageJSON = require(path.join(__dirname, 'package.json')); -var bowerFile = path.join(__dirname, 'bower.json'); -var bowerJSON = require('bower-json').parse( - require(bowerFile), - {normalize: true} -); -bowerJSON.version = packageJSON.version; -require('fs').writeFileSync( - bowerFile, - JSON.stringify(bowerJSON, null, 2) + '\n' -); diff --git a/library/blueimp_upload/bower.json b/library/blueimp_upload/bower.json deleted file mode 100644 index 4f4cd8adb..000000000 --- a/library/blueimp_upload/bower.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "blueimp-file-upload", - "version": "9.23.0", - "title": "jQuery File Upload", - "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images.", - "keywords": [ - "jquery", - "file", - "upload", - "widget", - "multiple", - "selection", - "drag", - "drop", - "progress", - "preview", - "cross-domain", - "cross-site", - "chunk", - "resume", - "gae", - "go", - "python", - "php", - "bootstrap" - ], - "homepage": "https://github.com/blueimp/jQuery-File-Upload", - "author": { - "name": "Sebastian Tschan", - "url": "https://blueimp.net" - }, - "maintainers": [ - { - "name": "Sebastian Tschan", - "url": "https://blueimp.net" - } - ], - "repository": { - "type": "git", - "url": "git://github.com/blueimp/jQuery-File-Upload.git" - }, - "bugs": "https://github.com/blueimp/jQuery-File-Upload/issues", - "license": "MIT", - "dependencies": { - "jquery": ">=1.6", - "blueimp-tmpl": ">=2.5.4", - "blueimp-load-image": ">=1.13.0", - "blueimp-canvas-to-blob": ">=2.1.1" - }, - "main": [ - "js/jquery.fileupload.js" - ], - "ignore": [ - "/*.*", - "/cors", - "css/jquery-ui-demo-ie8.css", - "css/jquery-ui-demo.css", - "css/style.css", - "js/app.js", - "js/main.js", - "server", - "test" - ] -} diff --git a/library/blueimp_upload/cors/postmessage.html b/library/blueimp_upload/cors/postmessage.html deleted file mode 100644 index 6a56cf0b6..000000000 --- a/library/blueimp_upload/cors/postmessage.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - -jQuery File Upload Plugin postMessage API - - - - - - diff --git a/library/blueimp_upload/cors/result.html b/library/blueimp_upload/cors/result.html deleted file mode 100644 index e3d629814..000000000 --- a/library/blueimp_upload/cors/result.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -jQuery Iframe Transport Plugin Redirect Page - - - - - diff --git a/library/blueimp_upload/css/jquery-ui-demo-ie8.css b/library/blueimp_upload/css/jquery-ui-demo-ie8.css deleted file mode 100644 index e0e8ea9b0..000000000 --- a/library/blueimp_upload/css/jquery-ui-demo-ie8.css +++ /dev/null @@ -1,21 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Demo CSS Fixes for IE<9 - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.navigation { - list-style: none; - padding: 0; - margin: 1em 0; -} -.navigation li { - display: inline; - margin-right: 10px; -} diff --git a/library/blueimp_upload/css/jquery-ui-demo.css b/library/blueimp_upload/css/jquery-ui-demo.css deleted file mode 100644 index d7d524df5..000000000 --- a/library/blueimp_upload/css/jquery-ui-demo.css +++ /dev/null @@ -1,67 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Demo CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -body { - max-width: 750px; - margin: 0 auto; - padding: 1em; - font-family: "Lucida Grande", "Lucida Sans Unicode", Arial, sans-serif; - font-size: 1em; - line-height: 1.4em; - background: #222; - color: #fff; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -a { - color: orange; - text-decoration: none; -} -img { - border: 0; - vertical-align: middle; -} -h1 { - line-height: 1em; -} -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eee; -} -table { - width: 100%; - margin: 10px 0; -} - -.fileupload-progress { - margin: 10px 0; -} -.fileupload-progress .progress-extended { - margin-top: 5px; -} -.error { - color: red; -} - -@media (min-width: 481px) { - .navigation { - list-style: none; - padding: 0; - } - .navigation li { - display: inline-block; - } - .navigation li:not(:first-child):before { - content: "| "; - } -} diff --git a/library/blueimp_upload/css/jquery.fileupload-noscript.css b/library/blueimp_upload/css/jquery.fileupload-noscript.css deleted file mode 100644 index 2409bfb0a..000000000 --- a/library/blueimp_upload/css/jquery.fileupload-noscript.css +++ /dev/null @@ -1,22 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Plugin NoScript CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileinput-button input { - position: static; - opacity: 1; - filter: none; - font-size: inherit !important; - direction: inherit; -} -.fileinput-button span { - display: none; -} diff --git a/library/blueimp_upload/css/jquery.fileupload-ui-noscript.css b/library/blueimp_upload/css/jquery.fileupload-ui-noscript.css deleted file mode 100644 index 30651acf0..000000000 --- a/library/blueimp_upload/css/jquery.fileupload-ui-noscript.css +++ /dev/null @@ -1,17 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload UI Plugin NoScript CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2012, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileinput-button i, -.fileupload-buttonbar .delete, -.fileupload-buttonbar .toggle { - display: none; -} diff --git a/library/blueimp_upload/css/jquery.fileupload-ui.css b/library/blueimp_upload/css/jquery.fileupload-ui.css deleted file mode 100644 index 9e36c42c5..000000000 --- a/library/blueimp_upload/css/jquery.fileupload-ui.css +++ /dev/null @@ -1,57 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload UI Plugin CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileupload-buttonbar .btn, -.fileupload-buttonbar .toggle { - margin-bottom: 5px; -} -.progress-animated .progress-bar, -.progress-animated .bar { - background: url("../img/progressbar.gif") !important; - filter: none; -} -.fileupload-process { - float: right; - display: none; -} -.fileupload-processing .fileupload-process, -.files .processing .preview { - display: block; - width: 32px; - height: 32px; - background: url("../img/loading.gif") center no-repeat; - background-size: contain; -} -.files audio, -.files video { - max-width: 300px; -} - -@media (max-width: 767px) { - .fileupload-buttonbar .toggle, - .files .toggle, - .files .btn span { - display: none; - } - .files .name { - width: 80px; - word-wrap: break-word; - } - .files audio, - .files video { - max-width: 80px; - } - .files img, - .files canvas { - max-width: 100%; - } -} diff --git a/library/blueimp_upload/css/jquery.fileupload.css b/library/blueimp_upload/css/jquery.fileupload.css deleted file mode 100644 index 8ae3b09d4..000000000 --- a/library/blueimp_upload/css/jquery.fileupload.css +++ /dev/null @@ -1,37 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Plugin CSS - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -.fileinput-button { - position: relative; - overflow: hidden; - display: inline-block; -} -.fileinput-button input { - position: absolute; - top: 0; - right: 0; - margin: 0; - opacity: 0; - -ms-filter: 'alpha(opacity=0)'; - font-size: 200px !important; - direction: ltr; - cursor: pointer; -} - -/* Fixes for IE < 8 */ -@media screen\9 { - .fileinput-button input { - filter: alpha(opacity=0); - font-size: 100%; - height: 100%; - } -} diff --git a/library/blueimp_upload/css/style.css b/library/blueimp_upload/css/style.css deleted file mode 100644 index 3aee25689..000000000 --- a/library/blueimp_upload/css/style.css +++ /dev/null @@ -1,15 +0,0 @@ -@charset "UTF-8"; -/* - * jQuery File Upload Plugin CSS Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -body { - padding-top: 60px; -} diff --git a/library/blueimp_upload/img/loading.gif b/library/blueimp_upload/img/loading.gif deleted file mode 100644 index 90f28cbdb..000000000 Binary files a/library/blueimp_upload/img/loading.gif and /dev/null differ diff --git a/library/blueimp_upload/img/progressbar.gif b/library/blueimp_upload/img/progressbar.gif deleted file mode 100644 index fbcce6bc9..000000000 Binary files a/library/blueimp_upload/img/progressbar.gif and /dev/null differ diff --git a/library/blueimp_upload/index.html b/library/blueimp_upload/index.html deleted file mode 100644 index c8c66ad8b..000000000 --- a/library/blueimp_upload/index.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - - -jQuery File Upload Demo - - - - - - - - - - - - - - - - - -
-

jQuery File Upload Demo

-

Basic Plus UI version

- -
-
-

File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

-
-
- -
- - - -
-
- - - - Add files... - - - - - - - - -
- -
- -
-
-
- -
 
-
-
- - -
-
-
-
-

Demo Notes

-
-
-
    -
  • The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
  • -
  • Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
  • -
  • Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
  • -
  • You can drag & drop files from your desktop on this webpage (see Browser support).
  • -
  • Please refer to the project website and documentation for more information.
  • -
  • Built with the Bootstrap CSS framework and Icons from Glyphicons.
  • -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/blueimp_upload/jquery-ui.html b/library/blueimp_upload/jquery-ui.html deleted file mode 100644 index 842dd4ca7..000000000 --- a/library/blueimp_upload/jquery-ui.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - -jQuery File Upload Demo - jQuery UI version - - - - - - - - - - - - - - - - - - - - - -

jQuery File Upload Demo

-

jQuery UI version

-
- - -
- -
-

File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery UI.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

-
- -
- - - -
-
- - - Add files... - - - - - - - - -
- - -
- -
-
-
-

Demo Notes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/blueimp_upload/js/app.js b/library/blueimp_upload/js/app.js deleted file mode 100644 index e6b7bce3e..000000000 --- a/library/blueimp_upload/js/app.js +++ /dev/null @@ -1,101 +0,0 @@ -/* - * jQuery File Upload Plugin Angular JS Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global window, angular */ - -;(function () { - 'use strict'; - - var isOnGitHub = window.location.hostname === 'blueimp.github.io', - url = isOnGitHub ? '//jquery-file-upload.appspot.com/' : 'server/php/'; - - angular.module('demo', [ - 'blueimp.fileupload' - ]) - .config([ - '$httpProvider', 'fileUploadProvider', - function ($httpProvider, fileUploadProvider) { - delete $httpProvider.defaults.headers.common['X-Requested-With']; - fileUploadProvider.defaults.redirect = window.location.href.replace( - /\/[^\/]*$/, - '/cors/result.html?%s' - ); - if (isOnGitHub) { - // Demo settings: - angular.extend(fileUploadProvider.defaults, { - // Enable image resizing, except for Android and Opera, - // which actually support image resizing, but fail to - // send Blob objects via XHR requests: - disableImageResize: /Android(?!.*Chrome)|Opera/ - .test(window.navigator.userAgent), - maxFileSize: 999000, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i - }); - } - } - ]) - - .controller('DemoFileUploadController', [ - '$scope', '$http', '$filter', '$window', - function ($scope, $http) { - $scope.options = { - url: url - }; - if (!isOnGitHub) { - $scope.loadingFiles = true; - $http.get(url) - .then( - function (response) { - $scope.loadingFiles = false; - $scope.queue = response.data.files || []; - }, - function () { - $scope.loadingFiles = false; - } - ); - } - } - ]) - - .controller('FileDestroyController', [ - '$scope', '$http', - function ($scope, $http) { - var file = $scope.file, - state; - if (file.url) { - file.$state = function () { - return state; - }; - file.$destroy = function () { - state = 'pending'; - return $http({ - url: file.deleteUrl, - method: file.deleteType - }).then( - function () { - state = 'resolved'; - $scope.clear(file); - }, - function () { - state = 'rejected'; - } - ); - }; - } else if (!file.$cancel && !file._index) { - file.$cancel = function () { - $scope.clear(file); - }; - } - } - ]); - -}()); diff --git a/library/blueimp_upload/js/cors/jquery.postmessage-transport.js b/library/blueimp_upload/js/cors/jquery.postmessage-transport.js deleted file mode 100644 index 2a0c38cb6..000000000 --- a/library/blueimp_upload/js/cors/jquery.postmessage-transport.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * jQuery postMessage Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global define, require, window, document */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - var counter = 0, - names = [ - 'accepts', - 'cache', - 'contents', - 'contentType', - 'crossDomain', - 'data', - 'dataType', - 'headers', - 'ifModified', - 'mimeType', - 'password', - 'processData', - 'timeout', - 'traditional', - 'type', - 'url', - 'username' - ], - convert = function (p) { - return p; - }; - - $.ajaxSetup({ - converters: { - 'postmessage text': convert, - 'postmessage json': convert, - 'postmessage html': convert - } - }); - - $.ajaxTransport('postmessage', function (options) { - if (options.postMessage && window.postMessage) { - var iframe, - loc = $('').prop('href', options.postMessage)[0], - target = loc.protocol + '//' + loc.host, - xhrUpload = options.xhr().upload; - // IE always includes the port for the host property of a link - // element, but not in the location.host or origin property for the - // default http port 80 and https port 443, so we strip it: - if (/^(http:\/\/.+:80)|(https:\/\/.+:443)$/.test(target)) { - target = target.replace(/:(80|443)$/, ''); - } - return { - send: function (_, completeCallback) { - counter += 1; - var message = { - id: 'postmessage-transport-' + counter - }, - eventName = 'message.' + message.id; - iframe = $( - '' - ).bind('load', function () { - $.each(names, function (i, name) { - message[name] = options[name]; - }); - message.dataType = message.dataType.replace('postmessage ', ''); - $(window).bind(eventName, function (e) { - e = e.originalEvent; - var data = e.data, - ev; - if (e.origin === target && data.id === message.id) { - if (data.type === 'progress') { - ev = document.createEvent('Event'); - ev.initEvent(data.type, false, true); - $.extend(ev, data); - xhrUpload.dispatchEvent(ev); - } else { - completeCallback( - data.status, - data.statusText, - {postmessage: data.result}, - data.headers - ); - iframe.remove(); - $(window).unbind(eventName); - } - } - }); - iframe[0].contentWindow.postMessage( - message, - target - ); - }).appendTo(document.body); - }, - abort: function () { - if (iframe) { - iframe.remove(); - } - } - }; - } - }); - -})); diff --git a/library/blueimp_upload/js/cors/jquery.xdr-transport.js b/library/blueimp_upload/js/cors/jquery.xdr-transport.js deleted file mode 100644 index a4e2699c6..000000000 --- a/library/blueimp_upload/js/cors/jquery.xdr-transport.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * jQuery XDomainRequest Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - * - * Based on Julian Aubourg's ajaxHooks xdr.js: - * https://github.com/jaubourg/ajaxHooks/ - */ - -/* global define, require, window, XDomainRequest */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - if (window.XDomainRequest && !$.support.cors) { - $.ajaxTransport(function (s) { - if (s.crossDomain && s.async) { - if (s.timeout) { - s.xdrTimeout = s.timeout; - delete s.timeout; - } - var xdr; - return { - send: function (headers, completeCallback) { - var addParamChar = /\?/.test(s.url) ? '&' : '?'; - function callback(status, statusText, responses, responseHeaders) { - xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; - xdr = null; - completeCallback(status, statusText, responses, responseHeaders); - } - xdr = new XDomainRequest(); - // XDomainRequest only supports GET and POST: - if (s.type === 'DELETE') { - s.url = s.url + addParamChar + '_method=DELETE'; - s.type = 'POST'; - } else if (s.type === 'PUT') { - s.url = s.url + addParamChar + '_method=PUT'; - s.type = 'POST'; - } else if (s.type === 'PATCH') { - s.url = s.url + addParamChar + '_method=PATCH'; - s.type = 'POST'; - } - xdr.open(s.type, s.url); - xdr.onload = function () { - callback( - 200, - 'OK', - {text: xdr.responseText}, - 'Content-Type: ' + xdr.contentType - ); - }; - xdr.onerror = function () { - callback(404, 'Not Found'); - }; - if (s.xdrTimeout) { - xdr.ontimeout = function () { - callback(0, 'timeout'); - }; - xdr.timeout = s.xdrTimeout; - } - xdr.send((s.hasContent && s.data) || null); - }, - abort: function () { - if (xdr) { - xdr.onerror = $.noop(); - xdr.abort(); - } - } - }; - } - }); - } -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-angular.js b/library/blueimp_upload/js/jquery.fileupload-angular.js deleted file mode 100644 index 185907d36..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-angular.js +++ /dev/null @@ -1,438 +0,0 @@ -/* - * jQuery File Upload AngularJS Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, angular, require */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'angular', - './jquery.fileupload-image', - './jquery.fileupload-audio', - './jquery.fileupload-video', - './jquery.fileupload-validate' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('angular'), - require('./jquery.fileupload-image'), - require('./jquery.fileupload-audio'), - require('./jquery.fileupload-video'), - require('./jquery.fileupload-validate') - ); - } else { - factory(); - } -}(function () { - 'use strict'; - - angular.module('blueimp.fileupload', []) - - // The fileUpload service provides configuration options - // for the fileUpload directive and default handlers for - // File Upload events: - .provider('fileUpload', function () { - var scopeEvalAsync = function (expression) { - var scope = angular.element(this) - .fileupload('option', 'scope'); - // Schedule a new $digest cycle if not already inside of one - // and evaluate the given expression: - scope.$evalAsync(expression); - }, - addFileMethods = function (scope, data) { - var files = data.files, - file = files[0]; - angular.forEach(files, function (file, index) { - file._index = index; - file.$state = function () { - return data.state(); - }; - file.$processing = function () { - return data.processing(); - }; - file.$progress = function () { - return data.progress(); - }; - file.$response = function () { - return data.response(); - }; - }); - file.$submit = function () { - if (!file.error) { - return data.submit(); - } - }; - file.$cancel = function () { - return data.abort(); - }; - }, - $config; - $config = this.defaults = { - handleResponse: function (e, data) { - var files = data.result && data.result.files; - if (files) { - data.scope.replace(data.files, files); - } else if (data.errorThrown || - data.textStatus === 'error') { - data.files[0].error = data.errorThrown || - data.textStatus; - } - }, - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var scope = data.scope, - filesCopy = []; - angular.forEach(data.files, function (file) { - filesCopy.push(file); - }); - scope.$parent.$applyAsync(function () { - addFileMethods(scope, data); - var method = scope.option('prependFiles') ? - 'unshift' : 'push'; - Array.prototype[method].apply(scope.queue, data.files); - }); - data.process(function () { - return scope.process(data); - }).always(function () { - scope.$parent.$applyAsync(function () { - addFileMethods(scope, data); - scope.replace(filesCopy, data.files); - }); - }).then(function () { - if ((scope.option('autoUpload') || - data.autoUpload) && - data.autoUpload !== false) { - data.submit(); - } - }); - }, - done: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = this; - data.scope.$apply(function () { - data.handleResponse.call(that, e, data); - }); - }, - fail: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = this, - scope = data.scope; - if (data.errorThrown === 'abort') { - scope.clear(data.files); - return; - } - scope.$apply(function () { - data.handleResponse.call(that, e, data); - }); - }, - stop: scopeEvalAsync, - processstart: scopeEvalAsync, - processstop: scopeEvalAsync, - getNumberOfFiles: function () { - var scope = this.scope; - return scope.queue.length - scope.processing(); - }, - dataType: 'json', - autoUpload: false - }; - this.$get = [ - function () { - return { - defaults: $config - }; - } - ]; - }) - - // Format byte numbers to readable presentations: - .provider('formatFileSizeFilter', function () { - var $config = { - // Byte units following the IEC format - // http://en.wikipedia.org/wiki/Kilobyte - units: [ - {size: 1000000000, suffix: ' GB'}, - {size: 1000000, suffix: ' MB'}, - {size: 1000, suffix: ' KB'} - ] - }; - this.defaults = $config; - this.$get = function () { - return function (bytes) { - if (!angular.isNumber(bytes)) { - return ''; - } - var unit = true, - i = 0, - prefix, - suffix; - while (unit) { - unit = $config.units[i]; - prefix = unit.prefix || ''; - suffix = unit.suffix || ''; - if (i === $config.units.length - 1 || bytes >= unit.size) { - return prefix + (bytes / unit.size).toFixed(2) + suffix; - } - i += 1; - } - }; - }; - }) - - // The FileUploadController initializes the fileupload widget and - // provides scope methods to control the File Upload functionality: - .controller('FileUploadController', [ - '$scope', '$element', '$attrs', '$window', 'fileUpload','$q', - function ($scope, $element, $attrs, $window, fileUpload, $q) { - var uploadMethods = { - progress: function () { - return $element.fileupload('progress'); - }, - active: function () { - return $element.fileupload('active'); - }, - option: function (option, data) { - if (arguments.length === 1) { - return $element.fileupload('option', option); - } - $element.fileupload('option', option, data); - }, - add: function (data) { - return $element.fileupload('add', data); - }, - send: function (data) { - return $element.fileupload('send', data); - }, - process: function (data) { - return $element.fileupload('process', data); - }, - processing: function (data) { - return $element.fileupload('processing', data); - } - }; - $scope.disabled = !$window.jQuery.support.fileInput; - $scope.queue = $scope.queue || []; - $scope.clear = function (files) { - var queue = this.queue, - i = queue.length, - file = files, - length = 1; - if (angular.isArray(files)) { - file = files[0]; - length = files.length; - } - while (i) { - i -= 1; - if (queue[i] === file) { - return queue.splice(i, length); - } - } - }; - $scope.replace = function (oldFiles, newFiles) { - var queue = this.queue, - file = oldFiles[0], - i, - j; - for (i = 0; i < queue.length; i += 1) { - if (queue[i] === file) { - for (j = 0; j < newFiles.length; j += 1) { - queue[i + j] = newFiles[j]; - } - return; - } - } - }; - $scope.applyOnQueue = function (method) { - var list = this.queue.slice(0), - i, - file, - promises = []; - for (i = 0; i < list.length; i += 1) { - file = list[i]; - if (file[method]) { - promises.push(file[method]()); - } - } - return $q.all(promises); - }; - $scope.submit = function () { - return this.applyOnQueue('$submit'); - }; - $scope.cancel = function () { - return this.applyOnQueue('$cancel'); - }; - // Add upload methods to the scope: - angular.extend($scope, uploadMethods); - // The fileupload widget will initialize with - // the options provided via "data-"-parameters, - // as well as those given via options object: - $element.fileupload(angular.extend( - {scope: $scope}, - fileUpload.defaults - )).on('fileuploadadd', function (e, data) { - data.scope = $scope; - }).on('fileuploadfail', function (e, data) { - if (data.errorThrown === 'abort') { - return; - } - if (data.dataType && - data.dataType.indexOf('json') === data.dataType.length - 4) { - try { - data.result = angular.fromJson(data.jqXHR.responseText); - } catch (ignore) {} - } - }).on([ - 'fileuploadadd', - 'fileuploadsubmit', - 'fileuploadsend', - 'fileuploaddone', - 'fileuploadfail', - 'fileuploadalways', - 'fileuploadprogress', - 'fileuploadprogressall', - 'fileuploadstart', - 'fileuploadstop', - 'fileuploadchange', - 'fileuploadpaste', - 'fileuploaddrop', - 'fileuploaddragover', - 'fileuploadchunkbeforesend', - 'fileuploadchunksend', - 'fileuploadchunkdone', - 'fileuploadchunkfail', - 'fileuploadchunkalways', - 'fileuploadprocessstart', - 'fileuploadprocess', - 'fileuploadprocessdone', - 'fileuploadprocessfail', - 'fileuploadprocessalways', - 'fileuploadprocessstop' - ].join(' '), function (e, data) { - $scope.$parent.$applyAsync(function () { - if ($scope.$emit(e.type, data).defaultPrevented) { - e.preventDefault(); - } - }); - }).on('remove', function () { - // Remove upload methods from the scope, - // when the widget is removed: - var method; - for (method in uploadMethods) { - if (uploadMethods.hasOwnProperty(method)) { - delete $scope[method]; - } - } - }); - // Observe option changes: - $scope.$watch( - $attrs.fileUpload, - function (newOptions) { - if (newOptions) { - $element.fileupload('option', newOptions); - } - } - ); - } - ]) - - // Provide File Upload progress feedback: - .controller('FileUploadProgressController', [ - '$scope', '$attrs', '$parse', - function ($scope, $attrs, $parse) { - var fn = $parse($attrs.fileUploadProgress), - update = function () { - var progress = fn($scope); - if (!progress || !progress.total) { - return; - } - $scope.num = Math.floor( - progress.loaded / progress.total * 100 - ); - }; - update(); - $scope.$watch( - $attrs.fileUploadProgress + '.loaded', - function (newValue, oldValue) { - if (newValue !== oldValue) { - update(); - } - } - ); - } - ]) - - // Display File Upload previews: - .controller('FileUploadPreviewController', [ - '$scope', '$element', '$attrs', - function ($scope, $element, $attrs) { - $scope.$watch( - $attrs.fileUploadPreview + '.preview', - function (preview) { - $element.empty(); - if (preview) { - $element.append(preview); - } - } - ); - } - ]) - - .directive('fileUpload', function () { - return { - controller: 'FileUploadController', - scope: true - }; - }) - - .directive('fileUploadProgress', function () { - return { - controller: 'FileUploadProgressController', - scope: true - }; - }) - - .directive('fileUploadPreview', function () { - return { - controller: 'FileUploadPreviewController' - }; - }) - - // Enhance the HTML5 download attribute to - // allow drag&drop of files to the desktop: - .directive('download', function () { - return function (scope, elm) { - elm.on('dragstart', function (e) { - try { - e.originalEvent.dataTransfer.setData( - 'DownloadURL', - [ - 'application/octet-stream', - elm.prop('download'), - elm.prop('href') - ].join(':') - ); - } catch (ignore) {} - }); - }; - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-audio.js b/library/blueimp_upload/js/jquery.fileupload-audio.js deleted file mode 100644 index a25377619..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-audio.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * jQuery File Upload Audio Preview Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'load-image', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-load-image/js/load-image'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.loadImage - ); - } -}(function ($, loadImage) { - 'use strict'; - - // Prepend to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.unshift( - { - action: 'loadAudio', - // Use the action as prefix for the "@" options: - prefix: true, - fileTypes: '@', - maxFileSize: '@', - disabled: '@disableAudioPreview' - }, - { - action: 'setAudio', - name: '@audioPreviewName', - disabled: '@disableAudioPreview' - } - ); - - // The File Upload Audio Preview plugin extends the fileupload widget - // with audio preview functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of audio files to load, - // matched against the file type: - loadAudioFileTypes: /^audio\/.*$/ - }, - - _audioElement: document.createElement('audio'), - - processActions: { - - // Loads the audio file given via data.files and data.index - // as audio element if the browser supports playing it. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadAudio: function (data, options) { - if (options.disabled) { - return data; - } - var file = data.files[data.index], - url, - audio; - if (this._audioElement.canPlayType && - this._audioElement.canPlayType(file.type) && - ($.type(options.maxFileSize) !== 'number' || - file.size <= options.maxFileSize) && - (!options.fileTypes || - options.fileTypes.test(file.type))) { - url = loadImage.createObjectURL(file); - if (url) { - audio = this._audioElement.cloneNode(false); - audio.src = url; - audio.controls = true; - data.audio = audio; - return data; - } - } - return data; - }, - - // Sets the audio element as a property of the file object: - setAudio: function (data, options) { - if (data.audio && !options.disabled) { - data.files[data.index][options.name || 'preview'] = data.audio; - } - return data; - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-image.js b/library/blueimp_upload/js/jquery.fileupload-image.js deleted file mode 100644 index 65fc6d7b8..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-image.js +++ /dev/null @@ -1,326 +0,0 @@ -/* - * jQuery File Upload Image Preview & Resize Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, Blob */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'load-image', - 'load-image-meta', - 'load-image-scale', - 'load-image-exif', - 'canvas-to-blob', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-load-image/js/load-image'), - require('blueimp-load-image/js/load-image-meta'), - require('blueimp-load-image/js/load-image-scale'), - require('blueimp-load-image/js/load-image-exif'), - require('blueimp-canvas-to-blob'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.loadImage - ); - } -}(function ($, loadImage) { - 'use strict'; - - // Prepend to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.unshift( - { - action: 'loadImageMetaData', - disableImageHead: '@', - disableExif: '@', - disableExifThumbnail: '@', - disableExifSub: '@', - disableExifGps: '@', - disabled: '@disableImageMetaDataLoad' - }, - { - action: 'loadImage', - // Use the action as prefix for the "@" options: - prefix: true, - fileTypes: '@', - maxFileSize: '@', - noRevoke: '@', - disabled: '@disableImageLoad' - }, - { - action: 'resizeImage', - // Use "image" as prefix for the "@" options: - prefix: 'image', - maxWidth: '@', - maxHeight: '@', - minWidth: '@', - minHeight: '@', - crop: '@', - orientation: '@', - forceResize: '@', - disabled: '@disableImageResize' - }, - { - action: 'saveImage', - quality: '@imageQuality', - type: '@imageType', - disabled: '@disableImageResize' - }, - { - action: 'saveImageMetaData', - disabled: '@disableImageMetaDataSave' - }, - { - action: 'resizeImage', - // Use "preview" as prefix for the "@" options: - prefix: 'preview', - maxWidth: '@', - maxHeight: '@', - minWidth: '@', - minHeight: '@', - crop: '@', - orientation: '@', - thumbnail: '@', - canvas: '@', - disabled: '@disableImagePreview' - }, - { - action: 'setImage', - name: '@imagePreviewName', - disabled: '@disableImagePreview' - }, - { - action: 'deleteImageReferences', - disabled: '@disableImageReferencesDeletion' - } - ); - - // The File Upload Resize plugin extends the fileupload widget - // with image resize functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of images to load: - // matched against the file type: - loadImageFileTypes: /^image\/(gif|jpeg|png|svg\+xml)$/, - // The maximum file size of images to load: - loadImageMaxFileSize: 10000000, // 10MB - // The maximum width of resized images: - imageMaxWidth: 1920, - // The maximum height of resized images: - imageMaxHeight: 1080, - // Defines the image orientation (1-8) or takes the orientation - // value from Exif data if set to true: - imageOrientation: false, - // Define if resized images should be cropped or only scaled: - imageCrop: false, - // Disable the resize image functionality by default: - disableImageResize: true, - // The maximum width of the preview images: - previewMaxWidth: 80, - // The maximum height of the preview images: - previewMaxHeight: 80, - // Defines the preview orientation (1-8) or takes the orientation - // value from Exif data if set to true: - previewOrientation: true, - // Create the preview using the Exif data thumbnail: - previewThumbnail: true, - // Define if preview images should be cropped or only scaled: - previewCrop: false, - // Define if preview images should be resized as canvas elements: - previewCanvas: true - }, - - processActions: { - - // Loads the image given via data.files and data.index - // as img element, if the browser supports the File API. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadImage: function (data, options) { - if (options.disabled) { - return data; - } - var that = this, - file = data.files[data.index], - dfd = $.Deferred(); - if (($.type(options.maxFileSize) === 'number' && - file.size > options.maxFileSize) || - (options.fileTypes && - !options.fileTypes.test(file.type)) || - !loadImage( - file, - function (img) { - if (img.src) { - data.img = img; - } - dfd.resolveWith(that, [data]); - }, - options - )) { - return data; - } - return dfd.promise(); - }, - - // Resizes the image given as data.canvas or data.img - // and updates data.canvas or data.img with the resized image. - // Also stores the resized image as preview property. - // Accepts the options maxWidth, maxHeight, minWidth, - // minHeight, canvas and crop: - resizeImage: function (data, options) { - if (options.disabled || !(data.canvas || data.img)) { - return data; - } - options = $.extend({canvas: true}, options); - var that = this, - dfd = $.Deferred(), - img = (options.canvas && data.canvas) || data.img, - resolve = function (newImg) { - if (newImg && (newImg.width !== img.width || - newImg.height !== img.height || - options.forceResize)) { - data[newImg.getContext ? 'canvas' : 'img'] = newImg; - } - data.preview = newImg; - dfd.resolveWith(that, [data]); - }, - thumbnail; - if (data.exif) { - if (options.orientation === true) { - options.orientation = data.exif.get('Orientation'); - } - if (options.thumbnail) { - thumbnail = data.exif.get('Thumbnail'); - if (thumbnail) { - loadImage(thumbnail, resolve, options); - return dfd.promise(); - } - } - // Prevent orienting the same image twice: - if (data.orientation) { - delete options.orientation; - } else { - data.orientation = options.orientation; - } - } - if (img) { - resolve(loadImage.scale(img, options)); - return dfd.promise(); - } - return data; - }, - - // Saves the processed image given as data.canvas - // inplace at data.index of data.files: - saveImage: function (data, options) { - if (!data.canvas || options.disabled) { - return data; - } - var that = this, - file = data.files[data.index], - dfd = $.Deferred(); - if (data.canvas.toBlob) { - data.canvas.toBlob( - function (blob) { - if (!blob.name) { - if (file.type === blob.type) { - blob.name = file.name; - } else if (file.name) { - blob.name = file.name.replace( - /\.\w+$/, - '.' + blob.type.substr(6) - ); - } - } - // Don't restore invalid meta data: - if (file.type !== blob.type) { - delete data.imageHead; - } - // Store the created blob at the position - // of the original file in the files list: - data.files[data.index] = blob; - dfd.resolveWith(that, [data]); - }, - options.type || file.type, - options.quality - ); - } else { - return data; - } - return dfd.promise(); - }, - - loadImageMetaData: function (data, options) { - if (options.disabled) { - return data; - } - var that = this, - dfd = $.Deferred(); - loadImage.parseMetaData(data.files[data.index], function (result) { - $.extend(data, result); - dfd.resolveWith(that, [data]); - }, options); - return dfd.promise(); - }, - - saveImageMetaData: function (data, options) { - if (!(data.imageHead && data.canvas && - data.canvas.toBlob && !options.disabled)) { - return data; - } - var file = data.files[data.index], - blob = new Blob([ - data.imageHead, - // Resized images always have a head size of 20 bytes, - // including the JPEG marker and a minimal JFIF header: - this._blobSlice.call(file, 20) - ], {type: file.type}); - blob.name = file.name; - data.files[data.index] = blob; - return data; - }, - - // Sets the resized version of the image as a property of the - // file object, must be called after "saveImage": - setImage: function (data, options) { - if (data.preview && !options.disabled) { - data.files[data.index][options.name || 'preview'] = data.preview; - } - return data; - }, - - deleteImageReferences: function (data, options) { - if (!options.disabled) { - delete data.img; - delete data.canvas; - delete data.preview; - delete data.imageHead; - } - return data; - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-jquery-ui.js b/library/blueimp_upload/js/jquery.fileupload-jquery-ui.js deleted file mode 100644 index 7b136b379..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-jquery-ui.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - * jQuery File Upload jQuery UI Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - './jquery.fileupload-ui' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./jquery.fileupload-ui') - ); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - processdone: function (e, data) { - data.context.find('.start').button('enable'); - }, - progress: function (e, data) { - if (data.context) { - data.context.find('.progress').progressbar( - 'option', - 'value', - parseInt(data.loaded / data.total * 100, 10) - ); - } - }, - progressall: function (e, data) { - var $this = $(this); - $this.find('.fileupload-progress') - .find('.progress').progressbar( - 'option', - 'value', - parseInt(data.loaded / data.total * 100, 10) - ).end() - .find('.progress-extended').each(function () { - $(this).html( - ($this.data('blueimp-fileupload') || - $this.data('fileupload')) - ._renderExtendedProgress(data) - ); - }); - } - }, - - _renderUpload: function (func, files) { - var node = this._super(func, files), - showIconText = $(window).width() > 480; - node.find('.progress').empty().progressbar(); - node.find('.start').button({ - icons: {primary: 'ui-icon-circle-arrow-e'}, - text: showIconText - }); - node.find('.cancel').button({ - icons: {primary: 'ui-icon-cancel'}, - text: showIconText - }); - if (node.hasClass('fade')) { - node.hide(); - } - return node; - }, - - _renderDownload: function (func, files) { - var node = this._super(func, files), - showIconText = $(window).width() > 480; - node.find('.delete').button({ - icons: {primary: 'ui-icon-trash'}, - text: showIconText - }); - if (node.hasClass('fade')) { - node.hide(); - } - return node; - }, - - _startHandler: function (e) { - $(e.currentTarget).button('disable'); - this._super(e); - }, - - _transition: function (node) { - var deferred = $.Deferred(); - if (node.hasClass('fade')) { - node.fadeToggle( - this.options.transitionDuration, - this.options.transitionEasing, - function () { - deferred.resolveWith(node); - } - ); - } else { - deferred.resolveWith(node); - } - return deferred; - }, - - _create: function () { - this._super(); - this.element - .find('.fileupload-buttonbar') - .find('.fileinput-button').each(function () { - var input = $(this).find('input:file').detach(); - $(this) - .button({icons: {primary: 'ui-icon-plusthick'}}) - .append(input); - }) - .end().find('.start') - .button({icons: {primary: 'ui-icon-circle-arrow-e'}}) - .end().find('.cancel') - .button({icons: {primary: 'ui-icon-cancel'}}) - .end().find('.delete') - .button({icons: {primary: 'ui-icon-trash'}}) - .end().find('.progress').progressbar(); - }, - - _destroy: function () { - this.element - .find('.fileupload-buttonbar') - .find('.fileinput-button').each(function () { - var input = $(this).find('input:file').detach(); - $(this) - .button('destroy') - .append(input); - }) - .end().find('.start') - .button('destroy') - .end().find('.cancel') - .button('destroy') - .end().find('.delete') - .button('destroy') - .end().find('.progress').progressbar('destroy'); - this._super(); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-process.js b/library/blueimp_upload/js/jquery.fileupload-process.js deleted file mode 100644 index 638f0d26b..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-process.js +++ /dev/null @@ -1,178 +0,0 @@ -/* - * jQuery File Upload Processing Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2012, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - './jquery.fileupload' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./jquery.fileupload') - ); - } else { - // Browser globals: - factory( - window.jQuery - ); - } -}(function ($) { - 'use strict'; - - var originalAdd = $.blueimp.fileupload.prototype.options.add; - - // The File Upload Processing plugin extends the fileupload widget - // with file processing functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The list of processing actions: - processQueue: [ - /* - { - action: 'log', - type: 'debug' - } - */ - ], - add: function (e, data) { - var $this = $(this); - data.process(function () { - return $this.fileupload('process', data); - }); - originalAdd.call(this, e, data); - } - }, - - processActions: { - /* - log: function (data, options) { - console[options.type]( - 'Processing "' + data.files[data.index].name + '"' - ); - } - */ - }, - - _processFile: function (data, originalData) { - var that = this, - dfd = $.Deferred().resolveWith(that, [data]), - chain = dfd.promise(); - this._trigger('process', null, data); - $.each(data.processQueue, function (i, settings) { - var func = function (data) { - if (originalData.errorThrown) { - return $.Deferred() - .rejectWith(that, [originalData]).promise(); - } - return that.processActions[settings.action].call( - that, - data, - settings - ); - }; - chain = chain.then(func, settings.always && func); - }); - chain - .done(function () { - that._trigger('processdone', null, data); - that._trigger('processalways', null, data); - }) - .fail(function () { - that._trigger('processfail', null, data); - that._trigger('processalways', null, data); - }); - return chain; - }, - - // Replaces the settings of each processQueue item that - // are strings starting with an "@", using the remaining - // substring as key for the option map, - // e.g. "@autoUpload" is replaced with options.autoUpload: - _transformProcessQueue: function (options) { - var processQueue = []; - $.each(options.processQueue, function () { - var settings = {}, - action = this.action, - prefix = this.prefix === true ? action : this.prefix; - $.each(this, function (key, value) { - if ($.type(value) === 'string' && - value.charAt(0) === '@') { - settings[key] = options[ - value.slice(1) || (prefix ? prefix + - key.charAt(0).toUpperCase() + key.slice(1) : key) - ]; - } else { - settings[key] = value; - } - - }); - processQueue.push(settings); - }); - options.processQueue = processQueue; - }, - - // Returns the number of files currently in the processsing queue: - processing: function () { - return this._processing; - }, - - // Processes the files given as files property of the data parameter, - // returns a Promise object that allows to bind callbacks: - process: function (data) { - var that = this, - options = $.extend({}, this.options, data); - if (options.processQueue && options.processQueue.length) { - this._transformProcessQueue(options); - if (this._processing === 0) { - this._trigger('processstart'); - } - $.each(data.files, function (index) { - var opts = index ? $.extend({}, options) : options, - func = function () { - if (data.errorThrown) { - return $.Deferred() - .rejectWith(that, [data]).promise(); - } - return that._processFile(opts, data); - }; - opts.index = index; - that._processing += 1; - that._processingQueue = that._processingQueue.then(func, func) - .always(function () { - that._processing -= 1; - if (that._processing === 0) { - that._trigger('processstop'); - } - }); - }); - } - return this._processingQueue; - }, - - _create: function () { - this._super(); - this._processing = 0; - this._processingQueue = $.Deferred().resolveWith(this) - .promise(); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-ui.js b/library/blueimp_upload/js/jquery.fileupload-ui.js deleted file mode 100644 index 5058084b4..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-ui.js +++ /dev/null @@ -1,714 +0,0 @@ -/* - * jQuery File Upload User Interface Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'blueimp-tmpl', - './jquery.fileupload-image', - './jquery.fileupload-audio', - './jquery.fileupload-video', - './jquery.fileupload-validate' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-tmpl'), - require('./jquery.fileupload-image'), - require('./jquery.fileupload-audio'), - require('./jquery.fileupload-video'), - require('./jquery.fileupload-validate') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.tmpl - ); - } -}(function ($, tmpl) { - 'use strict'; - - $.blueimp.fileupload.prototype._specialOptions.push( - 'filesContainer', - 'uploadTemplateId', - 'downloadTemplateId' - ); - - // The UI version extends the file upload widget - // and adds complete user interface interaction: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // By default, files added to the widget are uploaded as soon - // as the user clicks on the start buttons. To enable automatic - // uploads, set the following option to true: - autoUpload: false, - // The ID of the upload template: - uploadTemplateId: 'template-upload', - // The ID of the download template: - downloadTemplateId: 'template-download', - // The container for the list of files. If undefined, it is set to - // an element with class "files" inside of the widget element: - filesContainer: undefined, - // By default, files are appended to the files container. - // Set the following option to true, to prepend files instead: - prependFiles: false, - // The expected data type of the upload response, sets the dataType - // option of the $.ajax upload requests: - dataType: 'json', - - // Error and info messages: - messages: { - unknownError: 'Unknown error' - }, - - // Function returning the current number of files, - // used by the maxNumberOfFiles validation: - getNumberOfFiles: function () { - return this.filesContainer.children() - .not('.processing').length; - }, - - // Callback to retrieve the list of files from the server response: - getFilesFromResponse: function (data) { - if (data.result && $.isArray(data.result.files)) { - return data.result.files; - } - return []; - }, - - // The add callback is invoked as soon as files are added to the fileupload - // widget (via file input selection, drag & drop or add API call). - // See the basic file upload widget for more information: - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var $this = $(this), - that = $this.data('blueimp-fileupload') || - $this.data('fileupload'), - options = that.options; - data.context = that._renderUpload(data.files) - .data('data', data) - .addClass('processing'); - options.filesContainer[ - options.prependFiles ? 'prepend' : 'append' - ](data.context); - that._forceReflow(data.context); - that._transition(data.context); - data.process(function () { - return $this.fileupload('process', data); - }).always(function () { - data.context.each(function (index) { - $(this).find('.size').text( - that._formatFileSize(data.files[index].size) - ); - }).removeClass('processing'); - that._renderPreviews(data); - }).done(function () { - data.context.find('.start').prop('disabled', false); - if ((that._trigger('added', e, data) !== false) && - (options.autoUpload || data.autoUpload) && - data.autoUpload !== false) { - data.submit(); - } - }).fail(function () { - if (data.files.error) { - data.context.each(function (index) { - var error = data.files[index].error; - if (error) { - $(this).find('.error').text(error); - } - }); - } - }); - }, - // Callback for the start of each file upload request: - send: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'); - if (data.context && data.dataType && - data.dataType.substr(0, 6) === 'iframe') { - // Iframe Transport does not support progress events. - // In lack of an indeterminate progress bar, we set - // the progress to 100%, showing the full animated bar: - data.context - .find('.progress').addClass( - !$.support.transition && 'progress-animated' - ) - .attr('aria-valuenow', 100) - .children().first().css( - 'width', - '100%' - ); - } - return that._trigger('sent', e, data); - }, - // Callback for successful uploads: - done: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - getFilesFromResponse = data.getFilesFromResponse || - that.options.getFilesFromResponse, - files = getFilesFromResponse(data), - template, - deferred; - if (data.context) { - data.context.each(function (index) { - var file = files[index] || - {error: 'Empty file upload result'}; - deferred = that._addFinishedDeferreds(); - that._transition($(this)).done( - function () { - var node = $(this); - template = that._renderDownload([file]) - .replaceAll(node); - that._forceReflow(template); - that._transition(template).done( - function () { - data.context = $(this); - that._trigger('completed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - ); - }); - } else { - template = that._renderDownload(files)[ - that.options.prependFiles ? 'prependTo' : 'appendTo' - ](that.options.filesContainer); - that._forceReflow(template); - deferred = that._addFinishedDeferreds(); - that._transition(template).done( - function () { - data.context = $(this); - that._trigger('completed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - }, - // Callback for failed (abort or error) uploads: - fail: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - template, - deferred; - if (data.context) { - data.context.each(function (index) { - if (data.errorThrown !== 'abort') { - var file = data.files[index]; - file.error = file.error || data.errorThrown || - data.i18n('unknownError'); - deferred = that._addFinishedDeferreds(); - that._transition($(this)).done( - function () { - var node = $(this); - template = that._renderDownload([file]) - .replaceAll(node); - that._forceReflow(template); - that._transition(template).done( - function () { - data.context = $(this); - that._trigger('failed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - ); - } else { - deferred = that._addFinishedDeferreds(); - that._transition($(this)).done( - function () { - $(this).remove(); - that._trigger('failed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } - }); - } else if (data.errorThrown !== 'abort') { - data.context = that._renderUpload(data.files)[ - that.options.prependFiles ? 'prependTo' : 'appendTo' - ](that.options.filesContainer) - .data('data', data); - that._forceReflow(data.context); - deferred = that._addFinishedDeferreds(); - that._transition(data.context).done( - function () { - data.context = $(this); - that._trigger('failed', e, data); - that._trigger('finished', e, data); - deferred.resolve(); - } - ); - } else { - that._trigger('failed', e, data); - that._trigger('finished', e, data); - that._addFinishedDeferreds().resolve(); - } - }, - // Callback for upload progress events: - progress: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var progress = Math.floor(data.loaded / data.total * 100); - if (data.context) { - data.context.each(function () { - $(this).find('.progress') - .attr('aria-valuenow', progress) - .children().first().css( - 'width', - progress + '%' - ); - }); - } - }, - // Callback for global upload progress events: - progressall: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var $this = $(this), - progress = Math.floor(data.loaded / data.total * 100), - globalProgressNode = $this.find('.fileupload-progress'), - extendedProgressNode = globalProgressNode - .find('.progress-extended'); - if (extendedProgressNode.length) { - extendedProgressNode.html( - ($this.data('blueimp-fileupload') || $this.data('fileupload')) - ._renderExtendedProgress(data) - ); - } - globalProgressNode - .find('.progress') - .attr('aria-valuenow', progress) - .children().first().css( - 'width', - progress + '%' - ); - }, - // Callback for uploads start, equivalent to the global ajaxStart event: - start: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'); - that._resetFinishedDeferreds(); - that._transition($(this).find('.fileupload-progress')).done( - function () { - that._trigger('started', e); - } - ); - }, - // Callback for uploads stop, equivalent to the global ajaxStop event: - stop: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - deferred = that._addFinishedDeferreds(); - $.when.apply($, that._getFinishedDeferreds()) - .done(function () { - that._trigger('stopped', e); - }); - that._transition($(this).find('.fileupload-progress')).done( - function () { - $(this).find('.progress') - .attr('aria-valuenow', '0') - .children().first().css('width', '0%'); - $(this).find('.progress-extended').html(' '); - deferred.resolve(); - } - ); - }, - processstart: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - $(this).addClass('fileupload-processing'); - }, - processstop: function (e) { - if (e.isDefaultPrevented()) { - return false; - } - $(this).removeClass('fileupload-processing'); - }, - // Callback for file deletion: - destroy: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'), - removeNode = function () { - that._transition(data.context).done( - function () { - $(this).remove(); - that._trigger('destroyed', e, data); - } - ); - }; - if (data.url) { - data.dataType = data.dataType || that.options.dataType; - $.ajax(data).done(removeNode).fail(function () { - that._trigger('destroyfailed', e, data); - }); - } else { - removeNode(); - } - } - }, - - _resetFinishedDeferreds: function () { - this._finishedUploads = []; - }, - - _addFinishedDeferreds: function (deferred) { - if (!deferred) { - deferred = $.Deferred(); - } - this._finishedUploads.push(deferred); - return deferred; - }, - - _getFinishedDeferreds: function () { - return this._finishedUploads; - }, - - // Link handler, that allows to download files - // by drag & drop of the links to the desktop: - _enableDragToDesktop: function () { - var link = $(this), - url = link.prop('href'), - name = link.prop('download'), - type = 'application/octet-stream'; - link.bind('dragstart', function (e) { - try { - e.originalEvent.dataTransfer.setData( - 'DownloadURL', - [type, name, url].join(':') - ); - } catch (ignore) {} - }); - }, - - _formatFileSize: function (bytes) { - if (typeof bytes !== 'number') { - return ''; - } - if (bytes >= 1000000000) { - return (bytes / 1000000000).toFixed(2) + ' GB'; - } - if (bytes >= 1000000) { - return (bytes / 1000000).toFixed(2) + ' MB'; - } - return (bytes / 1000).toFixed(2) + ' KB'; - }, - - _formatBitrate: function (bits) { - if (typeof bits !== 'number') { - return ''; - } - if (bits >= 1000000000) { - return (bits / 1000000000).toFixed(2) + ' Gbit/s'; - } - if (bits >= 1000000) { - return (bits / 1000000).toFixed(2) + ' Mbit/s'; - } - if (bits >= 1000) { - return (bits / 1000).toFixed(2) + ' kbit/s'; - } - return bits.toFixed(2) + ' bit/s'; - }, - - _formatTime: function (seconds) { - var date = new Date(seconds * 1000), - days = Math.floor(seconds / 86400); - days = days ? days + 'd ' : ''; - return days + - ('0' + date.getUTCHours()).slice(-2) + ':' + - ('0' + date.getUTCMinutes()).slice(-2) + ':' + - ('0' + date.getUTCSeconds()).slice(-2); - }, - - _formatPercentage: function (floatValue) { - return (floatValue * 100).toFixed(2) + ' %'; - }, - - _renderExtendedProgress: function (data) { - return this._formatBitrate(data.bitrate) + ' | ' + - this._formatTime( - (data.total - data.loaded) * 8 / data.bitrate - ) + ' | ' + - this._formatPercentage( - data.loaded / data.total - ) + ' | ' + - this._formatFileSize(data.loaded) + ' / ' + - this._formatFileSize(data.total); - }, - - _renderTemplate: function (func, files) { - if (!func) { - return $(); - } - var result = func({ - files: files, - formatFileSize: this._formatFileSize, - options: this.options - }); - if (result instanceof $) { - return result; - } - return $(this.options.templatesContainer).html(result).children(); - }, - - _renderPreviews: function (data) { - data.context.find('.preview').each(function (index, elm) { - $(elm).append(data.files[index].preview); - }); - }, - - _renderUpload: function (files) { - return this._renderTemplate( - this.options.uploadTemplate, - files - ); - }, - - _renderDownload: function (files) { - return this._renderTemplate( - this.options.downloadTemplate, - files - ).find('a[download]').each(this._enableDragToDesktop).end(); - }, - - _startHandler: function (e) { - e.preventDefault(); - var button = $(e.currentTarget), - template = button.closest('.template-upload'), - data = template.data('data'); - button.prop('disabled', true); - if (data && data.submit) { - data.submit(); - } - }, - - _cancelHandler: function (e) { - e.preventDefault(); - var template = $(e.currentTarget) - .closest('.template-upload,.template-download'), - data = template.data('data') || {}; - data.context = data.context || template; - if (data.abort) { - data.abort(); - } else { - data.errorThrown = 'abort'; - this._trigger('fail', e, data); - } - }, - - _deleteHandler: function (e) { - e.preventDefault(); - var button = $(e.currentTarget); - this._trigger('destroy', e, $.extend({ - context: button.closest('.template-download'), - type: 'DELETE' - }, button.data())); - }, - - _forceReflow: function (node) { - return $.support.transition && node.length && - node[0].offsetWidth; - }, - - _transition: function (node) { - var dfd = $.Deferred(); - if ($.support.transition && node.hasClass('fade') && node.is(':visible')) { - node.bind( - $.support.transition.end, - function (e) { - // Make sure we don't respond to other transitions events - // in the container element, e.g. from button elements: - if (e.target === node[0]) { - node.unbind($.support.transition.end); - dfd.resolveWith(node); - } - } - ).toggleClass('in'); - } else { - node.toggleClass('in'); - dfd.resolveWith(node); - } - return dfd; - }, - - _initButtonBarEventHandlers: function () { - var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'), - filesList = this.options.filesContainer; - this._on(fileUploadButtonBar.find('.start'), { - click: function (e) { - e.preventDefault(); - filesList.find('.start').click(); - } - }); - this._on(fileUploadButtonBar.find('.cancel'), { - click: function (e) { - e.preventDefault(); - filesList.find('.cancel').click(); - } - }); - this._on(fileUploadButtonBar.find('.delete'), { - click: function (e) { - e.preventDefault(); - filesList.find('.toggle:checked') - .closest('.template-download') - .find('.delete').click(); - fileUploadButtonBar.find('.toggle') - .prop('checked', false); - } - }); - this._on(fileUploadButtonBar.find('.toggle'), { - change: function (e) { - filesList.find('.toggle').prop( - 'checked', - $(e.currentTarget).is(':checked') - ); - } - }); - }, - - _destroyButtonBarEventHandlers: function () { - this._off( - this.element.find('.fileupload-buttonbar') - .find('.start, .cancel, .delete'), - 'click' - ); - this._off( - this.element.find('.fileupload-buttonbar .toggle'), - 'change.' - ); - }, - - _initEventHandlers: function () { - this._super(); - this._on(this.options.filesContainer, { - 'click .start': this._startHandler, - 'click .cancel': this._cancelHandler, - 'click .delete': this._deleteHandler - }); - this._initButtonBarEventHandlers(); - }, - - _destroyEventHandlers: function () { - this._destroyButtonBarEventHandlers(); - this._off(this.options.filesContainer, 'click'); - this._super(); - }, - - _enableFileInputButton: function () { - this.element.find('.fileinput-button input') - .prop('disabled', false) - .parent().removeClass('disabled'); - }, - - _disableFileInputButton: function () { - this.element.find('.fileinput-button input') - .prop('disabled', true) - .parent().addClass('disabled'); - }, - - _initTemplates: function () { - var options = this.options; - options.templatesContainer = this.document[0].createElement( - options.filesContainer.prop('nodeName') - ); - if (tmpl) { - if (options.uploadTemplateId) { - options.uploadTemplate = tmpl(options.uploadTemplateId); - } - if (options.downloadTemplateId) { - options.downloadTemplate = tmpl(options.downloadTemplateId); - } - } - }, - - _initFilesContainer: function () { - var options = this.options; - if (options.filesContainer === undefined) { - options.filesContainer = this.element.find('.files'); - } else if (!(options.filesContainer instanceof $)) { - options.filesContainer = $(options.filesContainer); - } - }, - - _initSpecialOptions: function () { - this._super(); - this._initFilesContainer(); - this._initTemplates(); - }, - - _create: function () { - this._super(); - this._resetFinishedDeferreds(); - if (!$.support.fileInput) { - this._disableFileInputButton(); - } - }, - - enable: function () { - var wasDisabled = false; - if (this.options.disabled) { - wasDisabled = true; - } - this._super(); - if (wasDisabled) { - this.element.find('input, button').prop('disabled', false); - this._enableFileInputButton(); - } - }, - - disable: function () { - if (!this.options.disabled) { - this.element.find('input, button').prop('disabled', true); - this._disableFileInputButton(); - } - this._super(); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-validate.js b/library/blueimp_upload/js/jquery.fileupload-validate.js deleted file mode 100644 index eebeb3733..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-validate.js +++ /dev/null @@ -1,125 +0,0 @@ -/* - * jQuery File Upload Validation Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global define, require, window */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery - ); - } -}(function ($) { - 'use strict'; - - // Append to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.push( - { - action: 'validate', - // Always trigger this action, - // even if the previous action was rejected: - always: true, - // Options taken from the global options map: - acceptFileTypes: '@', - maxFileSize: '@', - minFileSize: '@', - maxNumberOfFiles: '@', - disabled: '@disableValidation' - } - ); - - // The File Upload Validation plugin extends the fileupload widget - // with file validation functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - /* - // The regular expression for allowed file types, matches - // against either file type or file name: - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, - // The maximum allowed file size in bytes: - maxFileSize: 10000000, // 10 MB - // The minimum allowed file size in bytes: - minFileSize: undefined, // No minimal file size - // The limit of files to be uploaded: - maxNumberOfFiles: 10, - */ - - // Function returning the current number of files, - // has to be overriden for maxNumberOfFiles validation: - getNumberOfFiles: $.noop, - - // Error and info messages: - messages: { - maxNumberOfFiles: 'Maximum number of files exceeded', - acceptFileTypes: 'File type not allowed', - maxFileSize: 'File is too large', - minFileSize: 'File is too small' - } - }, - - processActions: { - - validate: function (data, options) { - if (options.disabled) { - return data; - } - var dfd = $.Deferred(), - settings = this.options, - file = data.files[data.index], - fileSize; - if (options.minFileSize || options.maxFileSize) { - fileSize = file.size; - } - if ($.type(options.maxNumberOfFiles) === 'number' && - (settings.getNumberOfFiles() || 0) + data.files.length > - options.maxNumberOfFiles) { - file.error = settings.i18n('maxNumberOfFiles'); - } else if (options.acceptFileTypes && - !(options.acceptFileTypes.test(file.type) || - options.acceptFileTypes.test(file.name))) { - file.error = settings.i18n('acceptFileTypes'); - } else if (fileSize > options.maxFileSize) { - file.error = settings.i18n('maxFileSize'); - } else if ($.type(fileSize) === 'number' && - fileSize < options.minFileSize) { - file.error = settings.i18n('minFileSize'); - } else { - delete file.error; - } - if (file.error || data.files.error) { - data.files.error = true; - dfd.rejectWith(this, [data]); - } else { - dfd.resolveWith(this, [data]); - } - return dfd.promise(); - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload-video.js b/library/blueimp_upload/js/jquery.fileupload-video.js deleted file mode 100644 index aedcec2ba..000000000 --- a/library/blueimp_upload/js/jquery.fileupload-video.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * jQuery File Upload Video Preview Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2013, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'load-image', - './jquery.fileupload-process' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('blueimp-load-image/js/load-image'), - require('./jquery.fileupload-process') - ); - } else { - // Browser globals: - factory( - window.jQuery, - window.loadImage - ); - } -}(function ($, loadImage) { - 'use strict'; - - // Prepend to the default processQueue: - $.blueimp.fileupload.prototype.options.processQueue.unshift( - { - action: 'loadVideo', - // Use the action as prefix for the "@" options: - prefix: true, - fileTypes: '@', - maxFileSize: '@', - disabled: '@disableVideoPreview' - }, - { - action: 'setVideo', - name: '@videoPreviewName', - disabled: '@disableVideoPreview' - } - ); - - // The File Upload Video Preview plugin extends the fileupload widget - // with video preview functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of video files to load, - // matched against the file type: - loadVideoFileTypes: /^video\/.*$/ - }, - - _videoElement: document.createElement('video'), - - processActions: { - - // Loads the video file given via data.files and data.index - // as video element if the browser supports playing it. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadVideo: function (data, options) { - if (options.disabled) { - return data; - } - var file = data.files[data.index], - url, - video; - if (this._videoElement.canPlayType && - this._videoElement.canPlayType(file.type) && - ($.type(options.maxFileSize) !== 'number' || - file.size <= options.maxFileSize) && - (!options.fileTypes || - options.fileTypes.test(file.type))) { - url = loadImage.createObjectURL(file); - if (url) { - video = this._videoElement.cloneNode(false); - video.src = url; - video.controls = true; - data.video = video; - return data; - } - } - return data; - }, - - // Sets the video element as a property of the file object: - setVideo: function (data, options) { - if (data.video && !options.disabled) { - data.files[data.index][options.name || 'preview'] = data.video; - } - return data; - } - - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.fileupload.js b/library/blueimp_upload/js/jquery.fileupload.js deleted file mode 100644 index 700f9013c..000000000 --- a/library/blueimp_upload/js/jquery.fileupload.js +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * jQuery File Upload Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* jshint nomen:false */ -/* global define, require, window, document, location, Blob, FormData */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define([ - 'jquery', - 'jquery-ui/ui/widget' - ], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory( - require('jquery'), - require('./vendor/jquery.ui.widget') - ); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - // Detect file input support, based on - // http://viljamis.com/blog/2012/file-upload-support-on-mobile/ - $.support.fileInput = !(new RegExp( - // Handle devices which give false positives for the feature detection: - '(Android (1\\.[0156]|2\\.[01]))' + - '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' + - '|(w(eb)?OSBrowser)|(webOS)' + - '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' - ).test(window.navigator.userAgent) || - // Feature detection for all other devices: - $('').prop('disabled')); - - // The FileReader API is not actually used, but works as feature detection, - // as some Safari versions (5?) support XHR file uploads via the FormData API, - // but not non-multipart XHR file uploads. - // window.XMLHttpRequestUpload is not available on IE10, so we check for - // window.ProgressEvent instead to detect XHR2 file upload capability: - $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader); - $.support.xhrFormDataFileUpload = !!window.FormData; - - // Detect support for Blob slicing (required for chunked uploads): - $.support.blobSlice = window.Blob && (Blob.prototype.slice || - Blob.prototype.webkitSlice || Blob.prototype.mozSlice); - - // Helper function to create drag handlers for dragover/dragenter/dragleave: - function getDragHandler(type) { - var isDragOver = type === 'dragover'; - return function (e) { - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; - var dataTransfer = e.dataTransfer; - if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && - this._trigger( - type, - $.Event(type, {delegatedEvent: e}) - ) !== false) { - e.preventDefault(); - if (isDragOver) { - dataTransfer.dropEffect = 'copy'; - } - } - }; - } - - // The fileupload widget listens for change events on file input fields defined - // via fileInput setting and paste or drop events of the given dropZone. - // In addition to the default jQuery Widget methods, the fileupload widget - // exposes the "add" and "send" methods, to add or directly send files using - // the fileupload API. - // By default, files added via file input selection, paste, drag & drop or - // "add" method are uploaded immediately, but it is possible to override - // the "add" callback option to queue file uploads. - $.widget('blueimp.fileupload', { - - options: { - // The drop target element(s), by the default the complete document. - // Set to null to disable drag & drop support: - dropZone: $(document), - // The paste target element(s), by the default undefined. - // Set to a DOM node or jQuery object to enable file pasting: - pasteZone: undefined, - // The file input field(s), that are listened to for change events. - // If undefined, it is set to the file input fields inside - // of the widget element on plugin initialization. - // Set to null to disable the change listener. - fileInput: undefined, - // By default, the file input field is replaced with a clone after - // each input field change event. This is required for iframe transport - // queues and allows change events to be fired for the same file - // selection, but can be disabled by setting the following option to false: - replaceFileInput: true, - // The parameter name for the file form data (the request argument name). - // If undefined or empty, the name property of the file input field is - // used, or "files[]" if the file input name property is also empty, - // can be a string or an array of strings: - paramName: undefined, - // By default, each file of a selection is uploaded using an individual - // request for XHR type uploads. Set to false to upload file - // selections in one request each: - singleFileUploads: true, - // To limit the number of files uploaded with one XHR request, - // set the following option to an integer greater than 0: - limitMultiFileUploads: undefined, - // The following option limits the number of files uploaded with one - // XHR request to keep the request size under or equal to the defined - // limit in bytes: - limitMultiFileUploadSize: undefined, - // Multipart file uploads add a number of bytes to each uploaded file, - // therefore the following option adds an overhead for each file used - // in the limitMultiFileUploadSize configuration: - limitMultiFileUploadSizeOverhead: 512, - // Set the following option to true to issue all file upload requests - // in a sequential order: - sequentialUploads: false, - // To limit the number of concurrent uploads, - // set the following option to an integer greater than 0: - limitConcurrentUploads: undefined, - // Set the following option to true to force iframe transport uploads: - forceIframeTransport: false, - // Set the following option to the location of a redirect url on the - // origin server, for cross-domain iframe transport uploads: - redirect: undefined, - // The parameter name for the redirect url, sent as part of the form - // data and set to 'redirect' if this option is empty: - redirectParamName: undefined, - // Set the following option to the location of a postMessage window, - // to enable postMessage transport uploads: - postMessage: undefined, - // By default, XHR file uploads are sent as multipart/form-data. - // The iframe transport is always using multipart/form-data. - // Set to false to enable non-multipart XHR uploads: - multipart: true, - // To upload large files in smaller chunks, set the following option - // to a preferred maximum chunk size. If set to 0, null or undefined, - // or the browser does not support the required Blob API, files will - // be uploaded as a whole. - maxChunkSize: undefined, - // When a non-multipart upload or a chunked multipart upload has been - // aborted, this option can be used to resume the upload by setting - // it to the size of the already uploaded bytes. This option is most - // useful when modifying the options object inside of the "add" or - // "send" callbacks, as the options are cloned for each file upload. - uploadedBytes: undefined, - // By default, failed (abort or error) file uploads are removed from the - // global progress calculation. Set the following option to false to - // prevent recalculating the global progress data: - recalculateProgress: true, - // Interval in milliseconds to calculate and trigger progress events: - progressInterval: 100, - // Interval in milliseconds to calculate progress bitrate: - bitrateInterval: 500, - // By default, uploads are started automatically when adding files: - autoUpload: true, - - // Error and info messages: - messages: { - uploadedBytes: 'Uploaded bytes exceed file size' - }, - - // Translation function, gets the message key to be translated - // and an object with context specific data as arguments: - i18n: function (message, context) { - message = this.messages[message] || message.toString(); - if (context) { - $.each(context, function (key, value) { - message = message.replace('{' + key + '}', value); - }); - } - return message; - }, - - // Additional form data to be sent along with the file uploads can be set - // using this option, which accepts an array of objects with name and - // value properties, a function returning such an array, a FormData - // object (for XHR file uploads), or a simple object. - // The form of the first fileInput is given as parameter to the function: - formData: function (form) { - return form.serializeArray(); - }, - - // The add callback is invoked as soon as files are added to the fileupload - // widget (via file input selection, drag & drop, paste or add API call). - // If the singleFileUploads option is enabled, this callback will be - // called once for each file in the selection for XHR file uploads, else - // once for each file selection. - // - // The upload starts when the submit method is invoked on the data parameter. - // The data object contains a files property holding the added files - // and allows you to override plugin options as well as define ajax settings. - // - // Listeners for this callback can also be bound the following way: - // .bind('fileuploadadd', func); - // - // data.submit() returns a Promise object and allows to attach additional - // handlers using jQuery's Deferred callbacks: - // data.submit().done(func).fail(func).always(func); - add: function (e, data) { - if (e.isDefaultPrevented()) { - return false; - } - if (data.autoUpload || (data.autoUpload !== false && - $(this).fileupload('option', 'autoUpload'))) { - data.process().done(function () { - data.submit(); - }); - } - }, - - // Other callbacks: - - // Callback for the submit event of each file upload: - // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); - - // Callback for the start of each file upload request: - // send: function (e, data) {}, // .bind('fileuploadsend', func); - - // Callback for successful uploads: - // done: function (e, data) {}, // .bind('fileuploaddone', func); - - // Callback for failed (abort or error) uploads: - // fail: function (e, data) {}, // .bind('fileuploadfail', func); - - // Callback for completed (success, abort or error) requests: - // always: function (e, data) {}, // .bind('fileuploadalways', func); - - // Callback for upload progress events: - // progress: function (e, data) {}, // .bind('fileuploadprogress', func); - - // Callback for global upload progress events: - // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); - - // Callback for uploads start, equivalent to the global ajaxStart event: - // start: function (e) {}, // .bind('fileuploadstart', func); - - // Callback for uploads stop, equivalent to the global ajaxStop event: - // stop: function (e) {}, // .bind('fileuploadstop', func); - - // Callback for change events of the fileInput(s): - // change: function (e, data) {}, // .bind('fileuploadchange', func); - - // Callback for paste events to the pasteZone(s): - // paste: function (e, data) {}, // .bind('fileuploadpaste', func); - - // Callback for drop events of the dropZone(s): - // drop: function (e, data) {}, // .bind('fileuploaddrop', func); - - // Callback for dragover events of the dropZone(s): - // dragover: function (e) {}, // .bind('fileuploaddragover', func); - - // Callback before the start of each chunk upload request (before form data initialization): - // chunkbeforesend: function (e, data) {}, // .bind('fileuploadchunkbeforesend', func); - - // Callback for the start of each chunk upload request: - // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); - - // Callback for successful chunk uploads: - // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); - - // Callback for failed (abort or error) chunk uploads: - // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); - - // Callback for completed (success, abort or error) chunk upload requests: - // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); - - // The plugin options are used as settings object for the ajax calls. - // The following are jQuery ajax settings required for the file uploads: - processData: false, - contentType: false, - cache: false, - timeout: 0 - }, - - // A list of options that require reinitializing event listeners and/or - // special initialization code: - _specialOptions: [ - 'fileInput', - 'dropZone', - 'pasteZone', - 'multipart', - 'forceIframeTransport' - ], - - _blobSlice: $.support.blobSlice && function () { - var slice = this.slice || this.webkitSlice || this.mozSlice; - return slice.apply(this, arguments); - }, - - _BitrateTimer: function () { - this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); - this.loaded = 0; - this.bitrate = 0; - this.getBitrate = function (now, loaded, interval) { - var timeDiff = now - this.timestamp; - if (!this.bitrate || !interval || timeDiff > interval) { - this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; - this.loaded = loaded; - this.timestamp = now; - } - return this.bitrate; - }; - }, - - _isXHRUpload: function (options) { - return !options.forceIframeTransport && - ((!options.multipart && $.support.xhrFileUpload) || - $.support.xhrFormDataFileUpload); - }, - - _getFormData: function (options) { - var formData; - if ($.type(options.formData) === 'function') { - return options.formData(options.form); - } - if ($.isArray(options.formData)) { - return options.formData; - } - if ($.type(options.formData) === 'object') { - formData = []; - $.each(options.formData, function (name, value) { - formData.push({name: name, value: value}); - }); - return formData; - } - return []; - }, - - _getTotal: function (files) { - var total = 0; - $.each(files, function (index, file) { - total += file.size || 1; - }); - return total; - }, - - _initProgressObject: function (obj) { - var progress = { - loaded: 0, - total: 0, - bitrate: 0 - }; - if (obj._progress) { - $.extend(obj._progress, progress); - } else { - obj._progress = progress; - } - }, - - _initResponseObject: function (obj) { - var prop; - if (obj._response) { - for (prop in obj._response) { - if (obj._response.hasOwnProperty(prop)) { - delete obj._response[prop]; - } - } - } else { - obj._response = {}; - } - }, - - _onProgress: function (e, data) { - if (e.lengthComputable) { - var now = ((Date.now) ? Date.now() : (new Date()).getTime()), - loaded; - if (data._time && data.progressInterval && - (now - data._time < data.progressInterval) && - e.loaded !== e.total) { - return; - } - data._time = now; - loaded = Math.floor( - e.loaded / e.total * (data.chunkSize || data._progress.total) - ) + (data.uploadedBytes || 0); - // Add the difference from the previously loaded state - // to the global loaded counter: - this._progress.loaded += (loaded - data._progress.loaded); - this._progress.bitrate = this._bitrateTimer.getBitrate( - now, - this._progress.loaded, - data.bitrateInterval - ); - data._progress.loaded = data.loaded = loaded; - data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( - now, - loaded, - data.bitrateInterval - ); - // Trigger a custom progress event with a total data property set - // to the file size(s) of the current upload and a loaded data - // property calculated accordingly: - this._trigger( - 'progress', - $.Event('progress', {delegatedEvent: e}), - data - ); - // Trigger a global progress event for all current file uploads, - // including ajax calls queued for sequential file uploads: - this._trigger( - 'progressall', - $.Event('progressall', {delegatedEvent: e}), - this._progress - ); - } - }, - - _initProgressListener: function (options) { - var that = this, - xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); - // Accesss to the native XHR object is required to add event listeners - // for the upload progress event: - if (xhr.upload) { - $(xhr.upload).bind('progress', function (e) { - var oe = e.originalEvent; - // Make sure the progress event properties get copied over: - e.lengthComputable = oe.lengthComputable; - e.loaded = oe.loaded; - e.total = oe.total; - that._onProgress(e, options); - }); - options.xhr = function () { - return xhr; - }; - } - }, - - _deinitProgressListener: function (options) { - var xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); - if (xhr.upload) { - $(xhr.upload).unbind('progress'); - } - }, - - _isInstanceOf: function (type, obj) { - // Cross-frame instanceof check - return Object.prototype.toString.call(obj) === '[object ' + type + ']'; - }, - - _initXHRData: function (options) { - var that = this, - formData, - file = options.files[0], - // Ignore non-multipart setting if not supported: - multipart = options.multipart || !$.support.xhrFileUpload, - paramName = $.type(options.paramName) === 'array' ? - options.paramName[0] : options.paramName; - options.headers = $.extend({}, options.headers); - if (options.contentRange) { - options.headers['Content-Range'] = options.contentRange; - } - if (!multipart || options.blob || !this._isInstanceOf('File', file)) { - options.headers['Content-Disposition'] = 'attachment; filename="' + - encodeURI(file.uploadName || file.name) + '"'; - } - if (!multipart) { - options.contentType = file.type || 'application/octet-stream'; - options.data = options.blob || file; - } else if ($.support.xhrFormDataFileUpload) { - if (options.postMessage) { - // window.postMessage does not allow sending FormData - // objects, so we just add the File/Blob objects to - // the formData array and let the postMessage window - // create the FormData object out of this array: - formData = this._getFormData(options); - if (options.blob) { - formData.push({ - name: paramName, - value: options.blob - }); - } else { - $.each(options.files, function (index, file) { - formData.push({ - name: ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - value: file - }); - }); - } - } else { - if (that._isInstanceOf('FormData', options.formData)) { - formData = options.formData; - } else { - formData = new FormData(); - $.each(this._getFormData(options), function (index, field) { - formData.append(field.name, field.value); - }); - } - if (options.blob) { - formData.append( - paramName, - options.blob, - file.uploadName || file.name - ); - } else { - $.each(options.files, function (index, file) { - // This check allows the tests to run with - // dummy objects: - if (that._isInstanceOf('File', file) || - that._isInstanceOf('Blob', file)) { - formData.append( - ($.type(options.paramName) === 'array' && - options.paramName[index]) || paramName, - file, - file.uploadName || file.name - ); - } - }); - } - } - options.data = formData; - } - // Blob reference is not needed anymore, free memory: - options.blob = null; - }, - - _initIframeSettings: function (options) { - var targetHost = $('').prop('href', options.url).prop('host'); - // Setting the dataType to iframe enables the iframe transport: - options.dataType = 'iframe ' + (options.dataType || ''); - // The iframe transport accepts a serialized array as form data: - options.formData = this._getFormData(options); - // Add redirect url to form data on cross-domain uploads: - if (options.redirect && targetHost && targetHost !== location.host) { - options.formData.push({ - name: options.redirectParamName || 'redirect', - value: options.redirect - }); - } - }, - - _initDataSettings: function (options) { - if (this._isXHRUpload(options)) { - if (!this._chunkedUpload(options, true)) { - if (!options.data) { - this._initXHRData(options); - } - this._initProgressListener(options); - } - if (options.postMessage) { - // Setting the dataType to postmessage enables the - // postMessage transport: - options.dataType = 'postmessage ' + (options.dataType || ''); - } - } else { - this._initIframeSettings(options); - } - }, - - _getParamName: function (options) { - var fileInput = $(options.fileInput), - paramName = options.paramName; - if (!paramName) { - paramName = []; - fileInput.each(function () { - var input = $(this), - name = input.prop('name') || 'files[]', - i = (input.prop('files') || [1]).length; - while (i) { - paramName.push(name); - i -= 1; - } - }); - if (!paramName.length) { - paramName = [fileInput.prop('name') || 'files[]']; - } - } else if (!$.isArray(paramName)) { - paramName = [paramName]; - } - return paramName; - }, - - _initFormSettings: function (options) { - // Retrieve missing options from the input field and the - // associated form, if available: - if (!options.form || !options.form.length) { - options.form = $(options.fileInput.prop('form')); - // If the given file input doesn't have an associated form, - // use the default widget file input's form: - if (!options.form.length) { - options.form = $(this.options.fileInput.prop('form')); - } - } - options.paramName = this._getParamName(options); - if (!options.url) { - options.url = options.form.prop('action') || location.href; - } - // The HTTP request method must be "POST" or "PUT": - options.type = (options.type || - ($.type(options.form.prop('method')) === 'string' && - options.form.prop('method')) || '' - ).toUpperCase(); - if (options.type !== 'POST' && options.type !== 'PUT' && - options.type !== 'PATCH') { - options.type = 'POST'; - } - if (!options.formAcceptCharset) { - options.formAcceptCharset = options.form.attr('accept-charset'); - } - }, - - _getAJAXSettings: function (data) { - var options = $.extend({}, this.options, data); - this._initFormSettings(options); - this._initDataSettings(options); - return options; - }, - - // jQuery 1.6 doesn't provide .state(), - // while jQuery 1.8+ removed .isRejected() and .isResolved(): - _getDeferredState: function (deferred) { - if (deferred.state) { - return deferred.state(); - } - if (deferred.isResolved()) { - return 'resolved'; - } - if (deferred.isRejected()) { - return 'rejected'; - } - return 'pending'; - }, - - // Maps jqXHR callbacks to the equivalent - // methods of the given Promise object: - _enhancePromise: function (promise) { - promise.success = promise.done; - promise.error = promise.fail; - promise.complete = promise.always; - return promise; - }, - - // Creates and returns a Promise object enhanced with - // the jqXHR methods abort, success, error and complete: - _getXHRPromise: function (resolveOrReject, context, args) { - var dfd = $.Deferred(), - promise = dfd.promise(); - context = context || this.options.context || promise; - if (resolveOrReject === true) { - dfd.resolveWith(context, args); - } else if (resolveOrReject === false) { - dfd.rejectWith(context, args); - } - promise.abort = dfd.promise; - return this._enhancePromise(promise); - }, - - // Adds convenience methods to the data callback argument: - _addConvenienceMethods: function (e, data) { - var that = this, - getPromise = function (args) { - return $.Deferred().resolveWith(that, args).promise(); - }; - data.process = function (resolveFunc, rejectFunc) { - if (resolveFunc || rejectFunc) { - data._processQueue = this._processQueue = - (this._processQueue || getPromise([this])).then( - function () { - if (data.errorThrown) { - return $.Deferred() - .rejectWith(that, [data]).promise(); - } - return getPromise(arguments); - } - ).then(resolveFunc, rejectFunc); - } - return this._processQueue || getPromise([this]); - }; - data.submit = function () { - if (this.state() !== 'pending') { - data.jqXHR = this.jqXHR = - (that._trigger( - 'submit', - $.Event('submit', {delegatedEvent: e}), - this - ) !== false) && that._onSend(e, this); - } - return this.jqXHR || that._getXHRPromise(); - }; - data.abort = function () { - if (this.jqXHR) { - return this.jqXHR.abort(); - } - this.errorThrown = 'abort'; - that._trigger('fail', null, this); - return that._getXHRPromise(false); - }; - data.state = function () { - if (this.jqXHR) { - return that._getDeferredState(this.jqXHR); - } - if (this._processQueue) { - return that._getDeferredState(this._processQueue); - } - }; - data.processing = function () { - return !this.jqXHR && this._processQueue && that - ._getDeferredState(this._processQueue) === 'pending'; - }; - data.progress = function () { - return this._progress; - }; - data.response = function () { - return this._response; - }; - }, - - // Parses the Range header from the server response - // and returns the uploaded bytes: - _getUploadedBytes: function (jqXHR) { - var range = jqXHR.getResponseHeader('Range'), - parts = range && range.split('-'), - upperBytesPos = parts && parts.length > 1 && - parseInt(parts[1], 10); - return upperBytesPos && upperBytesPos + 1; - }, - - // Uploads a file in multiple, sequential requests - // by splitting the file up in multiple blob chunks. - // If the second parameter is true, only tests if the file - // should be uploaded in chunks, but does not invoke any - // upload requests: - _chunkedUpload: function (options, testOnly) { - options.uploadedBytes = options.uploadedBytes || 0; - var that = this, - file = options.files[0], - fs = file.size, - ub = options.uploadedBytes, - mcs = options.maxChunkSize || fs, - slice = this._blobSlice, - dfd = $.Deferred(), - promise = dfd.promise(), - jqXHR, - upload; - if (!(this._isXHRUpload(options) && slice && (ub || ($.type(mcs) === 'function' ? mcs(options) : mcs) < fs)) || - options.data) { - return false; - } - if (testOnly) { - return true; - } - if (ub >= fs) { - file.error = options.i18n('uploadedBytes'); - return this._getXHRPromise( - false, - options.context, - [null, 'error', file.error] - ); - } - // The chunk upload method: - upload = function () { - // Clone the options object for each chunk upload: - var o = $.extend({}, options), - currentLoaded = o._progress.loaded; - o.blob = slice.call( - file, - ub, - ub + ($.type(mcs) === 'function' ? mcs(o) : mcs), - file.type - ); - // Store the current chunk size, as the blob itself - // will be dereferenced after data processing: - o.chunkSize = o.blob.size; - // Expose the chunk bytes position range: - o.contentRange = 'bytes ' + ub + '-' + - (ub + o.chunkSize - 1) + '/' + fs; - // Trigger chunkbeforesend to allow form data to be updated for this chunk - that._trigger('chunkbeforesend', null, o); - // Process the upload data (the blob and potential form data): - that._initXHRData(o); - // Add progress listeners for this chunk upload: - that._initProgressListener(o); - jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || - that._getXHRPromise(false, o.context)) - .done(function (result, textStatus, jqXHR) { - ub = that._getUploadedBytes(jqXHR) || - (ub + o.chunkSize); - // Create a progress event if no final progress event - // with loaded equaling total has been triggered - // for this chunk: - if (currentLoaded + o.chunkSize - o._progress.loaded) { - that._onProgress($.Event('progress', { - lengthComputable: true, - loaded: ub - o.uploadedBytes, - total: ub - o.uploadedBytes - }), o); - } - options.uploadedBytes = o.uploadedBytes = ub; - o.result = result; - o.textStatus = textStatus; - o.jqXHR = jqXHR; - that._trigger('chunkdone', null, o); - that._trigger('chunkalways', null, o); - if (ub < fs) { - // File upload not yet complete, - // continue with the next chunk: - upload(); - } else { - dfd.resolveWith( - o.context, - [result, textStatus, jqXHR] - ); - } - }) - .fail(function (jqXHR, textStatus, errorThrown) { - o.jqXHR = jqXHR; - o.textStatus = textStatus; - o.errorThrown = errorThrown; - that._trigger('chunkfail', null, o); - that._trigger('chunkalways', null, o); - dfd.rejectWith( - o.context, - [jqXHR, textStatus, errorThrown] - ); - }) - .always(function () { - that._deinitProgressListener(o); - }); - }; - this._enhancePromise(promise); - promise.abort = function () { - return jqXHR.abort(); - }; - upload(); - return promise; - }, - - _beforeSend: function (e, data) { - if (this._active === 0) { - // the start callback is triggered when an upload starts - // and no other uploads are currently running, - // equivalent to the global ajaxStart event: - this._trigger('start'); - // Set timer for global bitrate progress calculation: - this._bitrateTimer = new this._BitrateTimer(); - // Reset the global progress values: - this._progress.loaded = this._progress.total = 0; - this._progress.bitrate = 0; - } - // Make sure the container objects for the .response() and - // .progress() methods on the data object are available - // and reset to their initial state: - this._initResponseObject(data); - this._initProgressObject(data); - data._progress.loaded = data.loaded = data.uploadedBytes || 0; - data._progress.total = data.total = this._getTotal(data.files) || 1; - data._progress.bitrate = data.bitrate = 0; - this._active += 1; - // Initialize the global progress values: - this._progress.loaded += data.loaded; - this._progress.total += data.total; - }, - - _onDone: function (result, textStatus, jqXHR, options) { - var total = options._progress.total, - response = options._response; - if (options._progress.loaded < total) { - // Create a progress event if no final progress event - // with loaded equaling total has been triggered: - this._onProgress($.Event('progress', { - lengthComputable: true, - loaded: total, - total: total - }), options); - } - response.result = options.result = result; - response.textStatus = options.textStatus = textStatus; - response.jqXHR = options.jqXHR = jqXHR; - this._trigger('done', null, options); - }, - - _onFail: function (jqXHR, textStatus, errorThrown, options) { - var response = options._response; - if (options.recalculateProgress) { - // Remove the failed (error or abort) file upload from - // the global progress calculation: - this._progress.loaded -= options._progress.loaded; - this._progress.total -= options._progress.total; - } - response.jqXHR = options.jqXHR = jqXHR; - response.textStatus = options.textStatus = textStatus; - response.errorThrown = options.errorThrown = errorThrown; - this._trigger('fail', null, options); - }, - - _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { - // jqXHRorResult, textStatus and jqXHRorError are added to the - // options object via done and fail callbacks - this._trigger('always', null, options); - }, - - _onSend: function (e, data) { - if (!data.submit) { - this._addConvenienceMethods(e, data); - } - var that = this, - jqXHR, - aborted, - slot, - pipe, - options = that._getAJAXSettings(data), - send = function () { - that._sending += 1; - // Set timer for bitrate progress calculation: - options._bitrateTimer = new that._BitrateTimer(); - jqXHR = jqXHR || ( - ((aborted || that._trigger( - 'send', - $.Event('send', {delegatedEvent: e}), - options - ) === false) && - that._getXHRPromise(false, options.context, aborted)) || - that._chunkedUpload(options) || $.ajax(options) - ).done(function (result, textStatus, jqXHR) { - that._onDone(result, textStatus, jqXHR, options); - }).fail(function (jqXHR, textStatus, errorThrown) { - that._onFail(jqXHR, textStatus, errorThrown, options); - }).always(function (jqXHRorResult, textStatus, jqXHRorError) { - that._deinitProgressListener(options); - that._onAlways( - jqXHRorResult, - textStatus, - jqXHRorError, - options - ); - that._sending -= 1; - that._active -= 1; - if (options.limitConcurrentUploads && - options.limitConcurrentUploads > that._sending) { - // Start the next queued upload, - // that has not been aborted: - var nextSlot = that._slots.shift(); - while (nextSlot) { - if (that._getDeferredState(nextSlot) === 'pending') { - nextSlot.resolve(); - break; - } - nextSlot = that._slots.shift(); - } - } - if (that._active === 0) { - // The stop callback is triggered when all uploads have - // been completed, equivalent to the global ajaxStop event: - that._trigger('stop'); - } - }); - return jqXHR; - }; - this._beforeSend(e, options); - if (this.options.sequentialUploads || - (this.options.limitConcurrentUploads && - this.options.limitConcurrentUploads <= this._sending)) { - if (this.options.limitConcurrentUploads > 1) { - slot = $.Deferred(); - this._slots.push(slot); - pipe = slot.then(send); - } else { - this._sequence = this._sequence.then(send, send); - pipe = this._sequence; - } - // Return the piped Promise object, enhanced with an abort method, - // which is delegated to the jqXHR object of the current upload, - // and jqXHR callbacks mapped to the equivalent Promise methods: - pipe.abort = function () { - aborted = [undefined, 'abort', 'abort']; - if (!jqXHR) { - if (slot) { - slot.rejectWith(options.context, aborted); - } - return send(); - } - return jqXHR.abort(); - }; - return this._enhancePromise(pipe); - } - return send(); - }, - - _onAdd: function (e, data) { - var that = this, - result = true, - options = $.extend({}, this.options, data), - files = data.files, - filesLength = files.length, - limit = options.limitMultiFileUploads, - limitSize = options.limitMultiFileUploadSize, - overhead = options.limitMultiFileUploadSizeOverhead, - batchSize = 0, - paramName = this._getParamName(options), - paramNameSet, - paramNameSlice, - fileSet, - i, - j = 0; - if (!filesLength) { - return false; - } - if (limitSize && files[0].size === undefined) { - limitSize = undefined; - } - if (!(options.singleFileUploads || limit || limitSize) || - !this._isXHRUpload(options)) { - fileSet = [files]; - paramNameSet = [paramName]; - } else if (!(options.singleFileUploads || limitSize) && limit) { - fileSet = []; - paramNameSet = []; - for (i = 0; i < filesLength; i += limit) { - fileSet.push(files.slice(i, i + limit)); - paramNameSlice = paramName.slice(i, i + limit); - if (!paramNameSlice.length) { - paramNameSlice = paramName; - } - paramNameSet.push(paramNameSlice); - } - } else if (!options.singleFileUploads && limitSize) { - fileSet = []; - paramNameSet = []; - for (i = 0; i < filesLength; i = i + 1) { - batchSize += files[i].size + overhead; - if (i + 1 === filesLength || - ((batchSize + files[i + 1].size + overhead) > limitSize) || - (limit && i + 1 - j >= limit)) { - fileSet.push(files.slice(j, i + 1)); - paramNameSlice = paramName.slice(j, i + 1); - if (!paramNameSlice.length) { - paramNameSlice = paramName; - } - paramNameSet.push(paramNameSlice); - j = i + 1; - batchSize = 0; - } - } - } else { - paramNameSet = paramName; - } - data.originalFiles = files; - $.each(fileSet || files, function (index, element) { - var newData = $.extend({}, data); - newData.files = fileSet ? element : [element]; - newData.paramName = paramNameSet[index]; - that._initResponseObject(newData); - that._initProgressObject(newData); - that._addConvenienceMethods(e, newData); - result = that._trigger( - 'add', - $.Event('add', {delegatedEvent: e}), - newData - ); - return result; - }); - return result; - }, - - _replaceFileInput: function (data) { - var input = data.fileInput, - inputClone = input.clone(true), - restoreFocus = input.is(document.activeElement); - // Add a reference for the new cloned file input to the data argument: - data.fileInputClone = inputClone; - $('
').append(inputClone)[0].reset(); - // Detaching allows to insert the fileInput on another form - // without loosing the file input value: - input.after(inputClone).detach(); - // If the fileInput had focus before it was detached, - // restore focus to the inputClone. - if (restoreFocus) { - inputClone.focus(); - } - // Avoid memory leaks with the detached file input: - $.cleanData(input.unbind('remove')); - // Replace the original file input element in the fileInput - // elements set with the clone, which has been copied including - // event handlers: - this.options.fileInput = this.options.fileInput.map(function (i, el) { - if (el === input[0]) { - return inputClone[0]; - } - return el; - }); - // If the widget has been initialized on the file input itself, - // override this.element with the file input clone: - if (input[0] === this.element[0]) { - this.element = inputClone; - } - }, - - _handleFileTreeEntry: function (entry, path) { - var that = this, - dfd = $.Deferred(), - entries = [], - dirReader, - errorHandler = function (e) { - if (e && !e.entry) { - e.entry = entry; - } - // Since $.when returns immediately if one - // Deferred is rejected, we use resolve instead. - // This allows valid files and invalid items - // to be returned together in one set: - dfd.resolve([e]); - }, - successHandler = function (entries) { - that._handleFileTreeEntries( - entries, - path + entry.name + '/' - ).done(function (files) { - dfd.resolve(files); - }).fail(errorHandler); - }, - readEntries = function () { - dirReader.readEntries(function (results) { - if (!results.length) { - successHandler(entries); - } else { - entries = entries.concat(results); - readEntries(); - } - }, errorHandler); - }; - path = path || ''; - if (entry.isFile) { - if (entry._file) { - // Workaround for Chrome bug #149735 - entry._file.relativePath = path; - dfd.resolve(entry._file); - } else { - entry.file(function (file) { - file.relativePath = path; - dfd.resolve(file); - }, errorHandler); - } - } else if (entry.isDirectory) { - dirReader = entry.createReader(); - readEntries(); - } else { - // Return an empty list for file system items - // other than files or directories: - dfd.resolve([]); - } - return dfd.promise(); - }, - - _handleFileTreeEntries: function (entries, path) { - var that = this; - return $.when.apply( - $, - $.map(entries, function (entry) { - return that._handleFileTreeEntry(entry, path); - }) - ).then(function () { - return Array.prototype.concat.apply( - [], - arguments - ); - }); - }, - - _getDroppedFiles: function (dataTransfer) { - dataTransfer = dataTransfer || {}; - var items = dataTransfer.items; - if (items && items.length && (items[0].webkitGetAsEntry || - items[0].getAsEntry)) { - return this._handleFileTreeEntries( - $.map(items, function (item) { - var entry; - if (item.webkitGetAsEntry) { - entry = item.webkitGetAsEntry(); - if (entry) { - // Workaround for Chrome bug #149735: - entry._file = item.getAsFile(); - } - return entry; - } - return item.getAsEntry(); - }) - ); - } - return $.Deferred().resolve( - $.makeArray(dataTransfer.files) - ).promise(); - }, - - _getSingleFileInputFiles: function (fileInput) { - fileInput = $(fileInput); - var entries = fileInput.prop('webkitEntries') || - fileInput.prop('entries'), - files, - value; - if (entries && entries.length) { - return this._handleFileTreeEntries(entries); - } - files = $.makeArray(fileInput.prop('files')); - if (!files.length) { - value = fileInput.prop('value'); - if (!value) { - return $.Deferred().resolve([]).promise(); - } - // If the files property is not available, the browser does not - // support the File API and we add a pseudo File object with - // the input value as name with path information removed: - files = [{name: value.replace(/^.*\\/, '')}]; - } else if (files[0].name === undefined && files[0].fileName) { - // File normalization for Safari 4 and Firefox 3: - $.each(files, function (index, file) { - file.name = file.fileName; - file.size = file.fileSize; - }); - } - return $.Deferred().resolve(files).promise(); - }, - - _getFileInputFiles: function (fileInput) { - if (!(fileInput instanceof $) || fileInput.length === 1) { - return this._getSingleFileInputFiles(fileInput); - } - return $.when.apply( - $, - $.map(fileInput, this._getSingleFileInputFiles) - ).then(function () { - return Array.prototype.concat.apply( - [], - arguments - ); - }); - }, - - _onChange: function (e) { - var that = this, - data = { - fileInput: $(e.target), - form: $(e.target.form) - }; - this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; - if (that.options.replaceFileInput) { - that._replaceFileInput(data); - } - if (that._trigger( - 'change', - $.Event('change', {delegatedEvent: e}), - data - ) !== false) { - that._onAdd(e, data); - } - }); - }, - - _onPaste: function (e) { - var items = e.originalEvent && e.originalEvent.clipboardData && - e.originalEvent.clipboardData.items, - data = {files: []}; - if (items && items.length) { - $.each(items, function (index, item) { - var file = item.getAsFile && item.getAsFile(); - if (file) { - data.files.push(file); - } - }); - if (this._trigger( - 'paste', - $.Event('paste', {delegatedEvent: e}), - data - ) !== false) { - this._onAdd(e, data); - } - } - }, - - _onDrop: function (e) { - e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; - var that = this, - dataTransfer = e.dataTransfer, - data = {}; - if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { - e.preventDefault(); - this._getDroppedFiles(dataTransfer).always(function (files) { - data.files = files; - if (that._trigger( - 'drop', - $.Event('drop', {delegatedEvent: e}), - data - ) !== false) { - that._onAdd(e, data); - } - }); - } - }, - - _onDragOver: getDragHandler('dragover'), - - _onDragEnter: getDragHandler('dragenter'), - - _onDragLeave: getDragHandler('dragleave'), - - _initEventHandlers: function () { - if (this._isXHRUpload(this.options)) { - this._on(this.options.dropZone, { - dragover: this._onDragOver, - drop: this._onDrop, - // event.preventDefault() on dragenter is required for IE10+: - dragenter: this._onDragEnter, - // dragleave is not required, but added for completeness: - dragleave: this._onDragLeave - }); - this._on(this.options.pasteZone, { - paste: this._onPaste - }); - } - if ($.support.fileInput) { - this._on(this.options.fileInput, { - change: this._onChange - }); - } - }, - - _destroyEventHandlers: function () { - this._off(this.options.dropZone, 'dragenter dragleave dragover drop'); - this._off(this.options.pasteZone, 'paste'); - this._off(this.options.fileInput, 'change'); - }, - - _destroy: function () { - this._destroyEventHandlers(); - }, - - _setOption: function (key, value) { - var reinit = $.inArray(key, this._specialOptions) !== -1; - if (reinit) { - this._destroyEventHandlers(); - } - this._super(key, value); - if (reinit) { - this._initSpecialOptions(); - this._initEventHandlers(); - } - }, - - _initSpecialOptions: function () { - var options = this.options; - if (options.fileInput === undefined) { - options.fileInput = this.element.is('input[type="file"]') ? - this.element : this.element.find('input[type="file"]'); - } else if (!(options.fileInput instanceof $)) { - options.fileInput = $(options.fileInput); - } - if (!(options.dropZone instanceof $)) { - options.dropZone = $(options.dropZone); - } - if (!(options.pasteZone instanceof $)) { - options.pasteZone = $(options.pasteZone); - } - }, - - _getRegExp: function (str) { - var parts = str.split('/'), - modifiers = parts.pop(); - parts.shift(); - return new RegExp(parts.join('/'), modifiers); - }, - - _isRegExpOption: function (key, value) { - return key !== 'url' && $.type(value) === 'string' && - /^\/.*\/[igm]{0,3}$/.test(value); - }, - - _initDataAttributes: function () { - var that = this, - options = this.options, - data = this.element.data(); - // Initialize options set via HTML5 data-attributes: - $.each( - this.element[0].attributes, - function (index, attr) { - var key = attr.name.toLowerCase(), - value; - if (/^data-/.test(key)) { - // Convert hyphen-ated key to camelCase: - key = key.slice(5).replace(/-[a-z]/g, function (str) { - return str.charAt(1).toUpperCase(); - }); - value = data[key]; - if (that._isRegExpOption(key, value)) { - value = that._getRegExp(value); - } - options[key] = value; - } - } - ); - }, - - _create: function () { - this._initDataAttributes(); - this._initSpecialOptions(); - this._slots = []; - this._sequence = this._getXHRPromise(true); - this._sending = this._active = 0; - this._initProgressObject(this); - this._initEventHandlers(); - }, - - // This method is exposed to the widget API and allows to query - // the number of active uploads: - active: function () { - return this._active; - }, - - // This method is exposed to the widget API and allows to query - // the widget upload progress. - // It returns an object with loaded, total and bitrate properties - // for the running uploads: - progress: function () { - return this._progress; - }, - - // This method is exposed to the widget API and allows adding files - // using the fileupload API. The data parameter accepts an object which - // must have a files property and can contain additional options: - // .fileupload('add', {files: filesList}); - add: function (data) { - var that = this; - if (!data || this.options.disabled) { - return; - } - if (data.fileInput && !data.files) { - this._getFileInputFiles(data.fileInput).always(function (files) { - data.files = files; - that._onAdd(null, data); - }); - } else { - data.files = $.makeArray(data.files); - this._onAdd(null, data); - } - }, - - // This method is exposed to the widget API and allows sending files - // using the fileupload API. The data parameter accepts an object which - // must have a files or fileInput property and can contain additional options: - // .fileupload('send', {files: filesList}); - // The method returns a Promise object for the file upload call. - send: function (data) { - if (data && !this.options.disabled) { - if (data.fileInput && !data.files) { - var that = this, - dfd = $.Deferred(), - promise = dfd.promise(), - jqXHR, - aborted; - promise.abort = function () { - aborted = true; - if (jqXHR) { - return jqXHR.abort(); - } - dfd.reject(null, 'abort', 'abort'); - return promise; - }; - this._getFileInputFiles(data.fileInput).always( - function (files) { - if (aborted) { - return; - } - if (!files.length) { - dfd.reject(); - return; - } - data.files = files; - jqXHR = that._onSend(null, data); - jqXHR.then( - function (result, textStatus, jqXHR) { - dfd.resolve(result, textStatus, jqXHR); - }, - function (jqXHR, textStatus, errorThrown) { - dfd.reject(jqXHR, textStatus, errorThrown); - } - ); - } - ); - return this._enhancePromise(promise); - } - data.files = $.makeArray(data.files); - if (data.files.length) { - return this._onSend(null, data); - } - } - return this._getXHRPromise(false, data && data.context); - } - - }); - -})); diff --git a/library/blueimp_upload/js/jquery.iframe-transport.js b/library/blueimp_upload/js/jquery.iframe-transport.js deleted file mode 100644 index 8d25c4641..000000000 --- a/library/blueimp_upload/js/jquery.iframe-transport.js +++ /dev/null @@ -1,224 +0,0 @@ -/* - * jQuery Iframe Transport Plugin - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global define, require, window, document, JSON */ - -;(function (factory) { - 'use strict'; - if (typeof define === 'function' && define.amd) { - // Register as an anonymous AMD module: - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS: - factory(require('jquery')); - } else { - // Browser globals: - factory(window.jQuery); - } -}(function ($) { - 'use strict'; - - // Helper variable to create unique names for the transport iframes: - var counter = 0, - jsonAPI = $, - jsonParse = 'parseJSON'; - - if ('JSON' in window && 'parse' in JSON) { - jsonAPI = JSON; - jsonParse = 'parse'; - } - - // The iframe transport accepts four additional options: - // options.fileInput: a jQuery collection of file input fields - // options.paramName: the parameter name for the file form data, - // overrides the name property of the file input field(s), - // can be a string or an array of strings. - // options.formData: an array of objects with name and value properties, - // equivalent to the return data of .serializeArray(), e.g.: - // [{name: 'a', value: 1}, {name: 'b', value: 2}] - // options.initialIframeSrc: the URL of the initial iframe src, - // by default set to "javascript:false;" - $.ajaxTransport('iframe', function (options) { - if (options.async) { - // javascript:false as initial iframe src - // prevents warning popups on HTTPS in IE6: - /*jshint scripturl: true */ - var initialIframeSrc = options.initialIframeSrc || 'javascript:false;', - /*jshint scripturl: false */ - form, - iframe, - addParamChar; - return { - send: function (_, completeCallback) { - form = $('
'); - form.attr('accept-charset', options.formAcceptCharset); - addParamChar = /\?/.test(options.url) ? '&' : '?'; - // XDomainRequest only supports GET and POST: - if (options.type === 'DELETE') { - options.url = options.url + addParamChar + '_method=DELETE'; - options.type = 'POST'; - } else if (options.type === 'PUT') { - options.url = options.url + addParamChar + '_method=PUT'; - options.type = 'POST'; - } else if (options.type === 'PATCH') { - options.url = options.url + addParamChar + '_method=PATCH'; - options.type = 'POST'; - } - // IE versions below IE8 cannot set the name property of - // elements that have already been added to the DOM, - // so we set the name along with the iframe HTML markup: - counter += 1; - iframe = $( - '' - ).bind('load', function () { - var fileInputClones, - paramNames = $.isArray(options.paramName) ? - options.paramName : [options.paramName]; - iframe - .unbind('load') - .bind('load', function () { - var response; - // Wrap in a try/catch block to catch exceptions thrown - // when trying to access cross-domain iframe contents: - try { - response = iframe.contents(); - // Google Chrome and Firefox do not throw an - // exception when calling iframe.contents() on - // cross-domain requests, so we unify the response: - if (!response.length || !response[0].firstChild) { - throw new Error(); - } - } catch (e) { - response = undefined; - } - // The complete callback returns the - // iframe content document as response object: - completeCallback( - 200, - 'success', - {'iframe': response} - ); - // Fix for IE endless progress bar activity bug - // (happens on form submits to iframe targets): - $('') - .appendTo(form); - window.setTimeout(function () { - // Removing the form in a setTimeout call - // allows Chrome's developer tools to display - // the response result - form.remove(); - }, 0); - }); - form - .prop('target', iframe.prop('name')) - .prop('action', options.url) - .prop('method', options.type); - if (options.formData) { - $.each(options.formData, function (index, field) { - $('') - .prop('name', field.name) - .val(field.value) - .appendTo(form); - }); - } - if (options.fileInput && options.fileInput.length && - options.type === 'POST') { - fileInputClones = options.fileInput.clone(); - // Insert a clone for each file input field: - options.fileInput.after(function (index) { - return fileInputClones[index]; - }); - if (options.paramName) { - options.fileInput.each(function (index) { - $(this).prop( - 'name', - paramNames[index] || options.paramName - ); - }); - } - // Appending the file input fields to the hidden form - // removes them from their original location: - form - .append(options.fileInput) - .prop('enctype', 'multipart/form-data') - // enctype must be set as encoding for IE: - .prop('encoding', 'multipart/form-data'); - // Remove the HTML5 form attribute from the input(s): - options.fileInput.removeAttr('form'); - } - form.submit(); - // Insert the file input fields at their original location - // by replacing the clones with the originals: - if (fileInputClones && fileInputClones.length) { - options.fileInput.each(function (index, input) { - var clone = $(fileInputClones[index]); - // Restore the original name and form properties: - $(input) - .prop('name', clone.prop('name')) - .attr('form', clone.attr('form')); - clone.replaceWith(input); - }); - } - }); - form.append(iframe).appendTo(document.body); - }, - abort: function () { - if (iframe) { - // javascript:false as iframe src aborts the request - // and prevents warning popups on HTTPS in IE6. - // concat is used to avoid the "Script URL" JSLint error: - iframe - .unbind('load') - .prop('src', initialIframeSrc); - } - if (form) { - form.remove(); - } - } - }; - } - }); - - // The iframe transport returns the iframe content document as response. - // The following adds converters from iframe to text, json, html, xml - // and script. - // Please note that the Content-Type for JSON responses has to be text/plain - // or text/html, if the browser doesn't include application/json in the - // Accept header, else IE will show a download dialog. - // The Content-Type for XML responses on the other hand has to be always - // application/xml or text/xml, so IE properly parses the XML response. - // See also - // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation - $.ajaxSetup({ - converters: { - 'iframe text': function (iframe) { - return iframe && $(iframe[0].body).text(); - }, - 'iframe json': function (iframe) { - return iframe && jsonAPI[jsonParse]($(iframe[0].body).text()); - }, - 'iframe html': function (iframe) { - return iframe && $(iframe[0].body).html(); - }, - 'iframe xml': function (iframe) { - var xmlDoc = iframe && iframe[0]; - return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : - $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || - $(xmlDoc.body).html()); - }, - 'iframe script': function (iframe) { - return iframe && $.globalEval($(iframe[0].body).text()); - } - } - }); - -})); diff --git a/library/blueimp_upload/js/main.js b/library/blueimp_upload/js/main.js deleted file mode 100644 index 0403682e7..000000000 --- a/library/blueimp_upload/js/main.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * jQuery File Upload Plugin JS Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global $, window */ - -$(function () { - 'use strict'; - - // Initialize the jQuery File Upload widget: - $('#fileupload').fileupload({ - // Uncomment the following to send cross-domain cookies: - //xhrFields: {withCredentials: true}, - url: 'server/php/' - }); - - // Enable iframe cross-domain access via redirect option: - $('#fileupload').fileupload( - 'option', - 'redirect', - window.location.href.replace( - /\/[^\/]*$/, - '/cors/result.html?%s' - ) - ); - - if (window.location.hostname === 'blueimp.github.io') { - // Demo settings: - $('#fileupload').fileupload('option', { - url: '//jquery-file-upload.appspot.com/', - // Enable image resizing, except for Android and Opera, - // which actually support image resizing, but fail to - // send Blob objects via XHR requests: - disableImageResize: /Android(?!.*Chrome)|Opera/ - .test(window.navigator.userAgent), - maxFileSize: 999000, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i - }); - // Upload server status check for browsers with CORS support: - if ($.support.cors) { - $.ajax({ - url: '//jquery-file-upload.appspot.com/', - type: 'HEAD' - }).fail(function () { - $('
') - .text('Upload server currently unavailable - ' + - new Date()) - .appendTo('#fileupload'); - }); - } - } else { - // Load existing files: - $('#fileupload').addClass('fileupload-processing'); - $.ajax({ - // Uncomment the following to send cross-domain cookies: - //xhrFields: {withCredentials: true}, - url: $('#fileupload').fileupload('option', 'url'), - dataType: 'json', - context: $('#fileupload')[0] - }).always(function () { - $(this).removeClass('fileupload-processing'); - }).done(function (result) { - $(this).fileupload('option', 'done') - .call(this, $.Event('done'), {result: result}); - }); - } - -}); diff --git a/library/blueimp_upload/js/vendor/jquery.ui.widget.js b/library/blueimp_upload/js/vendor/jquery.ui.widget.js deleted file mode 100644 index 914b8ffb8..000000000 --- a/library/blueimp_upload/js/vendor/jquery.ui.widget.js +++ /dev/null @@ -1,752 +0,0 @@ -/*! jQuery UI - v1.12.1+CommonJS - 2018-02-10 - * http://jqueryui.com - * Includes: widget.js - * Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define([ "jquery" ], factory ); - } else if ( typeof exports === "object" ) { - - // Node/CommonJS - factory( require( "jquery" ) ); - } else { - - // Browser globals - factory( jQuery ); - } -}(function( $ ) { - - $.ui = $.ui || {}; - - var version = $.ui.version = "1.12.1"; - - - /*! - * jQuery UI Widget 1.12.1 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - */ - - //>>label: Widget - //>>group: Core - //>>description: Provides a factory for creating stateful widgets with a common API. - //>>docs: http://api.jqueryui.com/jQuery.widget/ - //>>demos: http://jqueryui.com/widget/ - - - - var widgetUuid = 0; - var widgetSlice = Array.prototype.slice; - - $.cleanData = ( function( orig ) { - return function( elems ) { - var events, elem, i; - for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { - try { - - // Only trigger remove when necessary to save time - events = $._data( elem, "events" ); - if ( events && events.remove ) { - $( elem ).triggerHandler( "remove" ); - } - - // Http://bugs.jquery.com/ticket/8235 - } catch ( e ) {} - } - orig( elems ); - }; - } )( $.cleanData ); - - $.widget = function( name, base, prototype ) { - var existingConstructor, constructor, basePrototype; - - // ProxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - var proxiedPrototype = {}; - - var namespace = name.split( "." )[ 0 ]; - name = name.split( "." )[ 1 ]; - var fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - if ( $.isArray( prototype ) ) { - prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); - } - - // Create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - - // Allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // Allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - - // Extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - - // Copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - - // Track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - } ); - - basePrototype = new base(); - - // We need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = ( function() { - function _super() { - return base.prototype[ prop ].apply( this, arguments ); - } - - function _superApply( args ) { - return base.prototype[ prop ].apply( this, args ); - } - - return function() { - var __super = this._super; - var __superApply = this._superApply; - var returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - } )(); - } ); - constructor.prototype = $.widget.extend( basePrototype, { - - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - } ); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // Redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, - child._proto ); - } ); - - // Remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); - - return constructor; - }; - - $.widget.extend = function( target ) { - var input = widgetSlice.call( arguments, 1 ); - var inputIndex = 0; - var inputLength = input.length; - var key; - var value; - - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; - }; - - $.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string"; - var args = widgetSlice.call( arguments, 1 ); - var returnValue = this; - - if ( isMethodCall ) { - - // If this is an empty collection, we need to have the instance method - // return undefined instead of the jQuery instance - if ( !this.length && options === "instance" ) { - returnValue = undefined; - } else { - this.each( function() { - var methodValue; - var instance = $.data( this, fullName ); - - if ( options === "instance" ) { - returnValue = instance; - return false; - } - - if ( !instance ) { - return $.error( "cannot call methods on " + name + - " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - - if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + - " widget instance" ); - } - - methodValue = instance[ options ].apply( instance, args ); - - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - } ); - } - } else { - - // Allow multiple hashes to be passed on init - if ( args.length ) { - options = $.widget.extend.apply( null, [ options ].concat( args ) ); - } - - this.each( function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} ); - if ( instance._init ) { - instance._init(); - } - } else { - $.data( this, fullName, new object( options, this ) ); - } - } ); - } - - return returnValue; - }; - }; - - $.Widget = function( /* options, element */ ) {}; - $.Widget._childConstructors = []; - - $.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
", - - options: { - classes: {}, - disabled: false, - - // Callbacks - create: null - }, - - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = widgetUuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - this.classesElementLookup = {}; - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - } ); - this.document = $( element.style ? - - // Element within the document - element.ownerDocument : - - // Element is window or document - element.document || element ); - this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); - } - - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this._create(); - - if ( this.options.disabled ) { - this._setOptionDisabled( this.options.disabled ); - } - - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - - _getCreateOptions: function() { - return {}; - }, - - _getCreateEventData: $.noop, - - _create: $.noop, - - _init: $.noop, - - destroy: function() { - var that = this; - - this._destroy(); - $.each( this.classesElementLookup, function( key, value ) { - that._removeClass( value, key ); - } ); - - // We can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .off( this.eventNamespace ) - .removeData( this.widgetFullName ); - this.widget() - .off( this.eventNamespace ) - .removeAttr( "aria-disabled" ); - - // Clean up events and states - this.bindings.off( this.eventNamespace ); - }, - - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key; - var parts; - var curOption; - var i; - - if ( arguments.length === 0 ) { - - // Don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - - // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( arguments.length === 1 ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( arguments.length === 1 ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - - _setOption: function( key, value ) { - if ( key === "classes" ) { - this._setOptionClasses( value ); - } - - this.options[ key ] = value; - - if ( key === "disabled" ) { - this._setOptionDisabled( value ); - } - - return this; - }, - - _setOptionClasses: function( value ) { - var classKey, elements, currentElements; - - for ( classKey in value ) { - currentElements = this.classesElementLookup[ classKey ]; - if ( value[ classKey ] === this.options.classes[ classKey ] || - !currentElements || - !currentElements.length ) { - continue; - } - - // We are doing this to create a new jQuery object because the _removeClass() call - // on the next line is going to destroy the reference to the current elements being - // tracked. We need to save a copy of this collection so that we can add the new classes - // below. - elements = $( currentElements.get() ); - this._removeClass( currentElements, classKey ); - - // We don't use _addClass() here, because that uses this.options.classes - // for generating the string of classes. We want to use the value passed in from - // _setOption(), this is the new value of the classes option which was passed to - // _setOption(). We pass this value directly to _classes(). - elements.addClass( this._classes( { - element: elements, - keys: classKey, - classes: value, - add: true - } ) ); - } - }, - - _setOptionDisabled: function( value ) { - this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); - - // If the widget is becoming disabled, then nothing is interactive - if ( value ) { - this._removeClass( this.hoverable, null, "ui-state-hover" ); - this._removeClass( this.focusable, null, "ui-state-focus" ); - } - }, - - enable: function() { - return this._setOptions( { disabled: false } ); - }, - - disable: function() { - return this._setOptions( { disabled: true } ); - }, - - _classes: function( options ) { - var full = []; - var that = this; - - options = $.extend( { - element: this.element, - classes: this.options.classes || {} - }, options ); - - function processClassString( classes, checkOption ) { - var current, i; - for ( i = 0; i < classes.length; i++ ) { - current = that.classesElementLookup[ classes[ i ] ] || $(); - if ( options.add ) { - current = $( $.unique( current.get().concat( options.element.get() ) ) ); - } else { - current = $( current.not( options.element ).get() ); - } - that.classesElementLookup[ classes[ i ] ] = current; - full.push( classes[ i ] ); - if ( checkOption && options.classes[ classes[ i ] ] ) { - full.push( options.classes[ classes[ i ] ] ); - } - } - } - - this._on( options.element, { - "remove": "_untrackClassesElement" - } ); - - if ( options.keys ) { - processClassString( options.keys.match( /\S+/g ) || [], true ); - } - if ( options.extra ) { - processClassString( options.extra.match( /\S+/g ) || [] ); - } - - return full.join( " " ); - }, - - _untrackClassesElement: function( event ) { - var that = this; - $.each( that.classesElementLookup, function( key, value ) { - if ( $.inArray( event.target, value ) !== -1 ) { - that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); - } - } ); - }, - - _removeClass: function( element, keys, extra ) { - return this._toggleClass( element, keys, extra, false ); - }, - - _addClass: function( element, keys, extra ) { - return this._toggleClass( element, keys, extra, true ); - }, - - _toggleClass: function( element, keys, extra, add ) { - add = ( typeof add === "boolean" ) ? add : extra; - var shift = ( typeof element === "string" || element === null ), - options = { - extra: shift ? keys : extra, - keys: shift ? element : keys, - element: shift ? this.element : element, - add: add - }; - options.element.toggleClass( this._classes( options ), add ); - return this; - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement; - var instance = this; - - // No suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // No element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - - // Allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // Copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^([\w:-]*)\s*(.*)$/ ); - var eventName = match[ 1 ] + instance.eventNamespace; - var selector = match[ 2 ]; - - if ( selector ) { - delegateElement.on( eventName, selector, handlerProxy ); - } else { - element.on( eventName, handlerProxy ); - } - } ); - }, - - _off: function( element, eventName ) { - eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + - this.eventNamespace; - element.off( eventName ).off( eventName ); - - // Clear the stack to avoid memory leaks (#10056) - this.bindings = $( this.bindings.not( element ).get() ); - this.focusable = $( this.focusable.not( element ).get() ); - this.hoverable = $( this.hoverable.not( element ).get() ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); - }, - mouseleave: function( event ) { - this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); - } - } ); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); - }, - focusout: function( event ) { - this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); - } - } ); - }, - - _trigger: function( type, event, data ) { - var prop, orig; - var callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - - // The original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // Copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } - }; - - $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - - var hasOptions; - var effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - - if ( options.delay ) { - element.delay( options.delay ); - } - - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue( function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - } ); - } - }; - } ); - - var widget = $.widget; - - - - -})); diff --git a/library/blueimp_upload/package.json b/library/blueimp_upload/package.json deleted file mode 100644 index 4801d7913..000000000 --- a/library/blueimp_upload/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "blueimp-file-upload", - "version": "9.23.0", - "title": "jQuery File Upload", - "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.", - "keywords": [ - "jquery", - "file", - "upload", - "widget", - "multiple", - "selection", - "drag", - "drop", - "progress", - "preview", - "cross-domain", - "cross-site", - "chunk", - "resume", - "gae", - "go", - "python", - "php", - "bootstrap" - ], - "homepage": "https://github.com/blueimp/jQuery-File-Upload", - "author": { - "name": "Sebastian Tschan", - "url": "https://blueimp.net" - }, - "repository": { - "type": "git", - "url": "git://github.com/blueimp/jQuery-File-Upload.git" - }, - "license": "MIT", - "optionalDependencies": { - "blueimp-canvas-to-blob": "3.5.0", - "blueimp-load-image": "2.12.2", - "blueimp-tmpl": "3.6.0" - }, - "devDependencies": { - "bower-json": "0.8.1", - "jshint": "2.9.3" - }, - "scripts": { - "bower-version-update": "./bower-version-update.js", - "lint": "jshint *.js js/*.js js/cors/*.js", - "test": "npm run lint", - "preversion": "npm test", - "version": "npm run bower-version-update && git add bower.json", - "postversion": "git push --tags origin master && npm publish" - }, - "main": "js/jquery.fileupload.js" -} diff --git a/library/blueimp_upload/server/gae-go/app.yaml b/library/blueimp_upload/server/gae-go/app.yaml deleted file mode 100644 index 2d09daa56..000000000 --- a/library/blueimp_upload/server/gae-go/app.yaml +++ /dev/null @@ -1,12 +0,0 @@ -application: jquery-file-upload -version: 2 -runtime: go -api_version: go1 - -handlers: -- url: /(favicon\.ico|robots\.txt) - static_files: static/\1 - upload: static/(.*) - expiration: '1d' -- url: /.* - script: _go_app diff --git a/library/blueimp_upload/server/gae-go/app/main.go b/library/blueimp_upload/server/gae-go/app/main.go deleted file mode 100644 index a92d128c0..000000000 --- a/library/blueimp_upload/server/gae-go/app/main.go +++ /dev/null @@ -1,361 +0,0 @@ -/* - * jQuery File Upload Plugin GAE Go Example - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -package app - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "github.com/disintegration/gift" - "golang.org/x/net/context" - "google.golang.org/appengine" - "google.golang.org/appengine/memcache" - "hash/crc32" - "image" - "image/gif" - "image/jpeg" - "image/png" - "io" - "log" - "mime/multipart" - "net/http" - "net/url" - "path/filepath" - "regexp" - "strings" -) - -const ( - WEBSITE = "https://blueimp.github.io/jQuery-File-Upload/" - MIN_FILE_SIZE = 1 // bytes - // Max file size is memcache limit (1MB) minus key size minus overhead: - MAX_FILE_SIZE = 999000 // bytes - IMAGE_TYPES = "image/(gif|p?jpeg|(x-)?png)" - ACCEPT_FILE_TYPES = IMAGE_TYPES - THUMB_MAX_WIDTH = 80 - THUMB_MAX_HEIGHT = 80 - EXPIRATION_TIME = 300 // seconds - // If empty, only allow redirects to the referer protocol+host. - // Set to a regexp string for custom pattern matching: - REDIRECT_ALLOW_TARGET = "" -) - -var ( - imageTypes = regexp.MustCompile(IMAGE_TYPES) - acceptFileTypes = regexp.MustCompile(ACCEPT_FILE_TYPES) - thumbSuffix = "." + fmt.Sprint(THUMB_MAX_WIDTH) + "x" + - fmt.Sprint(THUMB_MAX_HEIGHT) -) - -func escape(s string) string { - return strings.Replace(url.QueryEscape(s), "+", "%20", -1) -} - -func extractKey(r *http.Request) string { - // Use RequestURI instead of r.URL.Path, as we need the encoded form: - path := strings.Split(r.RequestURI, "?")[0] - // Also adjust double encoded slashes: - return strings.Replace(path[1:], "%252F", "%2F", -1) -} - -func check(err error) { - if err != nil { - panic(err) - } -} - -type FileInfo struct { - Key string `json:"-"` - ThumbnailKey string `json:"-"` - Url string `json:"url,omitempty"` - ThumbnailUrl string `json:"thumbnailUrl,omitempty"` - Name string `json:"name"` - Type string `json:"type"` - Size int64 `json:"size"` - Error string `json:"error,omitempty"` - DeleteUrl string `json:"deleteUrl,omitempty"` - DeleteType string `json:"deleteType,omitempty"` -} - -func (fi *FileInfo) ValidateType() (valid bool) { - if acceptFileTypes.MatchString(fi.Type) { - return true - } - fi.Error = "Filetype not allowed" - return false -} - -func (fi *FileInfo) ValidateSize() (valid bool) { - if fi.Size < MIN_FILE_SIZE { - fi.Error = "File is too small" - } else if fi.Size > MAX_FILE_SIZE { - fi.Error = "File is too big" - } else { - return true - } - return false -} - -func (fi *FileInfo) CreateUrls(r *http.Request, c context.Context) { - u := &url.URL{ - Scheme: r.URL.Scheme, - Host: appengine.DefaultVersionHostname(c), - Path: "/", - } - uString := u.String() - fi.Url = uString + fi.Key - fi.DeleteUrl = fi.Url - fi.DeleteType = "DELETE" - if fi.ThumbnailKey != "" { - fi.ThumbnailUrl = uString + fi.ThumbnailKey - } -} - -func (fi *FileInfo) SetKey(checksum uint32) { - fi.Key = escape(string(fi.Type)) + "/" + - escape(fmt.Sprint(checksum)) + "/" + - escape(string(fi.Name)) -} - -func (fi *FileInfo) createThumb(buffer *bytes.Buffer, c context.Context) { - if imageTypes.MatchString(fi.Type) { - src, _, err := image.Decode(bytes.NewReader(buffer.Bytes())) - check(err) - filter := gift.New(gift.ResizeToFit( - THUMB_MAX_WIDTH, - THUMB_MAX_HEIGHT, - gift.LanczosResampling, - )) - dst := image.NewNRGBA(filter.Bounds(src.Bounds())) - filter.Draw(dst, src) - buffer.Reset() - bWriter := bufio.NewWriter(buffer) - switch fi.Type { - case "image/jpeg", "image/pjpeg": - err = jpeg.Encode(bWriter, dst, nil) - case "image/gif": - err = gif.Encode(bWriter, dst, nil) - default: - err = png.Encode(bWriter, dst) - } - check(err) - bWriter.Flush() - thumbnailKey := fi.Key + thumbSuffix + filepath.Ext(fi.Name) - item := &memcache.Item{ - Key: thumbnailKey, - Value: buffer.Bytes(), - } - err = memcache.Set(c, item) - check(err) - fi.ThumbnailKey = thumbnailKey - } -} - -func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) { - fi = &FileInfo{ - Name: p.FileName(), - Type: p.Header.Get("Content-Type"), - } - if !fi.ValidateType() { - return - } - defer func() { - if rec := recover(); rec != nil { - log.Println(rec) - fi.Error = rec.(error).Error() - } - }() - var buffer bytes.Buffer - hash := crc32.NewIEEE() - mw := io.MultiWriter(&buffer, hash) - lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1} - _, err := io.Copy(mw, lr) - check(err) - fi.Size = MAX_FILE_SIZE + 1 - lr.N - if !fi.ValidateSize() { - return - } - fi.SetKey(hash.Sum32()) - item := &memcache.Item{ - Key: fi.Key, - Value: buffer.Bytes(), - } - context := appengine.NewContext(r) - err = memcache.Set(context, item) - check(err) - fi.createThumb(&buffer, context) - fi.CreateUrls(r, context) - return -} - -func getFormValue(p *multipart.Part) string { - var b bytes.Buffer - io.CopyN(&b, p, int64(1<<20)) // Copy max: 1 MiB - return b.String() -} - -func handleUploads(r *http.Request) (fileInfos []*FileInfo) { - fileInfos = make([]*FileInfo, 0) - mr, err := r.MultipartReader() - check(err) - r.Form, err = url.ParseQuery(r.URL.RawQuery) - check(err) - part, err := mr.NextPart() - for err == nil { - if name := part.FormName(); name != "" { - if part.FileName() != "" { - fileInfos = append(fileInfos, handleUpload(r, part)) - } else { - r.Form[name] = append(r.Form[name], getFormValue(part)) - } - } - part, err = mr.NextPart() - } - return -} - -func validateRedirect(r *http.Request, redirect string) bool { - if redirect != "" { - var redirectAllowTarget *regexp.Regexp - if REDIRECT_ALLOW_TARGET != "" { - redirectAllowTarget = regexp.MustCompile(REDIRECT_ALLOW_TARGET) - } else { - referer := r.Referer() - if referer == "" { - return false - } - refererUrl, err := url.Parse(referer) - if err != nil { - return false - } - redirectAllowTarget = regexp.MustCompile("^" + regexp.QuoteMeta( - refererUrl.Scheme+"://"+refererUrl.Host+"/", - )) - } - return redirectAllowTarget.MatchString(redirect) - } - return false -} - -func get(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/" { - http.Redirect(w, r, WEBSITE, http.StatusFound) - return - } - // Use RequestURI instead of r.URL.Path, as we need the encoded form: - key := extractKey(r) - parts := strings.Split(key, "/") - if len(parts) == 3 { - context := appengine.NewContext(r) - item, err := memcache.Get(context, key) - if err == nil { - w.Header().Add("X-Content-Type-Options", "nosniff") - contentType, _ := url.QueryUnescape(parts[0]) - if !imageTypes.MatchString(contentType) { - contentType = "application/octet-stream" - } - w.Header().Add("Content-Type", contentType) - w.Header().Add( - "Cache-Control", - fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), - ) - w.Write(item.Value) - return - } - } - http.Error(w, "404 Not Found", http.StatusNotFound) -} - -func post(w http.ResponseWriter, r *http.Request) { - result := make(map[string][]*FileInfo, 1) - result["files"] = handleUploads(r) - b, err := json.Marshal(result) - check(err) - if redirect := r.FormValue("redirect"); validateRedirect(r, redirect) { - if strings.Contains(redirect, "%s") { - redirect = fmt.Sprintf( - redirect, - escape(string(b)), - ) - } - http.Redirect(w, r, redirect, http.StatusFound) - return - } - w.Header().Set("Cache-Control", "no-cache") - jsonType := "application/json" - if strings.Index(r.Header.Get("Accept"), jsonType) != -1 { - w.Header().Set("Content-Type", jsonType) - } - fmt.Fprintln(w, string(b)) -} - -func delete(w http.ResponseWriter, r *http.Request) { - key := extractKey(r) - parts := strings.Split(key, "/") - if len(parts) == 3 { - result := make(map[string]bool, 1) - context := appengine.NewContext(r) - err := memcache.Delete(context, key) - if err == nil { - result[key] = true - contentType, _ := url.QueryUnescape(parts[0]) - if imageTypes.MatchString(contentType) { - thumbnailKey := key + thumbSuffix + filepath.Ext(parts[2]) - err := memcache.Delete(context, thumbnailKey) - if err == nil { - result[thumbnailKey] = true - } - } - } - w.Header().Set("Content-Type", "application/json") - b, err := json.Marshal(result) - check(err) - fmt.Fprintln(w, string(b)) - } else { - http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed) - } -} - -func handle(w http.ResponseWriter, r *http.Request) { - params, err := url.ParseQuery(r.URL.RawQuery) - check(err) - w.Header().Add("Access-Control-Allow-Origin", "*") - w.Header().Add( - "Access-Control-Allow-Methods", - "OPTIONS, HEAD, GET, POST, DELETE", - ) - w.Header().Add( - "Access-Control-Allow-Headers", - "Content-Type, Content-Range, Content-Disposition", - ) - switch r.Method { - case "OPTIONS", "HEAD": - return - case "GET": - get(w, r) - case "POST": - if len(params["_method"]) > 0 && params["_method"][0] == "DELETE" { - delete(w, r) - } else { - post(w, r) - } - case "DELETE": - delete(w, r) - default: - http.Error(w, "501 Not Implemented", http.StatusNotImplemented) - } -} - -func init() { - http.HandleFunc("/", handle) -} diff --git a/library/blueimp_upload/server/gae-go/static/robots.txt b/library/blueimp_upload/server/gae-go/static/robots.txt deleted file mode 100644 index eb0536286..000000000 --- a/library/blueimp_upload/server/gae-go/static/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/library/blueimp_upload/server/gae-python/app.yaml b/library/blueimp_upload/server/gae-python/app.yaml deleted file mode 100644 index 764449b74..000000000 --- a/library/blueimp_upload/server/gae-python/app.yaml +++ /dev/null @@ -1,17 +0,0 @@ -application: jquery-file-upload -version: 1 -runtime: python27 -api_version: 1 -threadsafe: true - -libraries: -- name: PIL - version: latest - -handlers: -- url: /(favicon\.ico|robots\.txt) - static_files: static/\1 - upload: static/(.*) - expiration: '1d' -- url: /.* - script: main.app diff --git a/library/blueimp_upload/server/gae-python/main.py b/library/blueimp_upload/server/gae-python/main.py deleted file mode 100644 index 1955ac00a..000000000 --- a/library/blueimp_upload/server/gae-python/main.py +++ /dev/null @@ -1,204 +0,0 @@ -# -*- coding: utf-8 -*- -# -# jQuery File Upload Plugin GAE Python Example -# https://github.com/blueimp/jQuery-File-Upload -# -# Copyright 2011, Sebastian Tschan -# https://blueimp.net -# -# Licensed under the MIT license: -# https://opensource.org/licenses/MIT -# - -from google.appengine.api import memcache, images -import json -import os -import re -import urllib -import webapp2 - -DEBUG=os.environ.get('SERVER_SOFTWARE', '').startswith('Dev') -WEBSITE = 'https://blueimp.github.io/jQuery-File-Upload/' -MIN_FILE_SIZE = 1 # bytes -# Max file size is memcache limit (1MB) minus key size minus overhead: -MAX_FILE_SIZE = 999000 # bytes -IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') -ACCEPT_FILE_TYPES = IMAGE_TYPES -THUMB_MAX_WIDTH = 80 -THUMB_MAX_HEIGHT = 80 -THUMB_SUFFIX = '.'+str(THUMB_MAX_WIDTH)+'x'+str(THUMB_MAX_HEIGHT)+'.png' -EXPIRATION_TIME = 300 # seconds -# If set to None, only allow redirects to the referer protocol+host. -# Set to a regexp for custom pattern matching against the redirect value: -REDIRECT_ALLOW_TARGET = None - -class CORSHandler(webapp2.RequestHandler): - def cors(self): - headers = self.response.headers - headers['Access-Control-Allow-Origin'] = '*' - headers['Access-Control-Allow-Methods'] =\ - 'OPTIONS, HEAD, GET, POST, DELETE' - headers['Access-Control-Allow-Headers'] =\ - 'Content-Type, Content-Range, Content-Disposition' - - def initialize(self, request, response): - super(CORSHandler, self).initialize(request, response) - self.cors() - - def json_stringify(self, obj): - return json.dumps(obj, separators=(',', ':')) - - def options(self, *args, **kwargs): - pass - -class UploadHandler(CORSHandler): - def validate(self, file): - if file['size'] < MIN_FILE_SIZE: - file['error'] = 'File is too small' - elif file['size'] > MAX_FILE_SIZE: - file['error'] = 'File is too big' - elif not ACCEPT_FILE_TYPES.match(file['type']): - file['error'] = 'Filetype not allowed' - else: - return True - return False - - def validate_redirect(self, redirect): - if redirect: - if REDIRECT_ALLOW_TARGET: - return REDIRECT_ALLOW_TARGET.match(redirect) - referer = self.request.headers['referer'] - if referer: - from urlparse import urlparse - parts = urlparse(referer) - redirect_allow_target = '^' + re.escape( - parts.scheme + '://' + parts.netloc + '/' - ) - return re.match(redirect_allow_target, redirect) - return False - - def get_file_size(self, file): - file.seek(0, 2) # Seek to the end of the file - size = file.tell() # Get the position of EOF - file.seek(0) # Reset the file position to the beginning - return size - - def write_blob(self, data, info): - key = urllib.quote(info['type'].encode('utf-8'), '') +\ - '/' + str(hash(data)) +\ - '/' + urllib.quote(info['name'].encode('utf-8'), '') - try: - memcache.set(key, data, time=EXPIRATION_TIME) - except: #Failed to add to memcache - return (None, None) - thumbnail_key = None - if IMAGE_TYPES.match(info['type']): - try: - img = images.Image(image_data=data) - img.resize( - width=THUMB_MAX_WIDTH, - height=THUMB_MAX_HEIGHT - ) - thumbnail_data = img.execute_transforms() - thumbnail_key = key + THUMB_SUFFIX - memcache.set( - thumbnail_key, - thumbnail_data, - time=EXPIRATION_TIME - ) - except: #Failed to resize Image or add to memcache - thumbnail_key = None - return (key, thumbnail_key) - - def handle_upload(self): - results = [] - for name, fieldStorage in self.request.POST.items(): - if type(fieldStorage) is unicode: - continue - result = {} - result['name'] = urllib.unquote(fieldStorage.filename) - result['type'] = fieldStorage.type - result['size'] = self.get_file_size(fieldStorage.file) - if self.validate(result): - key, thumbnail_key = self.write_blob( - fieldStorage.value, - result - ) - if key is not None: - result['url'] = self.request.host_url + '/' + key - result['deleteUrl'] = result['url'] - result['deleteType'] = 'DELETE' - if thumbnail_key is not None: - result['thumbnailUrl'] = self.request.host_url +\ - '/' + thumbnail_key - else: - result['error'] = 'Failed to store uploaded file.' - results.append(result) - return results - - def head(self): - pass - - def get(self): - self.redirect(WEBSITE) - - def post(self): - if (self.request.get('_method') == 'DELETE'): - return self.delete() - result = {'files': self.handle_upload()} - s = self.json_stringify(result) - redirect = self.request.get('redirect') - if self.validate_redirect(redirect): - return self.redirect(str( - redirect.replace('%s', urllib.quote(s, ''), 1) - )) - if 'application/json' in self.request.headers.get('Accept'): - self.response.headers['Content-Type'] = 'application/json' - self.response.write(s) - -class FileHandler(CORSHandler): - def normalize(self, str): - return urllib.quote(urllib.unquote(str), '') - - def get(self, content_type, data_hash, file_name): - content_type = self.normalize(content_type) - file_name = self.normalize(file_name) - key = content_type + '/' + data_hash + '/' + file_name - data = memcache.get(key) - if data is None: - return self.error(404) - # Prevent browsers from MIME-sniffing the content-type: - self.response.headers['X-Content-Type-Options'] = 'nosniff' - content_type = urllib.unquote(content_type) - if not IMAGE_TYPES.match(content_type): - # Force a download dialog for non-image types: - content_type = 'application/octet-stream' - elif file_name.endswith(THUMB_SUFFIX): - content_type = 'image/png' - self.response.headers['Content-Type'] = content_type - # Cache for the expiration time: - self.response.headers['Cache-Control'] = 'public,max-age=%d' \ - % EXPIRATION_TIME - self.response.write(data) - - def delete(self, content_type, data_hash, file_name): - content_type = self.normalize(content_type) - file_name = self.normalize(file_name) - key = content_type + '/' + data_hash + '/' + file_name - result = {key: memcache.delete(key)} - content_type = urllib.unquote(content_type) - if IMAGE_TYPES.match(content_type): - thumbnail_key = key + THUMB_SUFFIX - result[thumbnail_key] = memcache.delete(thumbnail_key) - if 'application/json' in self.request.headers.get('Accept'): - self.response.headers['Content-Type'] = 'application/json' - s = self.json_stringify(result) - self.response.write(s) - -app = webapp2.WSGIApplication( - [ - ('/', UploadHandler), - ('/(.+)/([^/]+)/([^/]+)', FileHandler) - ], - debug=DEBUG -) diff --git a/library/blueimp_upload/server/gae-python/static/robots.txt b/library/blueimp_upload/server/gae-python/static/robots.txt deleted file mode 100644 index eb0536286..000000000 --- a/library/blueimp_upload/server/gae-python/static/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/library/blueimp_upload/server/php/Dockerfile b/library/blueimp_upload/server/php/Dockerfile deleted file mode 100644 index 8633fee74..000000000 --- a/library/blueimp_upload/server/php/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -FROM php:7-apache - -# Enable the Apache Headers module: -RUN ln -s /etc/apache2/mods-available/headers.load \ - /etc/apache2/mods-enabled/headers.load - -# Enable the Apache Rewrite module: -RUN ln -s /etc/apache2/mods-available/rewrite.load \ - /etc/apache2/mods-enabled/rewrite.load - -# Install GD, Imagick and ImageMagick as image conversion options: -RUN DEBIAN_FRONTEND=noninteractive \ - apt-get update && apt-get install -y --no-install-recommends \ - libpng-dev \ - libjpeg-dev \ - libmagickwand-dev \ - imagemagick \ - && pecl install \ - imagick \ - && docker-php-ext-enable \ - imagick \ - && docker-php-ext-configure \ - gd --with-jpeg-dir=/usr/include/ \ - && docker-php-ext-install \ - gd \ - # Uninstall obsolete packages: - && apt-get autoremove -y \ - libpng-dev \ - libjpeg-dev \ - libmagickwand-dev \ - # Remove obsolete files: - && apt-get clean \ - && rm -rf \ - /tmp/* \ - /usr/share/doc/* \ - /var/cache/* \ - /var/lib/apt/lists/* \ - /var/tmp/* diff --git a/library/blueimp_upload/server/php/UploadHandler.php b/library/blueimp_upload/server/php/UploadHandler.php deleted file mode 100755 index 285d046aa..000000000 --- a/library/blueimp_upload/server/php/UploadHandler.php +++ /dev/null @@ -1,1411 +0,0 @@ - 'The uploaded file exceeds the upload_max_filesize directive in php.ini', - 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', - 3 => 'The uploaded file was only partially uploaded', - 4 => 'No file was uploaded', - 6 => 'Missing a temporary folder', - 7 => 'Failed to write file to disk', - 8 => 'A PHP extension stopped the file upload', - 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini', - 'max_file_size' => 'File is too big', - 'min_file_size' => 'File is too small', - 'accept_file_types' => 'Filetype not allowed', - 'max_number_of_files' => 'Maximum number of files exceeded', - 'max_width' => 'Image exceeds maximum width', - 'min_width' => 'Image requires a minimum width', - 'max_height' => 'Image exceeds maximum height', - 'min_height' => 'Image requires a minimum height', - 'abort' => 'File upload aborted', - 'image_resize' => 'Failed to resize image' - ); - - protected $image_objects = array(); - - public function __construct($options = null, $initialize = true, $error_messages = null) { - $this->response = array(); - $this->options = array( - 'script_url' => $this->get_full_url().'/'.$this->basename($this->get_server_var('SCRIPT_NAME')), - 'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/', - 'upload_url' => $this->get_full_url().'/files/', - 'input_stream' => 'php://input', - 'user_dirs' => false, - 'mkdir_mode' => 0755, - 'param_name' => 'files', - // Set the following option to 'POST', if your server does not support - // DELETE requests. This is a parameter sent to the client: - 'delete_type' => 'DELETE', - 'access_control_allow_origin' => '*', - 'access_control_allow_credentials' => false, - 'access_control_allow_methods' => array( - 'OPTIONS', - 'HEAD', - 'GET', - 'POST', - 'PUT', - 'PATCH', - 'DELETE' - ), - 'access_control_allow_headers' => array( - 'Content-Type', - 'Content-Range', - 'Content-Disposition' - ), - // By default, allow redirects to the referer protocol+host: - 'redirect_allow_target' => '/^'.preg_quote( - parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_SCHEME) - .'://' - .parse_url($this->get_server_var('HTTP_REFERER'), PHP_URL_HOST) - .'/', // Trailing slash to not match subdomains by mistake - '/' // preg_quote delimiter param - ).'/', - // Enable to provide file downloads via GET requests to the PHP script: - // 1. Set to 1 to download files via readfile method through PHP - // 2. Set to 2 to send a X-Sendfile header for lighttpd/Apache - // 3. Set to 3 to send a X-Accel-Redirect header for nginx - // If set to 2 or 3, adjust the upload_url option to the base path of - // the redirect parameter, e.g. '/files/'. - 'download_via_php' => false, - // Read files in chunks to avoid memory limits when download_via_php - // is enabled, set to 0 to disable chunked reading of files: - 'readfile_chunk_size' => 10 * 1024 * 1024, // 10 MiB - // Defines which files can be displayed inline when downloaded: - 'inline_file_types' => '/\.(gif|jpe?g|png)$/i', - // Defines which files (based on their names) are accepted for upload: - 'accept_file_types' => '/.+$/i', - // The php.ini settings upload_max_filesize and post_max_size - // take precedence over the following max_file_size setting: - 'max_file_size' => null, - 'min_file_size' => 1, - // The maximum number of files for the upload directory: - 'max_number_of_files' => null, - // Defines which files are handled as image files: - 'image_file_types' => '/\.(gif|jpe?g|png)$/i', - // Use exif_imagetype on all files to correct file extensions: - 'correct_image_extensions' => false, - // Image resolution restrictions: - 'max_width' => null, - 'max_height' => null, - 'min_width' => 1, - 'min_height' => 1, - // Set the following option to false to enable resumable uploads: - 'discard_aborted_uploads' => true, - // Set to 0 to use the GD library to scale and orient images, - // set to 1 to use imagick (if installed, falls back to GD), - // set to 2 to use the ImageMagick convert binary directly: - 'image_library' => 1, - // Uncomment the following to define an array of resource limits - // for imagick: - /* - 'imagick_resource_limits' => array( - imagick::RESOURCETYPE_MAP => 32, - imagick::RESOURCETYPE_MEMORY => 32 - ), - */ - // Command or path for to the ImageMagick convert binary: - 'convert_bin' => 'convert', - // Uncomment the following to add parameters in front of each - // ImageMagick convert call (the limit constraints seem only - // to have an effect if put in front): - /* - 'convert_params' => '-limit memory 32MiB -limit map 32MiB', - */ - // Command or path for to the ImageMagick identify binary: - 'identify_bin' => 'identify', - 'image_versions' => array( - // The empty image version key defines options for the original image. - // Keep in mind: these image manipulations are inherited by all other image versions from this point onwards. - // Also note that the property 'no_cache' is not inherited, since it's not a manipulation. - '' => array( - // Automatically rotate images based on EXIF meta data: - 'auto_orient' => true - ), - // You can add arrays to generate different versions. - // The name of the key is the name of the version (example: 'medium'). - // the array contains the options to apply. - /* - 'medium' => array( - 'max_width' => 800, - 'max_height' => 600 - ), - */ - 'thumbnail' => array( - // Uncomment the following to use a defined directory for the thumbnails - // instead of a subdirectory based on the version identifier. - // Make sure that this directory doesn't allow execution of files if you - // don't pose any restrictions on the type of uploaded files, e.g. by - // copying the .htaccess file from the files directory for Apache: - //'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/thumb/', - //'upload_url' => $this->get_full_url().'/thumb/', - // Uncomment the following to force the max - // dimensions and e.g. create square thumbnails: - // 'auto_orient' => true, - // 'crop' => true, - // 'jpeg_quality' => 70, - // 'no_cache' => true, (there's a caching option, but this remembers thumbnail sizes from a previous action!) - // 'strip' => true, (this strips EXIF tags, such as geolocation) - 'max_width' => 80, // either specify width, or set to 0. Then width is automatically adjusted - keeping aspect ratio to a specified max_height. - 'max_height' => 80 // either specify height, or set to 0. Then height is automatically adjusted - keeping aspect ratio to a specified max_width. - ) - ), - 'print_response' => true - ); - if ($options) { - $this->options = $options + $this->options; - } - if ($error_messages) { - $this->error_messages = $error_messages + $this->error_messages; - } - if ($initialize) { - $this->initialize(); - } - } - - protected function initialize() { - switch ($this->get_server_var('REQUEST_METHOD')) { - case 'OPTIONS': - case 'HEAD': - $this->head(); - break; - case 'GET': - $this->get($this->options['print_response']); - break; - case 'PATCH': - case 'PUT': - case 'POST': - $this->post($this->options['print_response']); - break; - case 'DELETE': - $this->delete($this->options['print_response']); - break; - default: - $this->header('HTTP/1.1 405 Method Not Allowed'); - } - } - - protected function get_full_url() { - $https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 || - !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && - strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0; - return - ($https ? 'https://' : 'http://'). - (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). - (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. - ($https && $_SERVER['SERVER_PORT'] === 443 || - $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). - substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')); - } - - protected function get_user_id() { - @session_start(); - return session_id(); - } - - protected function get_user_path() { - if ($this->options['user_dirs']) { - return $this->get_user_id().'/'; - } - return ''; - } - - protected function get_upload_path($file_name = null, $version = null) { - $file_name = $file_name ? $file_name : ''; - if (empty($version)) { - $version_path = ''; - } else { - $version_dir = @$this->options['image_versions'][$version]['upload_dir']; - if ($version_dir) { - return $version_dir.$this->get_user_path().$file_name; - } - $version_path = $version.'/'; - } - return $this->options['upload_dir'].$this->get_user_path() - .$version_path.$file_name; - } - - protected function get_query_separator($url) { - return strpos($url, '?') === false ? '?' : '&'; - } - - protected function get_download_url($file_name, $version = null, $direct = false) { - if (!$direct && $this->options['download_via_php']) { - $url = $this->options['script_url'] - .$this->get_query_separator($this->options['script_url']) - .$this->get_singular_param_name() - .'='.rawurlencode($file_name); - if ($version) { - $url .= '&version='.rawurlencode($version); - } - return $url.'&download=1'; - } - if (empty($version)) { - $version_path = ''; - } else { - $version_url = @$this->options['image_versions'][$version]['upload_url']; - if ($version_url) { - return $version_url.$this->get_user_path().rawurlencode($file_name); - } - $version_path = rawurlencode($version).'/'; - } - return $this->options['upload_url'].$this->get_user_path() - .$version_path.rawurlencode($file_name); - } - - protected function set_additional_file_properties($file) { - $file->deleteUrl = $this->options['script_url'] - .$this->get_query_separator($this->options['script_url']) - .$this->get_singular_param_name() - .'='.rawurlencode($file->name); - $file->deleteType = $this->options['delete_type']; - if ($file->deleteType !== 'DELETE') { - $file->deleteUrl .= '&_method=DELETE'; - } - if ($this->options['access_control_allow_credentials']) { - $file->deleteWithCredentials = true; - } - } - - // Fix for overflowing signed 32 bit integers, - // works for sizes up to 2^32-1 bytes (4 GiB - 1): - protected function fix_integer_overflow($size) { - if ($size < 0) { - $size += 2.0 * (PHP_INT_MAX + 1); - } - return $size; - } - - protected function get_file_size($file_path, $clear_stat_cache = false) { - if ($clear_stat_cache) { - if (version_compare(PHP_VERSION, '5.3.0') >= 0) { - clearstatcache(true, $file_path); - } else { - clearstatcache(); - } - } - return $this->fix_integer_overflow(filesize($file_path)); - } - - protected function is_valid_file_object($file_name) { - $file_path = $this->get_upload_path($file_name); - if (is_file($file_path) && $file_name[0] !== '.') { - return true; - } - return false; - } - - protected function get_file_object($file_name) { - if ($this->is_valid_file_object($file_name)) { - $file = new \stdClass(); - $file->name = $file_name; - $file->size = $this->get_file_size( - $this->get_upload_path($file_name) - ); - $file->url = $this->get_download_url($file->name); - foreach ($this->options['image_versions'] as $version => $options) { - if (!empty($version)) { - if (is_file($this->get_upload_path($file_name, $version))) { - $file->{$version.'Url'} = $this->get_download_url( - $file->name, - $version - ); - } - } - } - $this->set_additional_file_properties($file); - return $file; - } - return null; - } - - protected function get_file_objects($iteration_method = 'get_file_object') { - $upload_dir = $this->get_upload_path(); - if (!is_dir($upload_dir)) { - return array(); - } - return array_values(array_filter(array_map( - array($this, $iteration_method), - scandir($upload_dir) - ))); - } - - protected function count_file_objects() { - return count($this->get_file_objects('is_valid_file_object')); - } - - protected function get_error_message($error) { - return isset($this->error_messages[$error]) ? - $this->error_messages[$error] : $error; - } - - public function get_config_bytes($val) { - $val = trim($val); - $last = strtolower($val[strlen($val)-1]); - $val = (int)$val; - switch ($last) { - case 'g': - $val *= 1024; - case 'm': - $val *= 1024; - case 'k': - $val *= 1024; - } - return $this->fix_integer_overflow($val); - } - - protected function validate($uploaded_file, $file, $error, $index) { - if ($error) { - $file->error = $this->get_error_message($error); - return false; - } - $content_length = $this->fix_integer_overflow( - (int)$this->get_server_var('CONTENT_LENGTH') - ); - $post_max_size = $this->get_config_bytes(ini_get('post_max_size')); - if ($post_max_size && ($content_length > $post_max_size)) { - $file->error = $this->get_error_message('post_max_size'); - return false; - } - if (!preg_match($this->options['accept_file_types'], $file->name)) { - $file->error = $this->get_error_message('accept_file_types'); - return false; - } - if ($uploaded_file && is_uploaded_file($uploaded_file)) { - $file_size = $this->get_file_size($uploaded_file); - } else { - $file_size = $content_length; - } - if ($this->options['max_file_size'] && ( - $file_size > $this->options['max_file_size'] || - $file->size > $this->options['max_file_size']) - ) { - $file->error = $this->get_error_message('max_file_size'); - return false; - } - if ($this->options['min_file_size'] && - $file_size < $this->options['min_file_size']) { - $file->error = $this->get_error_message('min_file_size'); - return false; - } - if (is_int($this->options['max_number_of_files']) && - ($this->count_file_objects() >= $this->options['max_number_of_files']) && - // Ignore additional chunks of existing files: - !is_file($this->get_upload_path($file->name))) { - $file->error = $this->get_error_message('max_number_of_files'); - return false; - } - $max_width = @$this->options['max_width']; - $max_height = @$this->options['max_height']; - $min_width = @$this->options['min_width']; - $min_height = @$this->options['min_height']; - if (($max_width || $max_height || $min_width || $min_height) - && preg_match($this->options['image_file_types'], $file->name)) { - list($img_width, $img_height) = $this->get_image_size($uploaded_file); - - // If we are auto rotating the image by default, do the checks on - // the correct orientation - if ( - @$this->options['image_versions']['']['auto_orient'] && - function_exists('exif_read_data') && - ($exif = @exif_read_data($uploaded_file)) && - (((int) @$exif['Orientation']) >= 5) - ) { - $tmp = $img_width; - $img_width = $img_height; - $img_height = $tmp; - unset($tmp); - } - - } - if (!empty($img_width)) { - if ($max_width && $img_width > $max_width) { - $file->error = $this->get_error_message('max_width'); - return false; - } - if ($max_height && $img_height > $max_height) { - $file->error = $this->get_error_message('max_height'); - return false; - } - if ($min_width && $img_width < $min_width) { - $file->error = $this->get_error_message('min_width'); - return false; - } - if ($min_height && $img_height < $min_height) { - $file->error = $this->get_error_message('min_height'); - return false; - } - } - return true; - } - - protected function upcount_name_callback($matches) { - $index = isset($matches[1]) ? ((int)$matches[1]) + 1 : 1; - $ext = isset($matches[2]) ? $matches[2] : ''; - return ' ('.$index.')'.$ext; - } - - protected function upcount_name($name) { - return preg_replace_callback( - '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', - array($this, 'upcount_name_callback'), - $name, - 1 - ); - } - - protected function get_unique_filename($file_path, $name, $size, $type, $error, - $index, $content_range) { - while(is_dir($this->get_upload_path($name))) { - $name = $this->upcount_name($name); - } - // Keep an existing filename if this is part of a chunked upload: - $uploaded_bytes = $this->fix_integer_overflow((int)$content_range[1]); - while (is_file($this->get_upload_path($name))) { - if ($uploaded_bytes === $this->get_file_size( - $this->get_upload_path($name))) { - break; - } - $name = $this->upcount_name($name); - } - return $name; - } - - protected function fix_file_extension($file_path, $name, $size, $type, $error, - $index, $content_range) { - // Add missing file extension for known image types: - if (strpos($name, '.') === false && - preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { - $name .= '.'.$matches[1]; - } - if ($this->options['correct_image_extensions'] && - function_exists('exif_imagetype')) { - switch (@exif_imagetype($file_path)){ - case IMAGETYPE_JPEG: - $extensions = array('jpg', 'jpeg'); - break; - case IMAGETYPE_PNG: - $extensions = array('png'); - break; - case IMAGETYPE_GIF: - $extensions = array('gif'); - break; - } - // Adjust incorrect image file extensions: - if (!empty($extensions)) { - $parts = explode('.', $name); - $extIndex = count($parts) - 1; - $ext = strtolower(@$parts[$extIndex]); - if (!in_array($ext, $extensions)) { - $parts[$extIndex] = $extensions[0]; - $name = implode('.', $parts); - } - } - } - return $name; - } - - protected function trim_file_name($file_path, $name, $size, $type, $error, - $index, $content_range) { - // Remove path information and dots around the filename, to prevent uploading - // into different directories or replacing hidden system files. - // Also remove control characters and spaces (\x00..\x20) around the filename: - $name = trim($this->basename(stripslashes($name)), ".\x00..\x20"); - // Use a timestamp for empty filenames: - if (!$name) { - $name = str_replace('.', '-', microtime(true)); - } - return $name; - } - - protected function get_file_name($file_path, $name, $size, $type, $error, - $index, $content_range) { - $name = $this->trim_file_name($file_path, $name, $size, $type, $error, - $index, $content_range); - return $this->get_unique_filename( - $file_path, - $this->fix_file_extension($file_path, $name, $size, $type, $error, - $index, $content_range), - $size, - $type, - $error, - $index, - $content_range - ); - } - - protected function get_scaled_image_file_paths($file_name, $version) { - $file_path = $this->get_upload_path($file_name); - if (!empty($version)) { - $version_dir = $this->get_upload_path(null, $version); - if (!is_dir($version_dir)) { - mkdir($version_dir, $this->options['mkdir_mode'], true); - } - $new_file_path = $version_dir.'/'.$file_name; - } else { - $new_file_path = $file_path; - } - return array($file_path, $new_file_path); - } - - protected function gd_get_image_object($file_path, $func, $no_cache = false) { - if (empty($this->image_objects[$file_path]) || $no_cache) { - $this->gd_destroy_image_object($file_path); - $this->image_objects[$file_path] = $func($file_path); - } - return $this->image_objects[$file_path]; - } - - protected function gd_set_image_object($file_path, $image) { - $this->gd_destroy_image_object($file_path); - $this->image_objects[$file_path] = $image; - } - - protected function gd_destroy_image_object($file_path) { - $image = (isset($this->image_objects[$file_path])) ? $this->image_objects[$file_path] : null ; - return $image && imagedestroy($image); - } - - protected function gd_imageflip($image, $mode) { - if (function_exists('imageflip')) { - return imageflip($image, $mode); - } - $new_width = $src_width = imagesx($image); - $new_height = $src_height = imagesy($image); - $new_img = imagecreatetruecolor($new_width, $new_height); - $src_x = 0; - $src_y = 0; - switch ($mode) { - case '1': // flip on the horizontal axis - $src_y = $new_height - 1; - $src_height = -$new_height; - break; - case '2': // flip on the vertical axis - $src_x = $new_width - 1; - $src_width = -$new_width; - break; - case '3': // flip on both axes - $src_y = $new_height - 1; - $src_height = -$new_height; - $src_x = $new_width - 1; - $src_width = -$new_width; - break; - default: - return $image; - } - imagecopyresampled( - $new_img, - $image, - 0, - 0, - $src_x, - $src_y, - $new_width, - $new_height, - $src_width, - $src_height - ); - return $new_img; - } - - protected function gd_orient_image($file_path, $src_img) { - if (!function_exists('exif_read_data')) { - return false; - } - $exif = @exif_read_data($file_path); - if ($exif === false) { - return false; - } - $orientation = (int)@$exif['Orientation']; - if ($orientation < 2 || $orientation > 8) { - return false; - } - switch ($orientation) { - case 2: - $new_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2 - ); - break; - case 3: - $new_img = imagerotate($src_img, 180, 0); - break; - case 4: - $new_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1 - ); - break; - case 5: - $tmp_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1 - ); - $new_img = imagerotate($tmp_img, 270, 0); - imagedestroy($tmp_img); - break; - case 6: - $new_img = imagerotate($src_img, 270, 0); - break; - case 7: - $tmp_img = $this->gd_imageflip( - $src_img, - defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2 - ); - $new_img = imagerotate($tmp_img, 270, 0); - imagedestroy($tmp_img); - break; - case 8: - $new_img = imagerotate($src_img, 90, 0); - break; - default: - return false; - } - $this->gd_set_image_object($file_path, $new_img); - return true; - } - - protected function gd_create_scaled_image($file_name, $version, $options) { - if (!function_exists('imagecreatetruecolor')) { - error_log('Function not found: imagecreatetruecolor'); - return false; - } - list($file_path, $new_file_path) = - $this->get_scaled_image_file_paths($file_name, $version); - $type = strtolower(substr(strrchr($file_name, '.'), 1)); - switch ($type) { - case 'jpg': - case 'jpeg': - $src_func = 'imagecreatefromjpeg'; - $write_func = 'imagejpeg'; - $image_quality = isset($options['jpeg_quality']) ? - $options['jpeg_quality'] : 75; - break; - case 'gif': - $src_func = 'imagecreatefromgif'; - $write_func = 'imagegif'; - $image_quality = null; - break; - case 'png': - $src_func = 'imagecreatefrompng'; - $write_func = 'imagepng'; - $image_quality = isset($options['png_quality']) ? - $options['png_quality'] : 9; - break; - default: - return false; - } - $src_img = $this->gd_get_image_object( - $file_path, - $src_func, - !empty($options['no_cache']) - ); - $image_oriented = false; - if (!empty($options['auto_orient']) && $this->gd_orient_image( - $file_path, - $src_img - )) { - $image_oriented = true; - $src_img = $this->gd_get_image_object( - $file_path, - $src_func - ); - } - $max_width = $img_width = imagesx($src_img); - $max_height = $img_height = imagesy($src_img); - if (!empty($options['max_width'])) { - $max_width = $options['max_width']; - } - if (!empty($options['max_height'])) { - $max_height = $options['max_height']; - } - $scale = min( - $max_width / $img_width, - $max_height / $img_height - ); - if ($scale >= 1) { - if ($image_oriented) { - return $write_func($src_img, $new_file_path, $image_quality); - } - if ($file_path !== $new_file_path) { - return copy($file_path, $new_file_path); - } - return true; - } - if (empty($options['crop'])) { - $new_width = $img_width * $scale; - $new_height = $img_height * $scale; - $dst_x = 0; - $dst_y = 0; - $new_img = imagecreatetruecolor($new_width, $new_height); - } else { - if (($img_width / $img_height) >= ($max_width / $max_height)) { - $new_width = $img_width / ($img_height / $max_height); - $new_height = $max_height; - } else { - $new_width = $max_width; - $new_height = $img_height / ($img_width / $max_width); - } - $dst_x = 0 - ($new_width - $max_width) / 2; - $dst_y = 0 - ($new_height - $max_height) / 2; - $new_img = imagecreatetruecolor($max_width, $max_height); - } - // Handle transparency in GIF and PNG images: - switch ($type) { - case 'gif': - case 'png': - imagecolortransparent($new_img, imagecolorallocate($new_img, 0, 0, 0)); - case 'png': - imagealphablending($new_img, false); - imagesavealpha($new_img, true); - break; - } - $success = imagecopyresampled( - $new_img, - $src_img, - $dst_x, - $dst_y, - 0, - 0, - $new_width, - $new_height, - $img_width, - $img_height - ) && $write_func($new_img, $new_file_path, $image_quality); - $this->gd_set_image_object($file_path, $new_img); - return $success; - } - - protected function imagick_get_image_object($file_path, $no_cache = false) { - if (empty($this->image_objects[$file_path]) || $no_cache) { - $this->imagick_destroy_image_object($file_path); - $image = new \Imagick(); - if (!empty($this->options['imagick_resource_limits'])) { - foreach ($this->options['imagick_resource_limits'] as $type => $limit) { - $image->setResourceLimit($type, $limit); - } - } - $image->readImage($file_path); - $this->image_objects[$file_path] = $image; - } - return $this->image_objects[$file_path]; - } - - protected function imagick_set_image_object($file_path, $image) { - $this->imagick_destroy_image_object($file_path); - $this->image_objects[$file_path] = $image; - } - - protected function imagick_destroy_image_object($file_path) { - $image = (isset($this->image_objects[$file_path])) ? $this->image_objects[$file_path] : null ; - return $image && $image->destroy(); - } - - protected function imagick_orient_image($image) { - $orientation = $image->getImageOrientation(); - $background = new \ImagickPixel('none'); - switch ($orientation) { - case \imagick::ORIENTATION_TOPRIGHT: // 2 - $image->flopImage(); // horizontal flop around y-axis - break; - case \imagick::ORIENTATION_BOTTOMRIGHT: // 3 - $image->rotateImage($background, 180); - break; - case \imagick::ORIENTATION_BOTTOMLEFT: // 4 - $image->flipImage(); // vertical flip around x-axis - break; - case \imagick::ORIENTATION_LEFTTOP: // 5 - $image->flopImage(); // horizontal flop around y-axis - $image->rotateImage($background, 270); - break; - case \imagick::ORIENTATION_RIGHTTOP: // 6 - $image->rotateImage($background, 90); - break; - case \imagick::ORIENTATION_RIGHTBOTTOM: // 7 - $image->flipImage(); // vertical flip around x-axis - $image->rotateImage($background, 270); - break; - case \imagick::ORIENTATION_LEFTBOTTOM: // 8 - $image->rotateImage($background, 270); - break; - default: - return false; - } - $image->setImageOrientation(\imagick::ORIENTATION_TOPLEFT); // 1 - return true; - } - - protected function imagick_create_scaled_image($file_name, $version, $options) { - list($file_path, $new_file_path) = - $this->get_scaled_image_file_paths($file_name, $version); - $image = $this->imagick_get_image_object( - $file_path, - !empty($options['crop']) || !empty($options['no_cache']) - ); - if ($image->getImageFormat() === 'GIF') { - // Handle animated GIFs: - $images = $image->coalesceImages(); - foreach ($images as $frame) { - $image = $frame; - $this->imagick_set_image_object($file_name, $image); - break; - } - } - $image_oriented = false; - if (!empty($options['auto_orient'])) { - $image_oriented = $this->imagick_orient_image($image); - } - - $image_resize = false; - $new_width = $max_width = $img_width = $image->getImageWidth(); - $new_height = $max_height = $img_height = $image->getImageHeight(); - - // use isset(). User might be setting max_width = 0 (auto in regular resizing). Value 0 would be considered empty when you use empty() - if (isset($options['max_width'])) { - $image_resize = true; - $new_width = $max_width = $options['max_width']; - } - if (isset($options['max_height'])) { - $image_resize = true; - $new_height = $max_height = $options['max_height']; - } - - $image_strip = (isset($options['strip']) ? $options['strip'] : false); - - if ( !$image_oriented && ($max_width >= $img_width) && ($max_height >= $img_height) && !$image_strip && empty($options["jpeg_quality"]) ) { - if ($file_path !== $new_file_path) { - return copy($file_path, $new_file_path); - } - return true; - } - $crop = (isset($options['crop']) ? $options['crop'] : false); - - if ($crop) { - $x = 0; - $y = 0; - if (($img_width / $img_height) >= ($max_width / $max_height)) { - $new_width = 0; // Enables proportional scaling based on max_height - $x = ($img_width / ($img_height / $max_height) - $max_width) / 2; - } else { - $new_height = 0; // Enables proportional scaling based on max_width - $y = ($img_height / ($img_width / $max_width) - $max_height) / 2; - } - } - $success = $image->resizeImage( - $new_width, - $new_height, - isset($options['filter']) ? $options['filter'] : \imagick::FILTER_LANCZOS, - isset($options['blur']) ? $options['blur'] : 1, - $new_width && $new_height // fit image into constraints if not to be cropped - ); - if ($success && $crop) { - $success = $image->cropImage( - $max_width, - $max_height, - $x, - $y - ); - if ($success) { - $success = $image->setImagePage($max_width, $max_height, 0, 0); - } - } - $type = strtolower(substr(strrchr($file_name, '.'), 1)); - switch ($type) { - case 'jpg': - case 'jpeg': - if (!empty($options['jpeg_quality'])) { - $image->setImageCompression(\imagick::COMPRESSION_JPEG); - $image->setImageCompressionQuality($options['jpeg_quality']); - } - break; - } - if ( $image_strip ) { - $image->stripImage(); - } - return $success && $image->writeImage($new_file_path); - } - - protected function imagemagick_create_scaled_image($file_name, $version, $options) { - list($file_path, $new_file_path) = - $this->get_scaled_image_file_paths($file_name, $version); - $resize = @$options['max_width'] - .(empty($options['max_height']) ? '' : 'X'.$options['max_height']); - if (!$resize && empty($options['auto_orient'])) { - if ($file_path !== $new_file_path) { - return copy($file_path, $new_file_path); - } - return true; - } - $cmd = $this->options['convert_bin']; - if (!empty($this->options['convert_params'])) { - $cmd .= ' '.$this->options['convert_params']; - } - $cmd .= ' '.escapeshellarg($file_path); - if (!empty($options['auto_orient'])) { - $cmd .= ' -auto-orient'; - } - if ($resize) { - // Handle animated GIFs: - $cmd .= ' -coalesce'; - if (empty($options['crop'])) { - $cmd .= ' -resize '.escapeshellarg($resize.'>'); - } else { - $cmd .= ' -resize '.escapeshellarg($resize.'^'); - $cmd .= ' -gravity center'; - $cmd .= ' -crop '.escapeshellarg($resize.'+0+0'); - } - // Make sure the page dimensions are correct (fixes offsets of animated GIFs): - $cmd .= ' +repage'; - } - if (!empty($options['convert_params'])) { - $cmd .= ' '.$options['convert_params']; - } - $cmd .= ' '.escapeshellarg($new_file_path); - exec($cmd, $output, $error); - if ($error) { - error_log(implode('\n', $output)); - return false; - } - return true; - } - - protected function get_image_size($file_path) { - if ($this->options['image_library']) { - if (extension_loaded('imagick')) { - $image = new \Imagick(); - try { - if (@$image->pingImage($file_path)) { - $dimensions = array($image->getImageWidth(), $image->getImageHeight()); - $image->destroy(); - return $dimensions; - } - return false; - } catch (\Exception $e) { - error_log($e->getMessage()); - } - } - if ($this->options['image_library'] === 2) { - $cmd = $this->options['identify_bin']; - $cmd .= ' -ping '.escapeshellarg($file_path); - exec($cmd, $output, $error); - if (!$error && !empty($output)) { - // image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000 - $infos = preg_split('/\s+/', substr($output[0], strlen($file_path))); - $dimensions = preg_split('/x/', $infos[2]); - return $dimensions; - } - return false; - } - } - if (!function_exists('getimagesize')) { - error_log('Function not found: getimagesize'); - return false; - } - return @getimagesize($file_path); - } - - protected function create_scaled_image($file_name, $version, $options) { - if ($this->options['image_library'] === 2) { - return $this->imagemagick_create_scaled_image($file_name, $version, $options); - } - if ($this->options['image_library'] && extension_loaded('imagick')) { - return $this->imagick_create_scaled_image($file_name, $version, $options); - } - return $this->gd_create_scaled_image($file_name, $version, $options); - } - - protected function destroy_image_object($file_path) { - if ($this->options['image_library'] && extension_loaded('imagick')) { - return $this->imagick_destroy_image_object($file_path); - } - } - - protected function is_valid_image_file($file_path) { - if (!preg_match($this->options['image_file_types'], $file_path)) { - return false; - } - if (function_exists('exif_imagetype')) { - return @exif_imagetype($file_path); - } - $image_info = $this->get_image_size($file_path); - return $image_info && $image_info[0] && $image_info[1]; - } - - protected function handle_image_file($file_path, $file) { - $failed_versions = array(); - foreach ($this->options['image_versions'] as $version => $options) { - if ($this->create_scaled_image($file->name, $version, $options)) { - if (!empty($version)) { - $file->{$version.'Url'} = $this->get_download_url( - $file->name, - $version - ); - } else { - $file->size = $this->get_file_size($file_path, true); - } - } else { - $failed_versions[] = $version ? $version : 'original'; - } - } - if (count($failed_versions)) { - $file->error = $this->get_error_message('image_resize') - .' ('.implode($failed_versions, ', ').')'; - } - // Free memory: - $this->destroy_image_object($file_path); - } - - protected function handle_file_upload($uploaded_file, $name, $size, $type, $error, - $index = null, $content_range = null) { - $file = new \stdClass(); - $file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error, - $index, $content_range); - $file->size = $this->fix_integer_overflow((int)$size); - $file->type = $type; - if ($this->validate($uploaded_file, $file, $error, $index)) { - $this->handle_form_data($file, $index); - $upload_dir = $this->get_upload_path(); - if (!is_dir($upload_dir)) { - mkdir($upload_dir, $this->options['mkdir_mode'], true); - } - $file_path = $this->get_upload_path($file->name); - $append_file = $content_range && is_file($file_path) && - $file->size > $this->get_file_size($file_path); - if ($uploaded_file && is_uploaded_file($uploaded_file)) { - // multipart/formdata uploads (POST method uploads) - if ($append_file) { - file_put_contents( - $file_path, - fopen($uploaded_file, 'r'), - FILE_APPEND - ); - } else { - move_uploaded_file($uploaded_file, $file_path); - } - } else { - // Non-multipart uploads (PUT method support) - file_put_contents( - $file_path, - fopen($this->options['input_stream'], 'r'), - $append_file ? FILE_APPEND : 0 - ); - } - $file_size = $this->get_file_size($file_path, $append_file); - if ($file_size === $file->size) { - $file->url = $this->get_download_url($file->name); - if ($this->is_valid_image_file($file_path)) { - $this->handle_image_file($file_path, $file); - } - } else { - $file->size = $file_size; - if (!$content_range && $this->options['discard_aborted_uploads']) { - unlink($file_path); - $file->error = $this->get_error_message('abort'); - } - } - $this->set_additional_file_properties($file); - } - return $file; - } - - protected function readfile($file_path) { - $file_size = $this->get_file_size($file_path); - $chunk_size = $this->options['readfile_chunk_size']; - if ($chunk_size && $file_size > $chunk_size) { - $handle = fopen($file_path, 'rb'); - while (!feof($handle)) { - echo fread($handle, $chunk_size); - @ob_flush(); - @flush(); - } - fclose($handle); - return $file_size; - } - return readfile($file_path); - } - - protected function body($str) { - echo $str; - } - - protected function header($str) { - header($str); - } - - protected function get_upload_data($id) { - return @$_FILES[$id]; - } - - protected function get_post_param($id) { - return @$_POST[$id]; - } - - protected function get_query_param($id) { - return @$_GET[$id]; - } - - protected function get_server_var($id) { - return @$_SERVER[$id]; - } - - protected function handle_form_data($file, $index) { - // Handle form data, e.g. $_POST['description'][$index] - } - - protected function get_version_param() { - return $this->basename(stripslashes($this->get_query_param('version'))); - } - - protected function get_singular_param_name() { - return substr($this->options['param_name'], 0, -1); - } - - protected function get_file_name_param() { - $name = $this->get_singular_param_name(); - return $this->basename(stripslashes($this->get_query_param($name))); - } - - protected function get_file_names_params() { - $params = $this->get_query_param($this->options['param_name']); - if (!$params) { - return null; - } - foreach ($params as $key => $value) { - $params[$key] = $this->basename(stripslashes($value)); - } - return $params; - } - - protected function get_file_type($file_path) { - switch (strtolower(pathinfo($file_path, PATHINFO_EXTENSION))) { - case 'jpeg': - case 'jpg': - return 'image/jpeg'; - case 'png': - return 'image/png'; - case 'gif': - return 'image/gif'; - default: - return ''; - } - } - - protected function download() { - switch ($this->options['download_via_php']) { - case 1: - $redirect_header = null; - break; - case 2: - $redirect_header = 'X-Sendfile'; - break; - case 3: - $redirect_header = 'X-Accel-Redirect'; - break; - default: - return $this->header('HTTP/1.1 403 Forbidden'); - } - $file_name = $this->get_file_name_param(); - if (!$this->is_valid_file_object($file_name)) { - return $this->header('HTTP/1.1 404 Not Found'); - } - if ($redirect_header) { - return $this->header( - $redirect_header.': '.$this->get_download_url( - $file_name, - $this->get_version_param(), - true - ) - ); - } - $file_path = $this->get_upload_path($file_name, $this->get_version_param()); - // Prevent browsers from MIME-sniffing the content-type: - $this->header('X-Content-Type-Options: nosniff'); - if (!preg_match($this->options['inline_file_types'], $file_name)) { - $this->header('Content-Type: application/octet-stream'); - $this->header('Content-Disposition: attachment; filename="'.$file_name.'"'); - } else { - $this->header('Content-Type: '.$this->get_file_type($file_path)); - $this->header('Content-Disposition: inline; filename="'.$file_name.'"'); - } - $this->header('Content-Length: '.$this->get_file_size($file_path)); - $this->header('Last-Modified: '.gmdate('D, d M Y H:i:s T', filemtime($file_path))); - $this->readfile($file_path); - } - - protected function send_content_type_header() { - $this->header('Vary: Accept'); - if (strpos($this->get_server_var('HTTP_ACCEPT'), 'application/json') !== false) { - $this->header('Content-type: application/json'); - } else { - $this->header('Content-type: text/plain'); - } - } - - protected function send_access_control_headers() { - $this->header('Access-Control-Allow-Origin: '.$this->options['access_control_allow_origin']); - $this->header('Access-Control-Allow-Credentials: ' - .($this->options['access_control_allow_credentials'] ? 'true' : 'false')); - $this->header('Access-Control-Allow-Methods: ' - .implode(', ', $this->options['access_control_allow_methods'])); - $this->header('Access-Control-Allow-Headers: ' - .implode(', ', $this->options['access_control_allow_headers'])); - } - - public function generate_response($content, $print_response = true) { - $this->response = $content; - if ($print_response) { - $json = json_encode($content); - $redirect = stripslashes($this->get_post_param('redirect')); - if ($redirect && preg_match($this->options['redirect_allow_target'], $redirect)) { - $this->header('Location: '.sprintf($redirect, rawurlencode($json))); - return; - } - $this->head(); - if ($this->get_server_var('HTTP_CONTENT_RANGE')) { - $files = isset($content[$this->options['param_name']]) ? - $content[$this->options['param_name']] : null; - if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) { - $this->header('Range: 0-'.( - $this->fix_integer_overflow((int)$files[0]->size) - 1 - )); - } - } - $this->body($json); - } - return $content; - } - - public function get_response () { - return $this->response; - } - - public function head() { - $this->header('Pragma: no-cache'); - $this->header('Cache-Control: no-store, no-cache, must-revalidate'); - $this->header('Content-Disposition: inline; filename="files.json"'); - // Prevent Internet Explorer from MIME-sniffing the content-type: - $this->header('X-Content-Type-Options: nosniff'); - if ($this->options['access_control_allow_origin']) { - $this->send_access_control_headers(); - } - $this->send_content_type_header(); - } - - public function get($print_response = true) { - if ($print_response && $this->get_query_param('download')) { - return $this->download(); - } - $file_name = $this->get_file_name_param(); - if ($file_name) { - $response = array( - $this->get_singular_param_name() => $this->get_file_object($file_name) - ); - } else { - $response = array( - $this->options['param_name'] => $this->get_file_objects() - ); - } - return $this->generate_response($response, $print_response); - } - - public function post($print_response = true) { - if ($this->get_query_param('_method') === 'DELETE') { - return $this->delete($print_response); - } - $upload = $this->get_upload_data($this->options['param_name']); - // Parse the Content-Disposition header, if available: - $content_disposition_header = $this->get_server_var('HTTP_CONTENT_DISPOSITION'); - $file_name = $content_disposition_header ? - rawurldecode(preg_replace( - '/(^[^"]+")|("$)/', - '', - $content_disposition_header - )) : null; - // Parse the Content-Range header, which has the following form: - // Content-Range: bytes 0-524287/2000000 - $content_range_header = $this->get_server_var('HTTP_CONTENT_RANGE'); - $content_range = $content_range_header ? - preg_split('/[^0-9]+/', $content_range_header) : null; - $size = $content_range ? $content_range[3] : null; - $files = array(); - if ($upload) { - if (is_array($upload['tmp_name'])) { - // param_name is an array identifier like "files[]", - // $upload is a multi-dimensional array: - foreach ($upload['tmp_name'] as $index => $value) { - $files[] = $this->handle_file_upload( - $upload['tmp_name'][$index], - $file_name ? $file_name : $upload['name'][$index], - $size ? $size : $upload['size'][$index], - $upload['type'][$index], - $upload['error'][$index], - $index, - $content_range - ); - } - } else { - // param_name is a single object identifier like "file", - // $upload is a one-dimensional array: - $files[] = $this->handle_file_upload( - isset($upload['tmp_name']) ? $upload['tmp_name'] : null, - $file_name ? $file_name : (isset($upload['name']) ? - $upload['name'] : null), - $size ? $size : (isset($upload['size']) ? - $upload['size'] : $this->get_server_var('CONTENT_LENGTH')), - isset($upload['type']) ? - $upload['type'] : $this->get_server_var('CONTENT_TYPE'), - isset($upload['error']) ? $upload['error'] : null, - null, - $content_range - ); - } - } - $response = array($this->options['param_name'] => $files); - return $this->generate_response($response, $print_response); - } - - public function delete($print_response = true) { - $file_names = $this->get_file_names_params(); - if (empty($file_names)) { - $file_names = array($this->get_file_name_param()); - } - $response = array(); - foreach ($file_names as $file_name) { - $file_path = $this->get_upload_path($file_name); - $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); - if ($success) { - foreach ($this->options['image_versions'] as $version => $options) { - if (!empty($version)) { - $file = $this->get_upload_path($file_name, $version); - if (is_file($file)) { - unlink($file); - } - } - } - } - $response[$file_name] = $success; - } - return $this->generate_response($response, $print_response); - } - - protected function basename($filepath, $suffix = null) { - $splited = preg_split('/\//', rtrim ($filepath, '/ ')); - return substr(basename('X'.$splited[count($splited)-1], $suffix), 1); - } -} diff --git a/library/blueimp_upload/server/php/docker-compose.yml b/library/blueimp_upload/server/php/docker-compose.yml deleted file mode 100644 index 74eabf7dc..000000000 --- a/library/blueimp_upload/server/php/docker-compose.yml +++ /dev/null @@ -1,9 +0,0 @@ -version: '2.3' -services: - apache: - build: ./ - network_mode: bridge - ports: - - "80:80" - volumes: - - "../../:/var/www/html" diff --git a/library/blueimp_upload/server/php/files/.gitignore b/library/blueimp_upload/server/php/files/.gitignore deleted file mode 100644 index e24a60fae..000000000 --- a/library/blueimp_upload/server/php/files/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!.gitignore -!.htaccess diff --git a/library/blueimp_upload/server/php/files/.htaccess b/library/blueimp_upload/server/php/files/.htaccess deleted file mode 100644 index 6f454afb9..000000000 --- a/library/blueimp_upload/server/php/files/.htaccess +++ /dev/null @@ -1,26 +0,0 @@ -# To enable the Headers module, execute the following command and reload Apache: -# sudo a2enmod headers - -# The following directives prevent the execution of script files -# in the context of the website. -# They also force the content-type application/octet-stream and -# force browsers to display a download dialog for non-image files. -SetHandler default-handler -ForceType application/octet-stream -Header set Content-Disposition attachment - -# The following unsets the forced type and Content-Disposition headers -# for known image files: - - ForceType none - Header unset Content-Disposition - - -# The following directive prevents browsers from MIME-sniffing the content-type. -# This is an important complement to the ForceType directive above: -Header set X-Content-Type-Options nosniff - -# Uncomment the following lines to prevent unauthorized download of files: -#AuthName "Authorization required" -#AuthType Basic -#require valid-user diff --git a/library/blueimp_upload/test/index.html b/library/blueimp_upload/test/index.html deleted file mode 100644 index 0b5cf57b7..000000000 --- a/library/blueimp_upload/test/index.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - -jQuery File Upload Plugin Test - - - - -

jQuery File Upload Plugin Test

-

-
-

-
    -
    - -
    - -
    -
    - - - - Add files... - - - - - - - - -
    - -
    - -
    -
    -
    - -
     
    -
    -
    - - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/blueimp_upload/test/test.js b/library/blueimp_upload/test/test.js deleted file mode 100644 index 452127567..000000000 --- a/library/blueimp_upload/test/test.js +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * jQuery File Upload Plugin Test - * https://github.com/blueimp/jQuery-File-Upload - * - * Copyright 2010, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * https://opensource.org/licenses/MIT - */ - -/* global $, QUnit, window, document, expect, module, test, asyncTest, start, ok, strictEqual, notStrictEqual */ - -$(function () { - // jshint nomen:false - 'use strict'; - - QUnit.done = function () { - // Delete all uploaded files: - var url = $('#fileupload').prop('action'); - $.getJSON(url, function (result) { - $.each(result.files, function (index, file) { - $.ajax({ - url: url + '?file=' + encodeURIComponent(file.name), - type: 'DELETE' - }); - }); - }); - }; - - var lifecycle = { - setup: function () { - // Set the .fileupload method to the basic widget method: - $.widget('blueimp.fileupload', window.testBasicWidget, {}); - }, - teardown: function () { - // Remove all remaining event listeners: - $(document).unbind(); - } - }, - lifecycleUI = { - setup: function () { - // Set the .fileupload method to the UI widget method: - $.widget('blueimp.fileupload', window.testUIWidget, {}); - }, - teardown: function () { - // Remove all remaining event listeners: - $(document).unbind(); - } - }; - - module('Initialization', lifecycle); - - test('Widget initialization', function () { - var fu = $('#fileupload').fileupload(); - ok(fu.data('blueimp-fileupload') || fu.data('fileupload')); - }); - - test('Data attribute options', function () { - $('#fileupload').attr('data-url', 'http://example.org'); - $('#fileupload').fileupload(); - strictEqual( - $('#fileupload').fileupload('option', 'url'), - 'http://example.org' - ); - }); - - test('File input initialization', function () { - var fu = $('#fileupload').fileupload(); - ok( - fu.fileupload('option', 'fileInput').length, - 'File input field inside of the widget' - ); - ok( - fu.fileupload('option', 'fileInput').length, - 'Widget element as file input field' - ); - }); - - test('Drop zone initialization', function () { - ok($('#fileupload').fileupload() - .fileupload('option', 'dropZone').length); - }); - - test('Paste zone initialization', function () { - ok($('#fileupload').fileupload({pasteZone: document}) - .fileupload('option', 'pasteZone').length); - }); - - test('Event listeners initialization', function () { - expect( - $.support.xhrFormDataFileUpload ? 4 : 1 - ); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - fu = $('#fileupload').fileupload({ - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - module('API', lifecycle); - - test('destroy', function () { - expect(4); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - options = { - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }, - fu = $('#fileupload').fileupload(options), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - dropZone.bind('dragover', options.dragover); - dropZone.bind('drop', options.drop); - pasteZone.bind('paste', options.paste); - fileInput.bind('change', options.change); - fu.fileupload('destroy'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - test('disable/enable', function () { - expect( - $.support.xhrFormDataFileUpload ? 4 : 1 - ); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - fu = $('#fileupload').fileupload({ - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - fu.fileupload('disable'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - fu.fileupload('enable'); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - test('option', function () { - expect( - $.support.xhrFormDataFileUpload ? 10 : 7 - ); - var eo = { - originalEvent: { - dataTransfer: {files: [{}], types: ['Files']}, - clipboardData: {items: [{}]} - } - }, - fu = $('#fileupload').fileupload({ - pasteZone: document, - dragover: function () { - ok(true, 'Triggers dragover callback'); - return false; - }, - drop: function () { - ok(true, 'Triggers drop callback'); - return false; - }, - paste: function () { - ok(true, 'Triggers paste callback'); - return false; - }, - change: function () { - ok(true, 'Triggers change callback'); - return false; - } - }), - fileInput = fu.fileupload('option', 'fileInput'), - dropZone = fu.fileupload('option', 'dropZone'), - pasteZone = fu.fileupload('option', 'pasteZone'); - fu.fileupload('option', 'fileInput', null); - fu.fileupload('option', 'dropZone', null); - fu.fileupload('option', 'pasteZone', null); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - fu.fileupload('option', 'dropZone', 'body'); - strictEqual( - fu.fileupload('option', 'dropZone')[0], - document.body, - 'Allow a query string as parameter for the dropZone option' - ); - fu.fileupload('option', 'dropZone', document); - strictEqual( - fu.fileupload('option', 'dropZone')[0], - document, - 'Allow a document element as parameter for the dropZone option' - ); - fu.fileupload('option', 'pasteZone', 'body'); - strictEqual( - fu.fileupload('option', 'pasteZone')[0], - document.body, - 'Allow a query string as parameter for the pasteZone option' - ); - fu.fileupload('option', 'pasteZone', document); - strictEqual( - fu.fileupload('option', 'pasteZone')[0], - document, - 'Allow a document element as parameter for the pasteZone option' - ); - fu.fileupload('option', 'fileInput', ':file'); - strictEqual( - fu.fileupload('option', 'fileInput')[0], - $(':file')[0], - 'Allow a query string as parameter for the fileInput option' - ); - fu.fileupload('option', 'fileInput', $(':file')[0]); - strictEqual( - fu.fileupload('option', 'fileInput')[0], - $(':file')[0], - 'Allow a document element as parameter for the fileInput option' - ); - fu.fileupload('option', 'fileInput', fileInput); - fu.fileupload('option', 'dropZone', dropZone); - fu.fileupload('option', 'pasteZone', pasteZone); - fileInput.trigger($.Event('change', eo)); - dropZone.trigger($.Event('dragover', eo)); - dropZone.trigger($.Event('drop', eo)); - pasteZone.trigger($.Event('paste', eo)); - }); - - asyncTest('add', function () { - expect(2); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - add: function (e, data) { - strictEqual( - data.files[0].name, - param.files[0].name, - 'Triggers add callback' - ); - } - }).fileupload('add', param).fileupload( - 'option', - 'add', - function (e, data) { - data.submit().complete(function () { - ok(true, 'data.submit() Returns a jqXHR object'); - start(); - }); - } - ).fileupload('add', param); - }); - - asyncTest('send', function () { - expect(3); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - send: function (e, data) { - strictEqual( - data.files[0].name, - 'test', - 'Triggers send callback' - ); - } - }).fileupload('send', param).fail(function () { - ok(true, 'Allows to abort the request'); - }).complete(function () { - ok(true, 'Returns a jqXHR object'); - start(); - }).abort(); - }); - - module('Callbacks', lifecycle); - - asyncTest('add', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - add: function () { - ok(true, 'Triggers add callback'); - start(); - } - }).fileupload('add', param); - }); - - asyncTest('submit', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - submit: function () { - ok(true, 'Triggers submit callback'); - start(); - return false; - } - }).fileupload('add', param); - }); - - asyncTest('send', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - send: function () { - ok(true, 'Triggers send callback'); - start(); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('done', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - done: function () { - ok(true, 'Triggers done callback'); - start(); - } - }).fileupload('send', param); - }); - - asyncTest('fail', function () { - expect(1); - var param = {files: [{name: 'test'}]}, - fu = $('#fileupload').fileupload({ - url: '404', - fail: function () { - ok(true, 'Triggers fail callback'); - start(); - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('send', param); - }); - - asyncTest('always', function () { - expect(2); - var param = {files: [{name: 'test'}]}, - counter = 0, - fu = $('#fileupload').fileupload({ - always: function () { - ok(true, 'Triggers always callback'); - if (counter === 1) { - start(); - } else { - counter += 1; - } - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('add', param).fileupload( - 'option', - 'url', - '404' - ).fileupload('add', param); - }); - - asyncTest('progress', function () { - expect(1); - var param = {files: [{name: 'test'}]}, - counter = 0; - $('#fileupload').fileupload({ - forceIframeTransport: true, - progress: function () { - ok(true, 'Triggers progress callback'); - if (counter === 0) { - start(); - } else { - counter += 1; - } - } - }).fileupload('send', param); - }); - - asyncTest('progressall', function () { - expect(1); - var param = {files: [{name: 'test'}]}, - counter = 0; - $('#fileupload').fileupload({ - forceIframeTransport: true, - progressall: function () { - ok(true, 'Triggers progressall callback'); - if (counter === 0) { - start(); - } else { - counter += 1; - } - } - }).fileupload('send', param); - }); - - asyncTest('start', function () { - expect(1); - var param = {files: [{name: '1'}, {name: '2'}]}, - active = 0; - $('#fileupload').fileupload({ - send: function () { - active += 1; - }, - start: function () { - ok(!active, 'Triggers start callback before uploads'); - start(); - } - }).fileupload('send', param); - }); - - asyncTest('stop', function () { - expect(1); - var param = {files: [{name: '1'}, {name: '2'}]}, - active = 0; - $('#fileupload').fileupload({ - send: function () { - active += 1; - }, - always: function () { - active -= 1; - }, - stop: function () { - ok(!active, 'Triggers stop callback after uploads'); - start(); - } - }).fileupload('send', param); - }); - - test('change', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'), - fileInput = fu.fileupload('option', 'fileInput'); - expect(2); - fu.fileupload({ - change: function (e, data) { - ok(true, 'Triggers change callback'); - strictEqual( - data.files.length, - 0, - 'Returns empty files list' - ); - }, - add: $.noop - }); - fuo._onChange({ - data: {fileupload: fuo}, - target: fileInput[0] - }); - }); - - test('paste', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'); - expect(1); - fu.fileupload({ - paste: function () { - ok(true, 'Triggers paste callback'); - }, - add: $.noop - }); - fuo._onPaste({ - data: {fileupload: fuo}, - originalEvent: { - dataTransfer: {files: [{}]}, - clipboardData: {items: [{}]} - }, - preventDefault: $.noop - }); - }); - - test('drop', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'); - expect(1); - fu.fileupload({ - drop: function () { - ok(true, 'Triggers drop callback'); - }, - add: $.noop - }); - fuo._onDrop({ - data: {fileupload: fuo}, - originalEvent: { - dataTransfer: {files: [{}]}, - clipboardData: {items: [{}]} - }, - preventDefault: $.noop - }); - }); - - test('dragover', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'); - expect(1); - fu.fileupload({ - dragover: function () { - ok(true, 'Triggers dragover callback'); - }, - add: $.noop - }); - fuo._onDragOver({ - data: {fileupload: fuo}, - originalEvent: {dataTransfer: {types: ['Files']}}, - preventDefault: $.noop - }); - }); - - module('Options', lifecycle); - - test('paramName', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - paramName: null, - send: function (e, data) { - strictEqual( - data.paramName[0], - data.fileInput.prop('name'), - 'Takes paramName from file input field if not set' - ); - return false; - } - }).fileupload('send', param); - }); - - test('url', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - url: null, - send: function (e, data) { - strictEqual( - data.url, - $(data.fileInput.prop('form')).prop('action'), - 'Takes url from form action if not set' - ); - return false; - } - }).fileupload('send', param); - }); - - test('type', function () { - expect(2); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - type: null, - send: function (e, data) { - strictEqual( - data.type, - 'POST', - 'Request type is "POST" if not set to "PUT"' - ); - return false; - } - }).fileupload('send', param); - $('#fileupload').fileupload({ - type: 'PUT', - send: function (e, data) { - strictEqual( - data.type, - 'PUT', - 'Request type is "PUT" if set to "PUT"' - ); - return false; - } - }).fileupload('send', param); - }); - - test('replaceFileInput', function () { - var fu = $('#fileupload').fileupload(), - fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'), - fileInput = fu.fileupload('option', 'fileInput'), - fileInputElement = fileInput[0]; - expect(2); - fu.fileupload({ - replaceFileInput: false, - change: function () { - strictEqual( - fu.fileupload('option', 'fileInput')[0], - fileInputElement, - 'Keeps file input with replaceFileInput: false' - ); - }, - add: $.noop - }); - fuo._onChange({ - data: {fileupload: fuo}, - target: fileInput[0] - }); - fu.fileupload({ - replaceFileInput: true, - change: function () { - notStrictEqual( - fu.fileupload('option', 'fileInput')[0], - fileInputElement, - 'Replaces file input with replaceFileInput: true' - ); - }, - add: $.noop - }); - fuo._onChange({ - data: {fileupload: fuo}, - target: fileInput[0] - }); - }); - - asyncTest('forceIframeTransport', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - forceIframeTransport: true, - done: function (e, data) { - strictEqual( - data.dataType.substr(0, 6), - 'iframe', - 'Iframe Transport is used' - ); - start(); - } - }).fileupload('send', param); - }); - - test('singleFileUploads', function () { - expect(3); - var fu = $('#fileupload').fileupload(), - param = {files: [{name: '1'}, {name: '2'}]}, - index = 1; - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - $('#fileupload').fileupload({ - singleFileUploads: true, - add: function () { - ok(true, 'Triggers callback number ' + index.toString()); - index += 1; - } - }).fileupload('add', param).fileupload( - 'option', - 'singleFileUploads', - false - ).fileupload('add', param); - }); - - test('limitMultiFileUploads', function () { - expect(3); - var fu = $('#fileupload').fileupload(), - param = {files: [ - {name: '1'}, - {name: '2'}, - {name: '3'}, - {name: '4'}, - {name: '5'} - ]}, - index = 1; - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - $('#fileupload').fileupload({ - singleFileUploads: false, - limitMultiFileUploads: 2, - add: function () { - ok(true, 'Triggers callback number ' + index.toString()); - index += 1; - } - }).fileupload('add', param); - }); - - test('limitMultiFileUploadSize', function () { - expect(7); - var fu = $('#fileupload').fileupload(), - param = {files: [ - {name: '1-1', size: 100000}, - {name: '1-2', size: 40000}, - {name: '2-1', size: 100000}, - {name: '3-1', size: 50000}, - {name: '3-2', size: 40000}, - {name: '4-1', size: 45000} // New request due to limitMultiFileUploads - ]}, - param2 = {files: [ - {name: '5-1'}, - {name: '5-2'}, - {name: '6-1'}, - {name: '6-2'}, - {name: '7-1'} - ]}, - index = 1; - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - $('#fileupload').fileupload({ - singleFileUploads: false, - limitMultiFileUploads: 2, - limitMultiFileUploadSize: 150000, - limitMultiFileUploadSizeOverhead: 5000, - add: function () { - ok(true, 'Triggers callback number ' + index.toString()); - index += 1; - } - }).fileupload('add', param).fileupload('add', param2); - }); - - asyncTest('sequentialUploads', function () { - expect(6); - var param = {files: [ - {name: '1'}, - {name: '2'}, - {name: '3'}, - {name: '4'}, - {name: '5'}, - {name: '6'} - ]}, - addIndex = 0, - sendIndex = 0, - loadIndex = 0, - fu = $('#fileupload').fileupload({ - sequentialUploads: true, - add: function (e, data) { - addIndex += 1; - if (addIndex === 4) { - data.submit().abort(); - } else { - data.submit(); - } - }, - send: function () { - sendIndex += 1; - }, - done: function () { - loadIndex += 1; - strictEqual(sendIndex, loadIndex, 'upload in order'); - }, - fail: function (e, data) { - strictEqual(data.errorThrown, 'abort', 'upload aborted'); - }, - stop: function () { - start(); - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('add', param); - }); - - asyncTest('limitConcurrentUploads', function () { - expect(12); - var param = {files: [ - {name: '1'}, - {name: '2'}, - {name: '3'}, - {name: '4'}, - {name: '5'}, - {name: '6'}, - {name: '7'}, - {name: '8'}, - {name: '9'}, - {name: '10'}, - {name: '11'}, - {name: '12'} - ]}, - addIndex = 0, - sendIndex = 0, - loadIndex = 0, - fu = $('#fileupload').fileupload({ - limitConcurrentUploads: 3, - add: function (e, data) { - addIndex += 1; - if (addIndex === 4) { - data.submit().abort(); - } else { - data.submit(); - } - }, - send: function () { - sendIndex += 1; - }, - done: function () { - loadIndex += 1; - ok(sendIndex - loadIndex < 3); - }, - fail: function (e, data) { - strictEqual(data.errorThrown, 'abort', 'upload aborted'); - }, - stop: function () { - start(); - } - }); - (fu.data('blueimp-fileupload') || fu.data('fileupload')) - ._isXHRUpload = function () { - return true; - }; - fu.fileupload('add', param); - }); - - if ($.support.xhrFileUpload) { - asyncTest('multipart', function () { - expect(2); - var param = {files: [{ - name: 'test.png', - size: 123, - type: 'image/png' - }]}, - fu = $('#fileupload').fileupload({ - multipart: false, - always: function (e, data) { - strictEqual( - data.contentType, - param.files[0].type, - 'non-multipart upload sets file type as contentType' - ); - strictEqual( - data.headers['Content-Disposition'], - 'attachment; filename="' + param.files[0].name + '"', - 'non-multipart upload sets Content-Disposition header' - ); - start(); - } - }); - fu.fileupload('send', param); - }); - } - - module('UI Initialization', lifecycleUI); - - test('Widget initialization', function () { - var fu = $('#fileupload').fileupload(); - ok(fu.data('blueimp-fileupload') || fu.data('fileupload')); - ok( - $('#fileupload').fileupload('option', 'uploadTemplate').length, - 'Initialized upload template' - ); - ok( - $('#fileupload').fileupload('option', 'downloadTemplate').length, - 'Initialized download template' - ); - }); - - test('Buttonbar event listeners', function () { - var buttonbar = $('#fileupload .fileupload-buttonbar'), - files = [{name: 'test'}]; - expect(4); - $('#fileupload').fileupload({ - send: function () { - ok(true, 'Started file upload via global start button'); - }, - fail: function (e, data) { - ok(true, 'Canceled file upload via global cancel button'); - data.context.remove(); - }, - destroy: function () { - ok(true, 'Delete action called via global delete button'); - } - }); - $('#fileupload').fileupload('add', {files: files}); - buttonbar.find('.cancel').click(); - $('#fileupload').fileupload('add', {files: files}); - buttonbar.find('.start').click(); - buttonbar.find('.cancel').click(); - files[0].deleteUrl = 'http://example.org/banana.jpg'; - ($('#fileupload').data('blueimp-fileupload') || - $('#fileupload').data('fileupload')) - ._renderDownload(files) - .appendTo($('#fileupload .files')).show() - .find('.toggle').click(); - buttonbar.find('.delete').click(); - }); - - module('UI API', lifecycleUI); - - test('destroy', function () { - var buttonbar = $('#fileupload .fileupload-buttonbar'), - files = [{name: 'test'}]; - expect(1); - $('#fileupload').fileupload({ - send: function () { - ok(true, 'This test should not run'); - return false; - } - }) - .fileupload('add', {files: files}) - .fileupload('destroy'); - buttonbar.find('.start').click(function () { - ok(true, 'Clicked global start button'); - return false; - }).click(); - }); - - test('disable/enable', function () { - var buttonbar = $('#fileupload .fileupload-buttonbar'); - $('#fileupload').fileupload(); - $('#fileupload').fileupload('disable'); - strictEqual( - buttonbar.find('input[type=file], button').not(':disabled').length, - 0, - 'Disables the buttonbar buttons' - ); - $('#fileupload').fileupload('enable'); - strictEqual( - buttonbar.find('input[type=file], button').not(':disabled').length, - 4, - 'Enables the buttonbar buttons' - ); - }); - - module('UI Callbacks', lifecycleUI); - - test('destroy', function () { - expect(3); - $('#fileupload').fileupload({ - destroy: function (e, data) { - ok(true, 'Triggers destroy callback'); - strictEqual( - data.url, - 'test', - 'Passes over deletion url parameter' - ); - strictEqual( - data.type, - 'DELETE', - 'Passes over deletion request type parameter' - ); - } - }); - ($('#fileupload').data('blueimp-fileupload') || - $('#fileupload').data('fileupload')) - ._renderDownload([{ - name: 'test', - deleteUrl: 'test', - deleteType: 'DELETE' - }]) - .appendTo($('#fileupload .files')) - .show() - .find('.toggle').click(); - $('#fileupload .fileupload-buttonbar .delete').click(); - }); - - asyncTest('added', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - added: function (e, data) { - start(); - strictEqual( - data.files[0].name, - param.files[0].name, - 'Triggers added callback' - ); - }, - send: function () { - return false; - } - }).fileupload('add', param); - }); - - asyncTest('started', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - started: function () { - start(); - ok('Triggers started callback'); - return false; - }, - sent: function () { - return false; - } - }).fileupload('send', param); - }); - - asyncTest('sent', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - sent: function (e, data) { - start(); - strictEqual( - data.files[0].name, - param.files[0].name, - 'Triggers sent callback' - ); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('completed', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - completed: function () { - start(); - ok('Triggers completed callback'); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('failed', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - failed: function () { - start(); - ok('Triggers failed callback'); - return false; - } - }).fileupload('send', param).abort(); - }); - - asyncTest('stopped', function () { - expect(1); - var param = {files: [{name: 'test'}]}; - $('#fileupload').fileupload({ - stopped: function () { - start(); - ok('Triggers stopped callback'); - return false; - } - }).fileupload('send', param); - }); - - asyncTest('destroyed', function () { - expect(1); - $('#fileupload').fileupload({ - dataType: 'html', - destroyed: function () { - start(); - ok(true, 'Triggers destroyed callback'); - } - }); - ($('#fileupload').data('blueimp-fileupload') || - $('#fileupload').data('fileupload')) - ._renderDownload([{ - name: 'test', - deleteUrl: '.', - deleteType: 'GET' - }]) - .appendTo($('#fileupload .files')) - .show() - .find('.toggle').click(); - $('#fileupload .fileupload-buttonbar .delete').click(); - }); - - module('UI Options', lifecycleUI); - - test('autoUpload', function () { - expect(1); - $('#fileupload') - .fileupload({ - autoUpload: true, - send: function () { - ok(true, 'Started file upload automatically'); - return false; - } - }) - .fileupload('add', {files: [{name: 'test'}]}) - .fileupload('option', 'autoUpload', false) - .fileupload('add', {files: [{name: 'test'}]}); - }); - - test('maxNumberOfFiles', function () { - expect(3); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - maxNumberOfFiles: 3, - singleFileUploads: false, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - }, - progress: $.noop, - progressall: $.noop, - done: $.noop, - stop: $.noop - }) - .fileupload('add', {files: [{name: (addIndex += 1)}]}) - .fileupload('add', {files: [{name: (addIndex += 1)}]}) - .fileupload('add', {files: [{name: (addIndex += 1)}]}) - .fileupload('add', {files: [{name: 'test'}]}); - }); - - test('maxFileSize', function () { - expect(2); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - maxFileSize: 1000, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - return false; - } - }) - .fileupload('add', {files: [{ - name: (addIndex += 1) - }]}) - .fileupload('add', {files: [{ - name: (addIndex += 1), - size: 999 - }]}) - .fileupload('add', {files: [{ - name: 'test', - size: 1001 - }]}) - .fileupload({ - send: function (e, data) { - ok( - !$.blueimp.fileupload.prototype.options - .send.call(this, e, data) - ); - return false; - } - }); - }); - - test('minFileSize', function () { - expect(2); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - minFileSize: 1000, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - return false; - } - }) - .fileupload('add', {files: [{ - name: (addIndex += 1) - }]}) - .fileupload('add', {files: [{ - name: (addIndex += 1), - size: 1001 - }]}) - .fileupload('add', {files: [{ - name: 'test', - size: 999 - }]}) - .fileupload({ - send: function (e, data) { - ok( - !$.blueimp.fileupload.prototype.options - .send.call(this, e, data) - ); - return false; - } - }); - }); - - test('acceptFileTypes', function () { - expect(2); - var addIndex = 0, - sendIndex = 0; - $('#fileupload') - .fileupload({ - autoUpload: true, - acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, - disableImageMetaDataLoad: true, - send: function () { - strictEqual( - sendIndex += 1, - addIndex - ); - return false; - } - }) - .fileupload('add', {files: [{ - name: (addIndex += 1) + '.jpg' - }]}) - .fileupload('add', {files: [{ - name: (addIndex += 1), - type: 'image/jpeg' - }]}) - .fileupload('add', {files: [{ - name: 'test.txt', - type: 'text/plain' - }]}) - .fileupload({ - send: function (e, data) { - ok( - !$.blueimp.fileupload.prototype.options - .send.call(this, e, data) - ); - return false; - } - }); - }); - - test('acceptFileTypes as HTML5 data attribute', function () { - expect(2); - var regExp = /(\.|\/)(gif|jpe?g|png)$/i; - $('#fileupload') - .attr('data-accept-file-types', regExp.toString()) - .fileupload(); - strictEqual( - $.type($('#fileupload').fileupload('option', 'acceptFileTypes')), - $.type(regExp) - ); - strictEqual( - $('#fileupload').fileupload('option', 'acceptFileTypes').toString(), - regExp.toString() - ); - }); - -}); diff --git a/tests/unit/includes/MarkdownTest.php b/tests/unit/includes/MarkdownTest.php index f0e253a58..61600988d 100644 --- a/tests/unit/includes/MarkdownTest.php +++ b/tests/unit/includes/MarkdownTest.php @@ -52,12 +52,12 @@ class MarkdownTest extends UnitTestCase { '  ', '' ], -/* it is not clear why this test fails + 'strong, b, em, i, bib' => [ 'strong bold em italic boitalicld', - '**strong** **bold** _em_ _italic_ **bo_italic_ld**' + '**strong** **bold** *em* *italic* **bo*italic*ld**' ], -*/ + 'empty tags' => [ 'text1 text2 ', 'text1 text2' @@ -70,10 +70,6 @@ class MarkdownTest extends UnitTestCase { '& lt < gt >', '& lt < gt >' ], - 'our escaped HTML entities' => [ - '&_lt_; &_gt_; &_amp_;', - '&\_lt\_; &\_gt\_; &\_amp\_;' - ], 'linebreak' => [ "line1
    line2\nline3", "line1 \nline2 line3" @@ -84,15 +80,15 @@ class MarkdownTest extends UnitTestCase { ], 'unordered list' => [ '', - "- Item 1\n- Item 2\n- Item 3" + "- Item 1\n- Item 2\n- Item **3**" ], 'ordered list' => [ '
    1. Item 1
    2. Item 2
    3. Item 3
    ', - "1. Item 1\n2. Item 2\n3. Item 3" + "1. Item 1\n2. Item 2\n3. Item **3**" ], 'nested lists' => [ '', - "- Item 1\n 1. Item 1a\n 2. Item 1b\n- Item 2" + "- Item 1\n 1. Item 1a\n 2. Item **1b**\n- Item 2" ], 'img' => [ 'alt text', @@ -118,12 +114,10 @@ class MarkdownTest extends UnitTestCase { '<p>HTML text</p>', '`

    HTML text

    `' ], -/* it is not clear why this test fails 'pre' => [ - '
       line with  spaces   
    ', - '` line with spaces `' + '
      one line with spaces  
    ', + "```\n one line with spaces \n```" ], -*/ 'div p' => [ '
    div

    p

    ', "
    div
    p\n\n
    " diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE index f27399a04..f0157a6ed 100644 --- a/vendor/composer/LICENSE +++ b/vendor/composer/LICENSE @@ -1,21 +1,56 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Composer +Upstream-Contact: Jordi Boggiano +Source: https://github.com/composer/composer -Copyright (c) Nils Adermann, Jordi Boggiano +Files: * +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano +License: Expat -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: +Files: src/Composer/Util/TlsHelper.php +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano + 2013, Evan Coury +License: Expat and BSD-2-Clause -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +License: BSD-2-Clause + 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. + . + 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 4b8316c37..f3c814e02 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -300,6 +300,7 @@ return array( 'League\\HTMLToMarkdown\\ElementInterface' => $vendorDir . '/league/html-to-markdown/src/ElementInterface.php', 'League\\HTMLToMarkdown\\Environment' => $vendorDir . '/league/html-to-markdown/src/Environment.php', 'League\\HTMLToMarkdown\\HtmlConverter' => $vendorDir . '/league/html-to-markdown/src/HtmlConverter.php', + 'League\\HTMLToMarkdown\\HtmlConverterInterface' => $vendorDir . '/league/html-to-markdown/src/HtmlConverterInterface.php', 'Michelf\\Markdown' => $vendorDir . '/michelf/php-markdown/Michelf/Markdown.php', 'Michelf\\MarkdownExtra' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownExtra.php', 'Michelf\\MarkdownInterface' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownInterface.php', @@ -804,6 +805,7 @@ return array( 'Text_LanguageDetect_Exception' => $vendorDir . '/pear/text_languagedetect/Text/LanguageDetect/Exception.php', 'Text_LanguageDetect_ISO639' => $vendorDir . '/pear/text_languagedetect/Text/LanguageDetect/ISO639.php', 'Text_LanguageDetect_Parser' => $vendorDir . '/pear/text_languagedetect/Text/LanguageDetect/Parser.php', + 'UploadHandler' => $vendorDir . '/blueimp/jquery-file-upload/server/php/UploadHandler.php', 'Zotlabs\\Access\\AccessList' => $baseDir . '/Zotlabs/Access/AccessList.php', 'Zotlabs\\Access\\PermissionLimits' => $baseDir . '/Zotlabs/Access/PermissionLimits.php', 'Zotlabs\\Access\\PermissionRoles' => $baseDir . '/Zotlabs/Access/PermissionRoles.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 0202e148c..d55227eb1 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -468,6 +468,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'League\\HTMLToMarkdown\\ElementInterface' => __DIR__ . '/..' . '/league/html-to-markdown/src/ElementInterface.php', 'League\\HTMLToMarkdown\\Environment' => __DIR__ . '/..' . '/league/html-to-markdown/src/Environment.php', 'League\\HTMLToMarkdown\\HtmlConverter' => __DIR__ . '/..' . '/league/html-to-markdown/src/HtmlConverter.php', + 'League\\HTMLToMarkdown\\HtmlConverterInterface' => __DIR__ . '/..' . '/league/html-to-markdown/src/HtmlConverterInterface.php', 'Michelf\\Markdown' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/Markdown.php', 'Michelf\\MarkdownExtra' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownExtra.php', 'Michelf\\MarkdownInterface' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownInterface.php', @@ -972,6 +973,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'Text_LanguageDetect_Exception' => __DIR__ . '/..' . '/pear/text_languagedetect/Text/LanguageDetect/Exception.php', 'Text_LanguageDetect_ISO639' => __DIR__ . '/..' . '/pear/text_languagedetect/Text/LanguageDetect/ISO639.php', 'Text_LanguageDetect_Parser' => __DIR__ . '/..' . '/pear/text_languagedetect/Text/LanguageDetect/Parser.php', + 'UploadHandler' => __DIR__ . '/..' . '/blueimp/jquery-file-upload/server/php/UploadHandler.php', 'Zotlabs\\Access\\AccessList' => __DIR__ . '/../..' . '/Zotlabs/Access/AccessList.php', 'Zotlabs\\Access\\PermissionLimits' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionLimits.php', 'Zotlabs\\Access\\PermissionRoles' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionRoles.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index eac4cebde..af845828e 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,4 +1,61 @@ [ + { + "name": "blueimp/jquery-file-upload", + "version": "v9.25.1", + "version_normalized": "9.25.1.0", + "source": { + "type": "git", + "url": "https://github.com/vkhramtsov/jQuery-File-Upload.git", + "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/28891f9b2bc339bcc1ca8d548e5401e8563bf04b", + "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b", + "shasum": "" + }, + "time": "2018-10-26T07:21:48+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "server/php/UploadHandler.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sebastian Tschan", + "homepage": "https://blueimp.net" + } + ], + "description": "File Upload widget for jQuery.", + "homepage": "https://github.com/blueimp/jQuery-File-Upload", + "keywords": [ + "bootstrap", + "chunk", + "cross-domain", + "cross-site", + "drag", + "drop", + "file", + "gae", + "go", + "jquery", + "multiple", + "php", + "preview", + "progress", + "python", + "resume", + "selection", + "upload", + "widget" + ] + }, { "name": "bshaffer/oauth2-server-php", "version": "v1.10.0", @@ -156,17 +213,17 @@ }, { "name": "league/html-to-markdown", - "version": "4.7.0", - "version_normalized": "4.7.0.0", + "version": "4.8.0", + "version_normalized": "4.8.0.0", "source": { "type": "git", "url": "https://github.com/thephpleague/html-to-markdown.git", - "reference": "76c076483cef89860d32a3fd25312f5a42848a8c" + "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/76c076483cef89860d32a3fd25312f5a42848a8c", - "reference": "76c076483cef89860d32a3fd25312f5a42848a8c", + "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d", + "reference": "f9a879a068c68ff47b722de63f58bec79e448f9d", "shasum": "" }, "require": { @@ -179,14 +236,14 @@ "phpunit/phpunit": "4.*", "scrutinizer/ocular": "~1.1" }, - "time": "2018-05-19T23:47:12+00:00", + "time": "2018-09-18T12:18:08+00:00", "bin": [ "bin/html-to-markdown" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8-dev" + "dev-master": "4.9-dev" } }, "installation-source": "dist", @@ -200,17 +257,17 @@ "MIT" ], "authors": [ - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "http://www.colinodell.com", - "role": "Lead Developer" - }, { "name": "Nick Cernis", "email": "nick@cern.is", "homepage": "http://modernnerd.net", "role": "Original Author" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" } ], "description": "An HTML-to-markdown conversion helper for PHP", @@ -533,17 +590,17 @@ }, { "name": "sabre/dav", - "version": "3.2.2", - "version_normalized": "3.2.2.0", + "version": "3.2.3", + "version_normalized": "3.2.3.0", "source": { "type": "git", "url": "https://github.com/sabre-io/dav.git", - "reference": "e987775e619728f12205606c9cc3ee565ffb1516" + "reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/dav/zipball/e987775e619728f12205606c9cc3ee565ffb1516", - "reference": "e987775e619728f12205606c9cc3ee565ffb1516", + "url": "https://api.github.com/repos/sabre-io/dav/zipball/a9780ce4f35560ecbd0af524ad32d9d2c8954b80", + "reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80", "shasum": "" }, "require": { @@ -574,7 +631,7 @@ "ext-curl": "*", "ext-pdo": "*" }, - "time": "2017-02-15T03:06:08+00:00", + "time": "2018-10-19T09:58:27+00:00", "bin": [ "bin/sabredav", "bin/naturalselection" @@ -1029,23 +1086,23 @@ }, { "name": "smarty/smarty", - "version": "v3.1.32", - "version_normalized": "3.1.32.0", + "version": "v3.1.33", + "version_normalized": "3.1.33.0", "source": { "type": "git", "url": "https://github.com/smarty-php/smarty.git", - "reference": "ac9d4b587e5bf53381e21881820a9830765cb459" + "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smarty-php/smarty/zipball/ac9d4b587e5bf53381e21881820a9830765cb459", - "reference": "ac9d4b587e5bf53381e21881820a9830765cb459", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f", + "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f", "shasum": "" }, "require": { "php": ">=5.2" }, - "time": "2018-04-24T14:53:33+00:00", + "time": "2018-09-12T20:54:16+00:00", "type": "library", "extra": { "branch-alias": { diff --git a/vendor/league/html-to-markdown/CHANGELOG.md b/vendor/league/html-to-markdown/CHANGELOG.md index 981ffd594..ab07c94f5 100644 --- a/vendor/league/html-to-markdown/CHANGELOG.md +++ b/vendor/league/html-to-markdown/CHANGELOG.md @@ -4,6 +4,24 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip ## [Unreleased][unreleased] +## [4.8.0] - 2018-09-18 +### Added + - Added support for email auto-linking + - Added a new interface (`HtmlConverterInterface`) for the main `HtmlConverter` class + - Added additional test cases (#14) + +### Changed + - The `italic_style` option now defaults to `'*'` so that in-word emphasis is handled properly (#75) + +### Fixed + - Fixed several issues of `` and `
    ` tags not converting to blocks or inlines properly (#26, #70, #102, #140, #161, #162)
    + - Fixed in-word emphasis using underscores as delimiter (#75)
    + - Fixed character escaping inside of `
    ` elements + - Fixed header edge cases + +### Deprecated + - The `bold_style` and `italic_style` options have been deprecated (#75) + ## [4.7.0] - 2018-05-19 ### Added - Added `setOptions()` function for chainable calling (#149) @@ -217,7 +235,8 @@ not ideally set, so this releases fixes that. Moving forwards this should reduce ### Added - Initial release -[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.7.0...master +[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...master +[4.8.0]: https://github.com/thephpleague/html-to-markdown/compare/4.7.0...4.8.0 [4.7.0]: https://github.com/thephpleague/html-to-markdown/compare/4.6.2...4.7.0 [4.6.2]: https://github.com/thephpleague/html-to-markdown/compare/4.6.1...4.6.2 [4.6.1]: https://github.com/thephpleague/html-to-markdown/compare/4.6.0...4.6.1 diff --git a/vendor/league/html-to-markdown/composer.json b/vendor/league/html-to-markdown/composer.json index c79230562..53403916e 100644 --- a/vendor/league/html-to-markdown/composer.json +++ b/vendor/league/html-to-markdown/composer.json @@ -9,7 +9,7 @@ { "name": "Colin O'Dell", "email": "colinodell@gmail.com", - "homepage": "http://www.colinodell.com", + "homepage": "https://www.colinodell.com", "role": "Lead Developer" }, { @@ -42,7 +42,7 @@ "bin": ["bin/html-to-markdown"], "extra": { "branch-alias": { - "dev-master": "4.8-dev" + "dev-master": "4.9-dev" } } } diff --git a/vendor/league/html-to-markdown/src/Configuration.php b/vendor/league/html-to-markdown/src/Configuration.php index 2943383aa..5bc8d5503 100644 --- a/vendor/league/html-to-markdown/src/Configuration.php +++ b/vendor/league/html-to-markdown/src/Configuration.php @@ -12,6 +12,8 @@ class Configuration public function __construct(array $config = array()) { $this->config = $config; + + $this->checkForDeprecatedOptions($config); } /** @@ -19,6 +21,7 @@ class Configuration */ public function merge(array $config = array()) { + $this->checkForDeprecatedOptions($config); $this->config = array_replace_recursive($this->config, $config); } @@ -27,6 +30,7 @@ class Configuration */ public function replace(array $config = array()) { + $this->checkForDeprecatedOptions($config); $this->config = $config; } @@ -36,6 +40,7 @@ class Configuration */ public function setOption($key, $value) { + $this->checkForDeprecatedOptions(array($key => $value)); $this->config[$key] = $value; } @@ -57,4 +62,15 @@ class Configuration return $this->config[$key]; } + + private function checkForDeprecatedOptions(array $config) + { + foreach ($config as $key => $value) { + if ($key === 'bold_style' && $value !== '**') { + @trigger_error('Customizing the bold_style option is deprecated and may be removed in the next major version', E_USER_DEPRECATED); + } elseif ($key === 'italic_style' && $value !== '*') { + @trigger_error('Customizing the italic_style option is deprecated and may be removed in the next major version', E_USER_DEPRECATED); + } + } + } } diff --git a/vendor/league/html-to-markdown/src/Converter/CodeConverter.php b/vendor/league/html-to-markdown/src/Converter/CodeConverter.php index e536362ee..39e6a7bc4 100644 --- a/vendor/league/html-to-markdown/src/Converter/CodeConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/CodeConverter.php @@ -13,7 +13,7 @@ class CodeConverter implements ConverterInterface */ public function convert(ElementInterface $element) { - $language = null; + $language = ''; // Checking for language class on the code block $classes = $element->getAttribute('class'); @@ -24,8 +24,7 @@ class CodeConverter implements ConverterInterface foreach ($classes as $class) { if (strpos($class, 'language-') !== false) { // Found one, save it as the selected language and stop looping over the classes. - // The space after the language avoids gluing the actual code with the language tag - $language = str_replace('language-', '', $class) . ' '; + $language = str_replace('language-', '', $class); break; } } @@ -39,14 +38,13 @@ class CodeConverter implements ConverterInterface $code = preg_replace('/]*>/', '', $code); $code = str_replace('', '', $code); - // Checking if the code has multiple lines - $lines = preg_split('/\r\n|\r|\n/', $code); - if (count($lines) > 1) { - // Multiple lines detected, adding three backticks and newlines - $markdown .= '```' . $language . "\n" . $code . "\n" . '```' . "\n\n"; + // Checking if it's a code block or span + if ($this->shouldBeBlock($element, $code)) { + // Code block detected, newlines will be added in parent + $markdown .= '```' . $language . "\n" . $code . "\n" . '```'; } else { - // One line of code, wrapping it on one backtick. - $markdown .= '`' . $language . $code . '`'; + // One line of code, wrapping it on one backtick, removing new lines + $markdown .= '`' . preg_replace('/\r\n|\r|\n/', '', $code) . '`'; } return $markdown; @@ -59,4 +57,23 @@ class CodeConverter implements ConverterInterface { return array('code'); } + + /** + * @param ElementInterface $element + * @param string $code + * + * @return bool + */ + private function shouldBeBlock(ElementInterface $element, $code) + { + if ($element->getParent()->getTagName() == 'pre') { + return true; + } + + if (preg_match('/[^\s]` `/', $code)) { + return true; + } + + return false; + } } diff --git a/vendor/league/html-to-markdown/src/Converter/HeaderConverter.php b/vendor/league/html-to-markdown/src/Converter/HeaderConverter.php index d117e7d36..05d4fe81e 100644 --- a/vendor/league/html-to-markdown/src/Converter/HeaderConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/HeaderConverter.php @@ -34,6 +34,10 @@ class HeaderConverter implements ConverterInterface, ConfigurationAwareInterface $level = (int) substr($element->getTagName(), 1, 1); $style = $this->config->getOption('header_style', self::STYLE_SETEXT); + if (strlen($element->getValue()) === 0) { + return ''; + } + if (($level === 1 || $level === 2) && !$element->isDescendantOf('blockquote') && $style === self::STYLE_SETEXT) { return $this->createSetextHeader($level, $element->getValue()); } diff --git a/vendor/league/html-to-markdown/src/Converter/LinkConverter.php b/vendor/league/html-to-markdown/src/Converter/LinkConverter.php index 74b49a778..c82b70e97 100644 --- a/vendor/league/html-to-markdown/src/Converter/LinkConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/LinkConverter.php @@ -21,6 +21,8 @@ class LinkConverter implements ConverterInterface $markdown = '[' . $text . '](' . $href . ' "' . $title . '")'; } elseif ($href === $text && $this->isValidAutolink($href)) { $markdown = '<' . $href . '>'; + } elseif ($href === 'mailto:' . $text && $this->isValidEmail($text)) { + $markdown = '<' . $text . '>'; } else { $markdown = '[' . $text . '](' . $href . ')'; } @@ -49,4 +51,15 @@ class LinkConverter implements ConverterInterface { return preg_match('/^[A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]*/i', $href) === 1; } + + /** + * @param string $email + * + * @return bool + */ + private function isValidEmail($email) + { + // Email validation is messy business, but this should cover most cases + return filter_var($email, FILTER_VALIDATE_EMAIL); + } } diff --git a/vendor/league/html-to-markdown/src/Converter/PreformattedConverter.php b/vendor/league/html-to-markdown/src/Converter/PreformattedConverter.php index 3b77ba10b..321c898b1 100644 --- a/vendor/league/html-to-markdown/src/Converter/PreformattedConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/PreformattedConverter.php @@ -13,8 +13,6 @@ class PreformattedConverter implements ConverterInterface */ public function convert(ElementInterface $element) { - $markdown = ''; - $pre_content = html_entity_decode($element->getChildrenAsString()); $pre_content = str_replace(array('
    ', '
    '), '', $pre_content); @@ -28,28 +26,22 @@ class PreformattedConverter implements ConverterInterface $firstBacktick = strpos(trim($pre_content), '`'); $lastBacktick = strrpos(trim($pre_content), '`'); if ($firstBacktick === 0 && $lastBacktick === strlen(trim($pre_content)) - 1) { - return $pre_content; + return $pre_content . "\n\n"; } // If the execution reaches this point it means it's just a pre tag, with no code tag nested // Empty lines are a special case if ($pre_content === '') { - return "```\n```\n"; + return "```\n```\n\n"; } // Normalizing new lines - $pre_content = preg_replace('/\r\n|\r|\n/', PHP_EOL, $pre_content); - - // Is it a single line? - if (strpos($pre_content, PHP_EOL) === false) { - // One line of code, wrapping it on one backtick. - return '`' . $pre_content . '`'; - } + $pre_content = preg_replace('/\r\n|\r|\n/', "\n", $pre_content); // Ensure there's a newline at the end - if (strrpos($pre_content, PHP_EOL) !== strlen($pre_content) - 1) { - $pre_content .= PHP_EOL; + if (strrpos($pre_content, "\n") !== strlen($pre_content) - strlen("\n")) { + $pre_content .= "\n"; } // Use three backticks diff --git a/vendor/league/html-to-markdown/src/Converter/TextConverter.php b/vendor/league/html-to-markdown/src/Converter/TextConverter.php index d6d91e16f..fcd466094 100644 --- a/vendor/league/html-to-markdown/src/Converter/TextConverter.php +++ b/vendor/league/html-to-markdown/src/Converter/TextConverter.php @@ -22,7 +22,9 @@ class TextConverter implements ConverterInterface $markdown = preg_replace('~\s+~u', ' ', $markdown); // Escape the following characters: '*', '_', '[', ']' and '\' - $markdown = preg_replace('~([*_\\[\\]\\\\])~u', '\\\\$1', $markdown); + if ($element->getParent() && $element->getParent()->getTagName() !== 'div') { + $markdown = preg_replace('~([*_\\[\\]\\\\])~u', '\\\\$1', $markdown); + } $markdown = preg_replace('~^#~u', '\\\\#', $markdown); diff --git a/vendor/league/html-to-markdown/src/HtmlConverter.php b/vendor/league/html-to-markdown/src/HtmlConverter.php index 155369f56..3381e1e1e 100644 --- a/vendor/league/html-to-markdown/src/HtmlConverter.php +++ b/vendor/league/html-to-markdown/src/HtmlConverter.php @@ -14,7 +14,7 @@ namespace League\HTMLToMarkdown; * * @license http://www.opensource.org/licenses/mit-license.php MIT */ -class HtmlConverter +class HtmlConverter implements HtmlConverterInterface { /** * @var Environment @@ -35,8 +35,8 @@ class HtmlConverter 'header_style' => 'setext', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2 'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML 'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output. - 'bold_style' => '**', // Set to '__' if you prefer the underlined style - 'italic_style' => '_', // Set to '*' if you prefer the asterisk style + 'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style + 'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style 'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script' 'hard_break' => false, // Set to true to turn
    into `\n` instead of ` \n` 'list_item_style' => '-', // Set the default character for each
  1. in a
      . Can be '-', '*', or '+' diff --git a/vendor/sabre/dav/CHANGELOG.md b/vendor/sabre/dav/CHANGELOG.md index 0bccc995c..cda2564e1 100644 --- a/vendor/sabre/dav/CHANGELOG.md +++ b/vendor/sabre/dav/CHANGELOG.md @@ -1,6 +1,12 @@ ChangeLog ========= +3.2.3 (2018-10-19) +------------------ + +* #982: Make sure that files that are siblings of directories, are reported + as files (@nickvergessen) + 3.2.2 (2017-02-14) ------------------ diff --git a/vendor/sabre/dav/bin/build.php b/vendor/sabre/dav/bin/build.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/googlecode_upload.py b/vendor/sabre/dav/bin/googlecode_upload.py old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto20.php b/vendor/sabre/dav/bin/migrateto20.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto21.php b/vendor/sabre/dav/bin/migrateto21.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto30.php b/vendor/sabre/dav/bin/migrateto30.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/migrateto32.php b/vendor/sabre/dav/bin/migrateto32.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/bin/sabredav.php b/vendor/sabre/dav/bin/sabredav.php old mode 100755 new mode 100644 diff --git a/vendor/sabre/dav/lib/CardDAV/Xml/Filter/AddressData.php b/vendor/sabre/dav/lib/CardDAV/Xml/Filter/AddressData.php index a130cd61d..5b7b2ee17 100644 --- a/vendor/sabre/dav/lib/CardDAV/Xml/Filter/AddressData.php +++ b/vendor/sabre/dav/lib/CardDAV/Xml/Filter/AddressData.php @@ -52,12 +52,15 @@ class AddressData implements XmlDeserializable { ]; $elems = (array)$reader->parseInnerTree(); + $elems = array_filter($elems, function($element) { + return $element['name'] === '{urn:ietf:params:xml:ns:carddav}prop' && + isset($element['attributes']['name']); + }); $result['addressDataProperties'] = array_map(function($element) { return $element['attributes']['name']; }, $elems); return $result; - } } diff --git a/vendor/sabre/dav/lib/DAV/Server.php b/vendor/sabre/dav/lib/DAV/Server.php index 6805ec0b0..f7fcf3057 100644 --- a/vendor/sabre/dav/lib/DAV/Server.php +++ b/vendor/sabre/dav/lib/DAV/Server.php @@ -893,15 +893,16 @@ class Server extends EventEmitter implements LoggerAwareInterface { $newDepth--; } + $propertyNames = $propFind->getRequestedProperties(); + $propFindType = !empty($propertyNames) ? PropFind::NORMAL : PropFind::ALLPROPS; + foreach ($this->tree->getChildren($path) as $childNode) { - $subPropFind = clone $propFind; - $subPropFind->setDepth($newDepth); if ($path !== '') { $subPath = $path . '/' . $childNode->getName(); } else { $subPath = $childNode->getName(); } - $subPropFind->setPath($subPath); + $subPropFind = new PropFind($subPath, $propertyNames, $newDepth, $propFindType); yield [ $subPropFind, diff --git a/vendor/sabre/dav/lib/DAV/Tree.php b/vendor/sabre/dav/lib/DAV/Tree.php index 5d2792503..7c04f0915 100644 --- a/vendor/sabre/dav/lib/DAV/Tree.php +++ b/vendor/sabre/dav/lib/DAV/Tree.php @@ -298,7 +298,9 @@ class Tree { */ protected function copyNode(INode $source, ICollection $destinationParent, $destinationName = null) { - if (!$destinationName) $destinationName = $source->getName(); + if ((string)$destinationName === '') { + $destinationName = $source->getName(); + } if ($source instanceof IFile) { diff --git a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php index 455403aff..917f5ec3f 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/Auth/Backend/AbstractBasicTest.php @@ -60,7 +60,7 @@ class AbstractBasicTest extends \PHPUnit_Framework_TestCase { $backend->setRealm('writing unittests on a saturday night'); $backend->challenge($request, $response); - $this->assertEquals( + $this->assertContains( 'Basic realm="writing unittests on a saturday night"', $response->getHeader('WWW-Authenticate') ); diff --git a/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php b/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php index e719e38d5..c70d17a22 100644 --- a/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php +++ b/vendor/sabre/dav/tests/Sabre/DAV/TreeTest.php @@ -24,6 +24,22 @@ class TreeTest extends \PHPUnit_Framework_TestCase { } + function testCopyFile() { + + $tree = new TreeMock(); + $tree->copy('hi/file', 'hi/newfile'); + + $this->assertArrayHasKey('newfile', $tree->getNodeForPath('hi')->newFiles); + } + + function testCopyFile0() { + + $tree = new TreeMock(); + $tree->copy('hi/file', 'hi/0'); + + $this->assertArrayHasKey('0', $tree->getNodeForPath('hi')->newFiles); + } + function testMove() { $tree = new TreeMock(); diff --git a/vendor/smarty/smarty/NEW_FEATURES.txt b/vendor/smarty/smarty/NEW_FEATURES.txt index 7632b07ea..b3289dfc1 100644 --- a/vendor/smarty/smarty/NEW_FEATURES.txt +++ b/vendor/smarty/smarty/NEW_FEATURES.txt @@ -2,7 +2,14 @@ This file contains a brief description of new features which have been added to Smarty 3.1 -Smarty 3.1.32 New tags for inheritance parent and child +Smarty 3.1.33-dev + Variable capture name in Smarty special variable + ================================================ + {$smarty.capture.$foo} can now be used to access the content of a named + capture block + +Smarty 3.1.32 + New tags for inheritance parent and child ========================================= {parent} == {$smarty.block.parent} {child} == {$smarty.block.child} diff --git a/vendor/smarty/smarty/change_log.txt b/vendor/smarty/smarty/change_log.txt index 5765a1718..70762eda5 100644 --- a/vendor/smarty/smarty/change_log.txt +++ b/vendor/smarty/smarty/change_log.txt @@ -1,4 +1,46 @@ -===== 3.1.32 ===== (24.04.2018) +===== 3.1.33 release ===== 12.09.2018 +===== 3.1.33-dev-12 ===== +03.09.2018 + - bugfix {foreach} using new style property access like {$item@property} on + Smarty 2 style named foreach loop could produce errors https://github.com/smarty-php/smarty/issues/484 + +31.08.2018 + - bugfix some custom left and right delimiters like '{^' '^}' did not work + https://github.com/smarty-php/smarty/issues/450 https://github.com/smarty-php/smarty/pull/482 + + - reformating for PSR-2 coding standards https://github.com/smarty-php/smarty/pull/483 + + - bugfix on Windows absolute filepathes did fail if the drive letter was followed by a linux DIRECTORY_SEPARATOR + like C:/ at Smarty > 3.1.33-dev-5 https://github.com/smarty-php/smarty/issues/451 + + - PSR-2 code style fixes for config and template file Lexer/Parser generated with + the Smarty Lexer/Parser generator from https://github.com/smarty-php/smarty-lexer + https://github.com/smarty-php/smarty/pull/483 + +26.08.2018 + - bugfix/enhancement {capture} allow variable as capture block name in Smarty special variable + like $smarty.capture.$foo https://github.com/smarty-php/smarty/issues/478 https://github.com/smarty-php/smarty/pull/481 + +===== 3.1.33-dev-6 ===== +19.08.2018 + - fix PSR-2 coding standards and PHPDoc blocks https://github.com/smarty-php/smarty/pull/452 + https://github.com/smarty-php/smarty/pull/475 + https://github.com/smarty-php/smarty/pull/473 + - bugfix PHP5.2 compatibility https://github.com/smarty-php/smarty/pull/472 + +===== 3.1.33-dev-4 ===== +17.05.2018 + - bugfix strip-block produces different output in Smarty v3.1.32 https://github.com/smarty-php/smarty/issues/436 + - bugfix Smarty::compileAllTemplates ignores `$extension` parameter https://github.com/smarty-php/smarty/issues/437 + https://github.com/smarty-php/smarty/pull/438 + - improvement do not compute total property in {foreach} if not needed https://github.com/smarty-php/smarty/issues/443 + - bugfix plugins may not be loaded when setMergeCompiledIncludes is true https://github.com/smarty-php/smarty/issues/435 + +26.04.2018 + - bugfix regarding Security Vulnerability did not solve the problem under Linux. + Security issue CVE-2018-16831 + +===== 3.1.32 ===== (24.04.2018) 24.04.2018 - bugfix possible Security Vulnerability in Smarty_Security class. diff --git a/vendor/smarty/smarty/composer.json b/vendor/smarty/smarty/composer.json index 5064c8ce3..5007517bc 100644 --- a/vendor/smarty/smarty/composer.json +++ b/vendor/smarty/smarty/composer.json @@ -2,7 +2,9 @@ "name": "smarty/smarty", "type": "library", "description": "Smarty - the compiling PHP template engine", - "keywords": ["templating"], + "keywords": [ + "templating" + ], "homepage": "http://www.smarty.net", "license": "LGPL-3.0", "authors": [ @@ -28,12 +30,13 @@ "php": ">=5.2" }, "autoload": { - "files": ["libs/bootstrap.php"] + "files": [ + "libs/bootstrap.php" + ] }, "extra": { "branch-alias": { "dev-master": "3.1.x-dev" } } - -} +} \ No newline at end of file diff --git a/vendor/smarty/smarty/demo/index.php b/vendor/smarty/smarty/demo/index.php index b67c217be..3aed37168 100644 --- a/vendor/smarty/smarty/demo/index.php +++ b/vendor/smarty/smarty/demo/index.php @@ -4,27 +4,32 @@ * * @package Example-application */ - require '../libs/Smarty.class.php'; - $smarty = new Smarty; - //$smarty->force_compile = true; $smarty->debugging = true; $smarty->caching = true; $smarty->cache_lifetime = 120; - $smarty->assign("Name", "Fred Irving Johnathan Bradley Peppergill", true); $smarty->assign("FirstName", array("John", "Mary", "James", "Henry")); $smarty->assign("LastName", array("Doe", "Smith", "Johnson", "Case")); -$smarty->assign("Class", array(array("A", "B", "C", "D"), array("E", "F", "G", "H"), array("I", "J", "K", "L"), - array("M", "N", "O", "P"))); - -$smarty->assign("contacts", array(array("phone" => "1", "fax" => "2", "cell" => "3"), - array("phone" => "555-4444", "fax" => "555-3333", "cell" => "760-1234"))); - +$smarty->assign( + "Class", + array( + array("A", "B", "C", "D"), + array("E", "F", "G", "H"), + array("I", "J", "K", "L"), + array("M", "N", "O", "P") + ) +); +$smarty->assign( + "contacts", + array( + array("phone" => "1", "fax" => "2", "cell" => "3"), + array("phone" => "555-4444", "fax" => "555-3333", "cell" => "760-1234") + ) +); $smarty->assign("option_values", array("NY", "NE", "KS", "IA", "OK", "TX")); $smarty->assign("option_output", array("New York", "Nebraska", "Kansas", "Iowa", "Oklahoma", "Texas")); $smarty->assign("option_selected", "NE"); - $smarty->display('index.tpl'); diff --git a/vendor/smarty/smarty/demo/plugins/cacheresource.apc.php b/vendor/smarty/smarty/demo/plugins/cacheresource.apc.php index ed55ec846..7867cc598 100644 --- a/vendor/smarty/smarty/demo/plugins/cacheresource.apc.php +++ b/vendor/smarty/smarty/demo/plugins/cacheresource.apc.php @@ -11,6 +11,11 @@ */ class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore { + /** + * Smarty_CacheResource_Apc constructor. + * + * @throws \Exception + */ public function __construct() { // test if APC is present @@ -22,7 +27,7 @@ class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore /** * Read values for a set of keys from cache * - * @param array $keys list of keys to fetch + * @param array $keys list of keys to fetch * * @return array list of values with the given keys used as indexes * @return boolean true on success, false on failure @@ -34,15 +39,14 @@ class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore foreach ($res as $k => $v) { $_res[ $k ] = $v; } - return $_res; } /** * Save values for a set of keys to cache * - * @param array $keys list of values to save - * @param int $expire expiration time + * @param array $keys list of values to save + * @param int $expire expiration time * * @return boolean true on success, false on failure */ @@ -51,14 +55,13 @@ class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore foreach ($keys as $k => $v) { apc_store($k, $v, $expire); } - return true; } /** * Remove values from cache * - * @param array $keys list of keys to delete + * @param array $keys list of keys to delete * * @return boolean true on success, false on failure */ @@ -67,7 +70,6 @@ class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore foreach ($keys as $k) { apc_delete($k); } - return true; } diff --git a/vendor/smarty/smarty/demo/plugins/cacheresource.memcache.php b/vendor/smarty/smarty/demo/plugins/cacheresource.memcache.php index 945beb349..9c8855c31 100644 --- a/vendor/smarty/smarty/demo/plugins/cacheresource.memcache.php +++ b/vendor/smarty/smarty/demo/plugins/cacheresource.memcache.php @@ -19,6 +19,9 @@ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore */ protected $memcache = null; + /** + * Smarty_CacheResource_Memcache constructor. + */ public function __construct() { if (class_exists('Memcached')) { @@ -32,7 +35,7 @@ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore /** * Read values for a set of keys from cache * - * @param array $keys list of keys to fetch + * @param array $keys list of keys to fetch * * @return array list of values with the given keys used as indexes * @return boolean true on success, false on failure @@ -50,15 +53,14 @@ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore foreach ($res as $k => $v) { $_res[ $lookup[ $k ] ] = $v; } - return $_res; } /** * Save values for a set of keys to cache * - * @param array $keys list of values to save - * @param int $expire expiration time + * @param array $keys list of values to save + * @param int $expire expiration time * * @return boolean true on success, false on failure */ @@ -68,14 +70,13 @@ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore $k = sha1($k); $this->memcache->set($k, $v, 0, $expire); } - return true; } /** * Remove values from cache * - * @param array $keys list of keys to delete + * @param array $keys list of keys to delete * * @return boolean true on success, false on failure */ @@ -85,7 +86,6 @@ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore $k = sha1($k); $this->memcache->delete($k); } - return true; } @@ -96,6 +96,6 @@ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore */ protected function purge() { - $this->memcache->flush(); + return $this->memcache->flush(); } } diff --git a/vendor/smarty/smarty/demo/plugins/cacheresource.mysql.php b/vendor/smarty/smarty/demo/plugins/cacheresource.mysql.php index 027b93766..c5037eb13 100644 --- a/vendor/smarty/smarty/demo/plugins/cacheresource.mysql.php +++ b/vendor/smarty/smarty/demo/plugins/cacheresource.mysql.php @@ -24,38 +24,55 @@ */ class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom { - // PDO instance + /** + * @var \PDO + */ protected $db; + /** + * @var \PDOStatement + */ protected $fetch; + /** + * @var \PDOStatement + */ protected $fetchTimestamp; + /** + * @var \PDOStatement + */ protected $save; + /** + * Smarty_CacheResource_Mysql constructor. + * + * @throws \SmartyException + */ public function __construct() { try { $this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty"); - } - catch (PDOException $e) { + } catch (PDOException $e) { throw new SmartyException('Mysql Resource failed: ' . $e->getMessage()); } $this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id'); $this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id'); - $this->save = $this->db->prepare('REPLACE INTO output_cache (id, name, cache_id, compile_id, content) - VALUES (:id, :name, :cache_id, :compile_id, :content)'); + $this->save = $this->db->prepare( + 'REPLACE INTO output_cache (id, name, cache_id, compile_id, content) + VALUES (:id, :name, :cache_id, :compile_id, :content)' + ); } /** * fetch cached content and its modification time from data source * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param string $content cached content - * @param integer $mtime cache modification timestamp (epoch) + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param string $content cached content + * @param integer $mtime cache modification timestamp (epoch) * * @return void */ @@ -76,12 +93,13 @@ class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom /** * Fetch cached content's modification timestamp from data source * - * @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the complete cached content. + * @note implementing this method is optional. Only implement it if modification times can be accessed faster than + * loading the complete cached content. * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id * * @return integer|boolean timestamp (epoch) the template was modified, or false if not found */ @@ -90,37 +108,40 @@ class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom $this->fetchTimestamp->execute(array('id' => $id)); $mtime = strtotime($this->fetchTimestamp->fetchColumn()); $this->fetchTimestamp->closeCursor(); - return $mtime; } /** * Save content to cache * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param integer|null $exp_time seconds till expiration time in seconds or null - * @param string $content content to cache + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer|null $exp_time seconds till expiration time in seconds or null + * @param string $content content to cache * * @return boolean success */ protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content) { - $this->save->execute(array('id' => $id, 'name' => $name, 'cache_id' => $cache_id, 'compile_id' => $compile_id, - 'content' => $content,)); - + $this->save->execute( + array('id' => $id, + 'name' => $name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'content' => $content,) + ); return !!$this->save->rowCount(); } /** * Delete content from cache * - * @param string $name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param integer|null $exp_time seconds till expiration or null + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer|null $exp_time seconds till expiration or null * * @return integer number of deleted caches */ @@ -130,8 +151,7 @@ class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) { // returning the number of deleted caches would require a second query to count them $query = $this->db->query('TRUNCATE TABLE output_cache'); - - return - 1; + return -1; } // build the filter $where = array(); @@ -149,12 +169,15 @@ class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom } // equal test cache_id and match sub-groups if ($cache_id !== null) { - $where[] = '(cache_id = ' . $this->db->quote($cache_id) . ' OR cache_id LIKE ' . - $this->db->quote($cache_id . '|%') . ')'; + $where[] = + '(cache_id = ' . + $this->db->quote($cache_id) . + ' OR cache_id LIKE ' . + $this->db->quote($cache_id . '|%') . + ')'; } // run delete query $query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where)); - return $query->rowCount(); } } diff --git a/vendor/smarty/smarty/demo/plugins/cacheresource.pdo.php b/vendor/smarty/smarty/demo/plugins/cacheresource.pdo.php index 24a94c1a0..a80cd698e 100644 --- a/vendor/smarty/smarty/demo/plugins/cacheresource.pdo.php +++ b/vendor/smarty/smarty/demo/plugins/cacheresource.pdo.php @@ -29,28 +29,27 @@ */ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom { - - protected $fetchStatements = Array('default' => 'SELECT %2$s + /** + * @var string[] + */ + protected $fetchStatements = array('default' => 'SELECT %2$s FROM %1$s WHERE 1 AND id = :id AND cache_id IS NULL AND compile_id IS NULL', - 'withCacheId' => 'SELECT %2$s FROM %1$s WHERE 1 AND id = :id AND cache_id = :cache_id AND compile_id IS NULL', - 'withCompileId' => 'SELECT %2$s FROM %1$s WHERE 1 AND id = :id AND compile_id = :compile_id AND cache_id IS NULL', - 'withCacheIdAndCompileId' => 'SELECT %2$s FROM %1$s WHERE 1 @@ -58,6 +57,9 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom AND cache_id = :cache_id AND compile_id = :compile_id'); + /** + * @var string + */ protected $insertStatement = 'INSERT INTO %s SET id = :id, @@ -76,113 +78,130 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND), content = :content'; + /** + * @var string + */ protected $deleteStatement = 'DELETE FROM %1$s WHERE %2$s'; + /** + * @var string + */ protected $truncateStatement = 'TRUNCATE TABLE %s'; + /** + * @var string + */ protected $fetchColumns = 'modified, content'; + /** + * @var string + */ protected $fetchTimestampColumns = 'modified'; - protected $pdo, $table, $database; + /** + * @var \PDO + */ + protected $pdo; - /* - * Constructor - * - * @param PDO $pdo PDO : active connection - * @param string $table : table (or view) name - * @param string $database : optional - if table is located in another db + /** + * @var + */ + protected $table; + + /** + * @var null + */ + protected $database; + + /** + * Constructor + * + * @param PDO $pdo PDO : active connection + * @param string $table : table (or view) name + * @param string $database : optional - if table is located in another db + * + * @throws \SmartyException */ public function __construct(PDO $pdo, $table, $database = null) { - if (is_null($table)) { throw new SmartyException("Table name for caching can't be null"); } - $this->pdo = $pdo; $this->table = $table; $this->database = $database; - $this->fillStatementsWithTableName(); } - /* - * Fills the table name into the statements. - * - * @return Current Instance - * @access protected + /** + * Fills the table name into the statements. + * + * @return $this Current Instance + * @access protected */ protected function fillStatementsWithTableName() { - - foreach ($this->fetchStatements AS &$statement) { + foreach ($this->fetchStatements as &$statement) { $statement = sprintf($statement, $this->getTableName(), '%s'); } - $this->insertStatement = sprintf($this->insertStatement, $this->getTableName()); $this->deleteStatement = sprintf($this->deleteStatement, $this->getTableName(), '%s'); $this->truncateStatement = sprintf($this->truncateStatement, $this->getTableName()); - return $this; } - /* - * Gets the fetch statement, depending on what you specify - * - * @param string $columns : the column(s) name(s) you want to retrieve from the database - * @param string $id unique cache content identifier - * @param string|null $cache_id cache id - * @param string|null $compile_id compile id - * @access protected + /** + * Gets the fetch statement, depending on what you specify + * + * @param string $columns : the column(s) name(s) you want to retrieve from the database + * @param string $id unique cache content identifier + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * + * @access protected + * @return \PDOStatement */ protected function getFetchStatement($columns, $id, $cache_id = null, $compile_id = null) { - + $args = array(); if (!is_null($cache_id) && !is_null($compile_id)) { - $query = $this->fetchStatements[ 'withCacheIdAndCompileId' ] AND - $args = Array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id); + $query = $this->fetchStatements[ 'withCacheIdAndCompileId' ] and + $args = array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id); } elseif (is_null($cache_id) && !is_null($compile_id)) { - $query = $this->fetchStatements[ 'withCompileId' ] AND - $args = Array('id' => $id, 'compile_id' => $compile_id); + $query = $this->fetchStatements[ 'withCompileId' ] and + $args = array('id' => $id, 'compile_id' => $compile_id); } elseif (!is_null($cache_id) && is_null($compile_id)) { - $query = $this->fetchStatements[ 'withCacheId' ] AND $args = Array('id' => $id, 'cache_id' => $cache_id); + $query = $this->fetchStatements[ 'withCacheId' ] and $args = array('id' => $id, 'cache_id' => $cache_id); } else { - $query = $this->fetchStatements[ 'default' ] AND $args = Array('id' => $id); + $query = $this->fetchStatements[ 'default' ] and $args = array('id' => $id); } - $query = sprintf($query, $columns); - $stmt = $this->pdo->prepare($query); - - foreach ($args AS $key => $value) { + foreach ($args as $key => $value) { $stmt->bindValue($key, $value); } - return $stmt; } /** * fetch cached content and its modification time from data source * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string|null $cache_id cache id - * @param string|null $compile_id compile id - * @param string $content cached content - * @param integer $mtime cache modification timestamp (epoch) + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param string $content cached content + * @param integer $mtime cache modification timestamp (epoch) * * @return void * @access protected */ protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime) { - $stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id); $stmt->execute(); $row = $stmt->fetch(); $stmt->closeCursor(); - if ($row) { $content = $this->outputContent($row[ 'content' ]); $mtime = strtotime($row[ 'modified' ]); @@ -197,10 +216,10 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom * {@internal implementing this method is optional. * Only implement it if modification times can be accessed faster than loading the complete cached content.}} * - * @param string $id unique cache content identifier - * @param string $name template name - * @param string|null $cache_id cache id - * @param string|null $compile_id compile id + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id * * @return integer|boolean timestamp (epoch) the template was modified, or false if not found * @access protected @@ -212,7 +231,6 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom // $stmt -> closeCursor(); // return $mtime; // } - /** * Save content to cache * @@ -228,38 +246,37 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom */ protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content) { - $stmt = $this->pdo->prepare($this->insertStatement); - $stmt->bindValue('id', $id); $stmt->bindValue('name', $name); $stmt->bindValue('cache_id', $cache_id, (is_null($cache_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR); $stmt->bindValue('compile_id', $compile_id, (is_null($compile_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR); - $stmt->bindValue('expire', (int) $exp_time, PDO::PARAM_INT); + $stmt->bindValue('expire', (int)$exp_time, PDO::PARAM_INT); $stmt->bindValue('content', $this->inputContent($content)); $stmt->execute(); - return !!$stmt->rowCount(); } - /* - * Encodes the content before saving to database - * - * @param string $content - * @return string $content - * @access protected + /** + * Encodes the content before saving to database + * + * @param string $content + * + * @return string $content + * @access protected */ protected function inputContent($content) { return $content; } - /* - * Decodes the content before saving to database - * - * @param string $content - * @return string $content - * @access protected + /** + * Decodes the content before saving to database + * + * @param string $content + * + * @return string $content + * @access protected */ protected function outputContent($content) { @@ -272,43 +289,46 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom * @param string|null $name template name * @param string|null $cache_id cache id * @param string|null $compile_id compile id - * @param integer|null|-1 $exp_time seconds till expiration or null + * @param integer|null|-1 $exp_time seconds till expiration or null * * @return integer number of deleted caches - * @access protected + * @access protected */ protected function delete($name = null, $cache_id = null, $compile_id = null, $exp_time = null) { - - // delete the whole cache + // delete the whole cache if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) { - // returning the number of deleted caches would require a second query to count them + // returning the number of deleted caches would require a second query to count them $this->pdo->query($this->truncateStatement); - return - 1; + return -1; } - // build the filter + // build the filter $where = array(); - // equal test name + // equal test name if ($name !== null) { $where[] = 'name = ' . $this->pdo->quote($name); } - // equal test cache_id and match sub-groups + // equal test cache_id and match sub-groups if ($cache_id !== null) { - $where[] = '(cache_id = ' . $this->pdo->quote($cache_id) . ' OR cache_id LIKE ' . - $this->pdo->quote($cache_id . '|%') . ')'; + $where[] = + '(cache_id = ' . + $this->pdo->quote($cache_id) . + ' OR cache_id LIKE ' . + $this->pdo->quote($cache_id . '|%') . + ')'; } - // equal test compile_id + // equal test compile_id if ($compile_id !== null) { $where[] = 'compile_id = ' . $this->pdo->quote($compile_id); } - // for clearing expired caches + // for clearing expired caches if ($exp_time === Smarty::CLEAR_EXPIRED) { $where[] = 'expire < CURRENT_TIMESTAMP'; } // range test expiration time elseif ($exp_time !== null) { $where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)'; } - // run delete query + // run delete query $query = $this->pdo->query(sprintf($this->deleteStatement, join(' AND ', $where))); return $query->rowCount(); } @@ -324,4 +344,3 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom return (is_null($this->database)) ? "`{$this->table}`" : "`{$this->database}`.`{$this->table}`"; } } - \ No newline at end of file diff --git a/vendor/smarty/smarty/demo/plugins/cacheresource.pdo_gzip.php b/vendor/smarty/smarty/demo/plugins/cacheresource.pdo_gzip.php index 8a9e0a5dd..5560b9e39 100644 --- a/vendor/smarty/smarty/demo/plugins/cacheresource.pdo_gzip.php +++ b/vendor/smarty/smarty/demo/plugins/cacheresource.pdo_gzip.php @@ -1,4 +1,5 @@ uid ] = $s; $uid .= $s->filepath; $timestamp = $s->timestamp > $timestamp ? $s->timestamp : $timestamp; - } - catch (SmartyException $e) { + } catch (SmartyException $e) { } } if (!$sources) { $source->exists = false; return; } - $sources = array_reverse($sources, true); reset($sources); $s = current($sources); @@ -51,15 +49,14 @@ class Smarty_Resource_Extendsall extends Smarty_Internal_Resource_Extends $source->timestamp = $timestamp; } - /* + /** * Disable timestamp checks for extendsall resource. * The individual source components will be checked. * - * @return bool + * @return bool false */ public function checkTimestamps() { return false; } - } diff --git a/vendor/smarty/smarty/demo/plugins/resource.mysql.php b/vendor/smarty/smarty/demo/plugins/resource.mysql.php index 619707e78..95a3c2baf 100644 --- a/vendor/smarty/smarty/demo/plugins/resource.mysql.php +++ b/vendor/smarty/smarty/demo/plugins/resource.mysql.php @@ -12,28 +12,46 @@ * PRIMARY KEY (`name`) * ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  2. * Demo data: - *
    INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello world"}{$x}');
    + *
    INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
    + * world"}{$x}');
    + * * * @package Resource-examples * @author Rodney Rehm */ class Smarty_Resource_Mysql extends Smarty_Resource_Custom { - // PDO instance + /** + * PDO instance + * + * @var \PDO + */ protected $db; - // prepared fetch() statement + /** + * prepared fetch() statement + * + * @var \PDOStatement + */ protected $fetch; - // prepared fetchTimestamp() statement + /** + * prepared fetchTimestamp() statement + * + * @var \PDOStatement + */ protected $mtime; + /** + * Smarty_Resource_Mysql constructor. + * + * @throws \SmartyException + */ public function __construct() { try { $this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty"); - } - catch (PDOException $e) { + } catch (PDOException $e) { throw new SmartyException('Mysql Resource failed: ' . $e->getMessage()); } $this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name'); @@ -43,9 +61,9 @@ class Smarty_Resource_Mysql extends Smarty_Resource_Custom /** * Fetch a template and its modification time from database * - * @param string $name template name - * @param string $source template source - * @param integer $mtime template modification timestamp (epoch) + * @param string $name template name + * @param string $source template source + * @param integer $mtime template modification timestamp (epoch) * * @return void */ @@ -66,9 +84,10 @@ class Smarty_Resource_Mysql extends Smarty_Resource_Custom /** * Fetch a template's modification time from database * - * @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the comple template source. + * @note implementing this method is optional. Only implement it if modification times can be accessed faster than + * loading the comple template source. * - * @param string $name template name + * @param string $name template name * * @return integer timestamp (epoch) the template was modified */ @@ -77,7 +96,6 @@ class Smarty_Resource_Mysql extends Smarty_Resource_Custom $this->mtime->execute(array('name' => $name)); $mtime = $this->mtime->fetchColumn(); $this->mtime->closeCursor(); - return strtotime($mtime); } } diff --git a/vendor/smarty/smarty/demo/plugins/resource.mysqls.php b/vendor/smarty/smarty/demo/plugins/resource.mysqls.php index d85aecf31..148a8dd61 100644 --- a/vendor/smarty/smarty/demo/plugins/resource.mysqls.php +++ b/vendor/smarty/smarty/demo/plugins/resource.mysqls.php @@ -14,25 +14,39 @@ * PRIMARY KEY (`name`) * ) ENGINE=InnoDB DEFAULT CHARSET=utf8; * Demo data: - *
    INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello world"}{$x}');
    + *
    INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
    + * world"}{$x}');
    + * * * @package Resource-examples * @author Rodney Rehm */ class Smarty_Resource_Mysqls extends Smarty_Resource_Custom { - // PDO instance + /** + * PDO instance + * + * @var \PDO + */ protected $db; - // prepared fetch() statement + /** + * prepared fetch() statement + * + * @var \PDOStatement + */ protected $fetch; + /** + * Smarty_Resource_Mysqls constructor. + * + * @throws \SmartyException + */ public function __construct() { try { $this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty"); - } - catch (PDOException $e) { + } catch (PDOException $e) { throw new SmartyException('Mysql Resource failed: ' . $e->getMessage()); } $this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name'); @@ -41,9 +55,9 @@ class Smarty_Resource_Mysqls extends Smarty_Resource_Custom /** * Fetch a template and its modification time from database * - * @param string $name template name - * @param string $source template source - * @param integer $mtime template modification timestamp (epoch) + * @param string $name template name + * @param string $source template source + * @param integer $mtime template modification timestamp (epoch) * * @return void */ diff --git a/vendor/smarty/smarty/libs/Autoloader.php b/vendor/smarty/smarty/libs/Autoloader.php index 3a0da8faf..e4dc450f0 100644 --- a/vendor/smarty/smarty/libs/Autoloader.php +++ b/vendor/smarty/smarty/libs/Autoloader.php @@ -2,14 +2,14 @@ /** * Smarty Autoloader * - * @package Smarty + * @package Smarty */ /** * Smarty Autoloader * - * @package Smarty - * @author Uwe Tews + * @package Smarty + * @author Uwe Tews * Usage: * require_once '...path/Autoloader.php'; * Smarty_Autoloader::register(); @@ -20,7 +20,7 @@ */ class Smarty_Autoloader { - /** + /** * Filepath to Smarty root * * @var string @@ -54,8 +54,8 @@ class Smarty_Autoloader if (!defined('SMARTY_SPL_AUTOLOAD')) { define('SMARTY_SPL_AUTOLOAD', 0); } - if (SMARTY_SPL_AUTOLOAD && - set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false + if (SMARTY_SPL_AUTOLOAD + && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false ) { $registeredAutoLoadFunctions = spl_autoload_functions(); if (!isset($registeredAutoLoadFunctions[ 'spl_autoload' ])) { diff --git a/vendor/smarty/smarty/libs/Smarty.class.php b/vendor/smarty/smarty/libs/Smarty.class.php index 597fbbf0c..a8969926b 100644 --- a/vendor/smarty/smarty/libs/Smarty.class.php +++ b/vendor/smarty/smarty/libs/Smarty.class.php @@ -27,7 +27,7 @@ * @author Uwe Tews * @author Rodney Rehm * @package Smarty - * @version 3.1.32 + * @version 3.1.33 */ /** * set SMARTY_DIR to absolute path to Smarty library files. @@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.32'; + const SMARTY_VERSION = '3.1.33'; /** * define variable scopes */ @@ -166,133 +166,157 @@ class Smarty extends Smarty_Internal_TemplateBase const PLUGIN_COMPILER = 'compiler'; const PLUGIN_MODIFIER = 'modifier'; const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler'; + /** * assigned global tpl vars */ public static $global_tpl_vars = array(); + /** * Flag denoting if Multibyte String functions are available */ public static $_MBSTRING = SMARTY_MBSTRING; + /** * The character set to adhere to (e.g. "UTF-8") */ public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET; + /** * The date format to be used internally * (accepts date() and strftime()) */ public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT; + /** * Flag denoting if PCRE should run in UTF-8 mode */ public static $_UTF8_MODIFIER = 'u'; + /** * Flag denoting if operating system is windows */ public static $_IS_WINDOWS = false; + /** * auto literal on delimiters with whitespace * * @var boolean */ public $auto_literal = true; + /** * display error on not assigned variables * * @var boolean */ public $error_unassigned = false; + /** * look up relative file path in include_path * * @var boolean */ public $use_include_path = false; + /** * flag if template_dir is normalized * * @var bool */ public $_templateDirNormalized = false; + /** * joined template directory string used in cache keys * * @var string */ public $_joined_template_dir = null; + /** * flag if config_dir is normalized * * @var bool */ public $_configDirNormalized = false; + /** * joined config directory string used in cache keys * * @var string */ public $_joined_config_dir = null; + /** * default template handler * * @var callable */ public $default_template_handler_func = null; + /** * default config handler * * @var callable */ public $default_config_handler_func = null; + /** * default plugin handler * * @var callable */ public $default_plugin_handler_func = null; + /** * flag if template_dir is normalized * * @var bool */ public $_compileDirNormalized = false; + /** * flag if plugins_dir is normalized * * @var bool */ public $_pluginsDirNormalized = false; + /** * flag if template_dir is normalized * * @var bool */ public $_cacheDirNormalized = false; + /** * force template compiling? * * @var boolean */ public $force_compile = false; - /** + + /** * use sub dirs for compiled/cached files? * * @var boolean */ public $use_sub_dirs = false; + /** * allow ambiguous resources (that are made unique by the resource handler) * * @var boolean */ public $allow_ambiguous_resources = false; + /** * merge compiled includes * * @var boolean */ public $merge_compiled_includes = false; + /* * flag for behaviour when extends: resource and {extends} tag are used simultaneous * if false disable execution of {extends} in templates called by extends resource. @@ -301,30 +325,35 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $extends_recursion = true; + /** * force cache file creation * * @var boolean */ public $force_cache = false; + /** * template left-delimiter * * @var string */ public $left_delimiter = "{"; + /** * template right-delimiter * * @var string */ public $right_delimiter = "}"; + /** * array of strings which shall be treated as literal by compiler * * @var array string */ public $literals = array(); + /** * class name * This should be instance of Smarty_Security. @@ -333,24 +362,28 @@ class Smarty extends Smarty_Internal_TemplateBase * @see Smarty_Security */ public $security_class = 'Smarty_Security'; + /** * implementation of security class * * @var Smarty_Security */ public $security_policy = null; + /** * controls handling of PHP-blocks * * @var integer */ public $php_handling = self::PHP_PASSTHRU; + /** * controls if the php template file resource is allowed * * @var bool */ public $allow_php_templates = false; + /** * debug mode * Setting this to true enables the debug-console. @@ -358,6 +391,7 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $debugging = false; + /** * This determines if debugging is enable-able from the browser. *
      @@ -368,6 +402,7 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $debugging_ctrl = 'NONE'; + /** * Name of debugging URL-param. * Only used when $debugging_ctrl is set to 'URL'. @@ -376,54 +411,63 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $smarty_debug_id = 'SMARTY_DEBUG'; + /** * Path of debug template. * * @var string */ public $debug_tpl = null; + /** * When set, smarty uses this value as error_reporting-level. * * @var int */ public $error_reporting = null; + /** * Controls whether variables with the same name overwrite each other. * * @var boolean */ public $config_overwrite = true; + /** * Controls whether config values of on/true/yes and off/false/no get converted to boolean. * * @var boolean */ public $config_booleanize = true; + /** * Controls whether hidden config sections/vars are read from the file. * * @var boolean */ public $config_read_hidden = false; + /** * locking concurrent compiles * * @var boolean */ public $compile_locking = true; + /** * Controls whether cache resources should use locking mechanism * * @var boolean */ public $cache_locking = false; + /** * seconds to wait for acquiring a lock before ignoring the write lock * * @var float */ public $locking_timeout = 10; + /** * resource type used if none given * Must be an valid key of $registered_resources. @@ -431,6 +475,7 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $default_resource_type = 'file'; + /** * caching type * Must be an element of $cache_resource_types. @@ -438,160 +483,189 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $caching_type = 'file'; + /** * config type * * @var string */ public $default_config_type = 'file'; + /** * check If-Modified-Since headers * * @var boolean */ public $cache_modified_check = false; + /** * registered plugins * * @var array */ public $registered_plugins = array(); + /** * registered objects * * @var array */ public $registered_objects = array(); + /** * registered classes * * @var array */ public $registered_classes = array(); + /** * registered filters * * @var array */ public $registered_filters = array(); + /** * registered resources * * @var array */ public $registered_resources = array(); + /** * registered cache resources * * @var array */ public $registered_cache_resources = array(); + /** * autoload filter * * @var array */ public $autoload_filters = array(); + /** * default modifier * * @var array */ public $default_modifiers = array(); + /** * autoescape variable output * * @var boolean */ public $escape_html = false; + /** * start time for execution time calculation * * @var int */ public $start_time = 0; + /** * required by the compiler for BC * * @var string */ public $_current_file = null; + /** * internal flag to enable parser debugging * * @var bool */ public $_parserdebug = false; + /** * This object type (Smarty = 1, template = 2, data = 4) * * @var int */ public $_objType = 1; + /** * Debug object * * @var Smarty_Internal_Debug */ public $_debug = null; + /** * template directory * * @var array */ protected $template_dir = array('./templates/'); + /** * flags for normalized template directory entries * * @var array */ protected $_processedTemplateDir = array(); + /** * config directory * * @var array */ protected $config_dir = array('./configs/'); + /** * flags for normalized template directory entries * * @var array */ protected $_processedConfigDir = array(); + /** * compile directory * * @var string */ protected $compile_dir = './templates_c/'; + /** * plugins directory * * @var array */ protected $plugins_dir = array(); + /** * cache directory * * @var string */ protected $cache_dir = './cache/'; + /** * removed properties * * @var string[] */ - protected $obsoleteProperties = array('resource_caching', 'template_resource_caching', 'direct_access_security', - '_dir_perms', '_file_perms', 'plugin_search_order', - 'inheritance_merge_compiled_includes', 'resource_cache_mode',); + protected $obsoleteProperties = array( + 'resource_caching', 'template_resource_caching', 'direct_access_security', + '_dir_perms', '_file_perms', 'plugin_search_order', + 'inheritance_merge_compiled_includes', 'resource_cache_mode', + ); + /** * List of private properties which will call getter/setter on a direct access * * @var string[] */ - protected $accessMap = array('template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir', - 'plugins_dir' => 'PluginsDir', 'compile_dir' => 'CompileDir', - 'cache_dir' => 'CacheDir',); + protected $accessMap = array( + 'template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir', + 'plugins_dir' => 'PluginsDir', 'compile_dir' => 'CompileDir', + 'cache_dir' => 'CacheDir', + ); /** * Initialize new Smarty object @@ -618,7 +692,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Enable error handler to mute expected messages * - * @return boolean + * @return boolean * @deprecated */ public static function muteExpectedErrors() @@ -639,7 +713,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Check if a template resource exists * - * @param string $resource_name template name + * @param string $resource_name template name * * @return bool status * @throws \SmartyException @@ -654,10 +728,10 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Loads security class and enables security * - * @param string|Smarty_Security $security_class if a string is used, it must be class-name + * @param string|Smarty_Security $security_class if a string is used, it must be class-name * * @return Smarty current Smarty instance for chaining - * @throws SmartyException when an invalid class name is provided + * @throws \SmartyException */ public function enableSecurity($security_class = null) { @@ -679,9 +753,9 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Add template directory(s) * - * @param string|array $template_dir directory(s) of template sources - * @param string $key of the array element to assign the template dir to - * @param bool $isConfig true for config_dir + * @param string|array $template_dir directory(s) of template sources + * @param string $key of the array element to assign the template dir to + * @param bool $isConfig true for config_dir * * @return Smarty current Smarty instance for chaining */ @@ -747,8 +821,8 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Set template directory * - * @param string|array $template_dir directory(s) of template sources - * @param bool $isConfig true for config_dir + * @param string|array $template_dir directory(s) of template sources + * @param bool $isConfig true for config_dir * * @return \Smarty current Smarty instance for chaining */ @@ -835,7 +909,7 @@ class Smarty extends Smarty_Internal_TemplateBase $this->plugins_dir = (array)$this->plugins_dir; } foreach ($this->plugins_dir as $k => $v) { - $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true); + $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, '/\\') . DIRECTORY_SEPARATOR, true); } $this->_cache[ 'plugin_files' ] = array(); $this->_pluginsDirNormalized = true; @@ -846,7 +920,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Set plugins directory * - * @param string|array $plugins_dir directory(s) of plugins + * @param string|array $plugins_dir directory(s) of plugins * * @return Smarty current Smarty instance for chaining */ @@ -901,7 +975,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Set cache directory * - * @param string $cache_dir directory to store cached templates in + * @param string $cache_dir directory to store cached templates in * * @return Smarty current Smarty instance for chaining */ @@ -915,11 +989,11 @@ class Smarty extends Smarty_Internal_TemplateBase /** * creates a template object * - * @param string $template the resource handle of the template file - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - * @param boolean $do_clone flag is Smarty object shall be cloned + * @param string $template the resource handle of the template file + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param boolean $do_clone flag is Smarty object shall be cloned * * @return \Smarty_Internal_Template template object * @throws \SmartyException @@ -946,7 +1020,7 @@ class Smarty extends Smarty_Internal_TemplateBase Smarty_Internal_Template::$isCacheTplObj[ $_templateId ]; $tpl->inheritance = null; $tpl->tpl_vars = $tpl->config_vars = array(); - } else if (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) { + } elseif (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) { $tpl = clone Smarty_Internal_Template::$tplObjCache[ $_templateId ]; $tpl->inheritance = null; $tpl->tpl_vars = $tpl->config_vars = array(); @@ -981,11 +1055,11 @@ class Smarty extends Smarty_Internal_TemplateBase * class name format: Smarty_PluginType_PluginName * plugin filename format: plugintype.pluginname.php * - * @param string $plugin_name class plugin name to load - * @param bool $check check if already loaded + * @param string $plugin_name class plugin name to load + * @param bool $check check if already loaded * - * @throws SmartyException * @return string |boolean filepath of loaded file or false + * @throws \SmartyException */ public function loadPlugin($plugin_name, $check = true) { @@ -1004,12 +1078,13 @@ class Smarty extends Smarty_Internal_TemplateBase * @return string * @throws \SmartyException */ - public function _getTemplateId($template_name, - $cache_id = null, - $compile_id = null, - $caching = null, - Smarty_Internal_Template $template = null) - { + public function _getTemplateId( + $template_name, + $cache_id = null, + $compile_id = null, + $caching = null, + Smarty_Internal_Template $template = null + ) { $template_name = (strpos($template_name, ':') === false) ? "{$this->default_resource_type}:{$template_name}" : $template_name; $cache_id = $cache_id === null ? $this->cache_id : $cache_id; @@ -1033,33 +1108,22 @@ class Smarty extends Smarty_Internal_TemplateBase * - remove /./ and /../ * - make it absolute if required * - * @param string $path file path - * @param bool $realpath if true - convert to absolute - * false - convert to relative - * null - keep as it is but remove /./ /../ + * @param string $path file path + * @param bool $realpath if true - convert to absolute + * false - convert to relative + * null - keep as it is but + * remove /./ /../ * * @return string */ public function _realpath($path, $realpath = null) { - static $nds = null; - static $sepDotsep = null; - static $sepDot = null; - static $sepSep =null; - if (!isset($nds)) { - $nds = array('/' => '\\', '\\' => '/'); - $sepDotsep = DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR; - $sepDot = DIRECTORY_SEPARATOR . '.'; - $sepSep = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; - } - // normalize DIRECTORY_SEPARATOR - $path = str_replace(array($nds[DIRECTORY_SEPARATOR], $sepDotsep), DIRECTORY_SEPARATOR, $path); - if (strpos($path,$sepDot) === false && (($realpath === false && $path[0] === '.') || $realpath === null) && $path[0] !== '\\') { - return $path; - } - preg_match('%^(?(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?(.*))$%u', - $path, - $parts); + $nds = array('/' => '\\', '\\' => '/'); + preg_match( + '%^(?(?:[[:alpha:]]:[\\\\/]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?(.*))$%u', + $path, + $parts + ); $path = $parts[ 'path' ]; if ($parts[ 'root' ] === '\\') { $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ]; @@ -1068,24 +1132,18 @@ class Smarty extends Smarty_Internal_TemplateBase $path = getcwd() . DIRECTORY_SEPARATOR . $path; } } - // remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns - $path = str_replace(array($sepDotsep,$sepSep), DIRECTORY_SEPARATOR, $path); - // resolve '..DIRECTORY_SEPARATOR' pattern, smallest first - if (strpos($path, '..' . DIRECTORY_SEPARATOR) !== false && - preg_match_all('#[\\\\/]([.][.][\\\\/])+#u', $path, $match) - ) { - $counts = array(); - foreach ($match[ 0 ] as $m) { - $counts[] = (int)((strlen($m) - 1) / 3); - } - sort($counts); - foreach ($counts as $count) { - $path = preg_replace('#([\\\\/]+[^\\\\/]+){' . $count . - '}[\\\\/]+([.][.][\\\\/]+){' . $count . '}#u', - DIRECTORY_SEPARATOR, - $path); - } - } + // normalize DIRECTORY_SEPARATOR + $path = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $path); + $parts[ 'root' ] = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $parts[ 'root' ]); + do { + $path = preg_replace( + array('#[\\\\/]{2}#', '#[\\\\/][.][\\\\/]#', '#[\\\\/]([^\\\\/.]+)[\\\\/][.][.][\\\\/]#'), + DIRECTORY_SEPARATOR, + $path, + -1, + $count + ); + } while ($count > 0); return $realpath !== false ? $parts[ 'root' ] . $path : str_ireplace(getcwd(), '.', $parts[ 'root' ] . $path); } @@ -1279,19 +1337,18 @@ class Smarty extends Smarty_Internal_TemplateBase * Calls the appropriate getter function. * Issues an E_USER_NOTICE if no valid getter is found. * - * @param string $name property name + * @param string $name property name * * @return mixed - * @throws \SmartyException */ public function __get($name) { if (isset($this->accessMap[ $name ])) { $method = 'get' . $this->accessMap[ $name ]; return $this->{$method}(); - } else if (isset($this->_cache[ $name ])) { + } elseif (isset($this->_cache[ $name ])) { return $this->_cache[ $name ]; - } else if (in_array($name, $this->obsoleteProperties)) { + } elseif (in_array($name, $this->obsoleteProperties)) { return null; } else { trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); @@ -1307,21 +1364,18 @@ class Smarty extends Smarty_Internal_TemplateBase * @param string $name property name * @param mixed $value parameter passed to setter * - * @throws \SmartyException */ public function __set($name, $value) { if (isset($this->accessMap[ $name ])) { $method = 'set' . $this->accessMap[ $name ]; $this->{$method}($value); - } else if (in_array($name, $this->obsoleteProperties)) { + } elseif (in_array($name, $this->obsoleteProperties)) { return; + } elseif (is_object($value) && method_exists($value, $name)) { + $this->$name = $value; } else { - if (is_object($value) && method_exists($value, $name)) { - $this->$name = $value; - } else { - trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); - } + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); } } @@ -1345,7 +1399,6 @@ class Smarty extends Smarty_Internal_TemplateBase * Normalize template_dir or config_dir * * @param bool $isConfig true for config_dir - * */ private function _normalizeTemplateConfig($isConfig) { diff --git a/vendor/smarty/smarty/libs/SmartyBC.class.php b/vendor/smarty/smarty/libs/SmartyBC.class.php index f2230fc9c..836f98153 100644 --- a/vendor/smarty/smarty/libs/SmartyBC.class.php +++ b/vendor/smarty/smarty/libs/SmartyBC.class.php @@ -28,7 +28,7 @@ /** * @ignore */ -require_once(dirname(__FILE__) . '/Smarty.class.php'); +require_once dirname(__FILE__) . '/Smarty.class.php'; /** * Smarty Backward Compatibility Wrapper Class @@ -53,7 +53,6 @@ class SmartyBC extends Smarty /** * Initialize new SmartyBC object - * */ public function __construct() { @@ -127,12 +126,16 @@ class SmartyBC extends Smarty * @param boolean $smarty_args smarty argument format, else traditional * @param array $block_methods list of methods that are block format * - * @throws SmartyException + * @throws SmartyException * @internal param array $block_functs list of methods that are block format */ - public function register_object($object, $object_impl, $allowed = array(), $smarty_args = true, - $block_methods = array()) - { + public function register_object( + $object, + $object_impl, + $allowed = array(), + $smarty_args = true, + $block_methods = array() + ) { settype($allowed, 'array'); settype($smarty_args, 'boolean'); $this->registerObject($object, $object_impl, $allowed, $smarty_args, $block_methods); @@ -326,10 +329,10 @@ class SmartyBC extends Smarty /** * clear cached content for the given template and cache id * - * @param string $tpl_file name of template file - * @param string $cache_id name of cache_id - * @param string $compile_id name of compile_id - * @param string $exp_time expiration time + * @param string $tpl_file name of template file + * @param string $cache_id name of cache_id + * @param string $compile_id name of compile_id + * @param string $exp_time expiration time * * @return boolean */ @@ -341,7 +344,7 @@ class SmartyBC extends Smarty /** * clear the entire contents of cache (all templates) * - * @param string $exp_time expire time + * @param string $exp_time expire time * * @return boolean */ @@ -353,9 +356,9 @@ class SmartyBC extends Smarty /** * test to see if valid cache exists for this template * - * @param string $tpl_file name of template file - * @param string $cache_id - * @param string $compile_id + * @param string $tpl_file name of template file + * @param string $cache_id + * @param string $compile_id * * @return bool * @throws \Exception @@ -379,9 +382,9 @@ class SmartyBC extends Smarty * or all compiled template files if one is not specified. * This function is for advanced use only, not normally needed. * - * @param string $tpl_file - * @param string $compile_id - * @param string $exp_time + * @param string $tpl_file + * @param string $compile_id + * @param string $exp_time * * @return boolean results of {@link smarty_core_rm_auto()} */ @@ -393,7 +396,7 @@ class SmartyBC extends Smarty /** * Checks whether requested template exists. * - * @param string $tpl_file + * @param string $tpl_file * * @return bool * @throws \SmartyException @@ -406,7 +409,7 @@ class SmartyBC extends Smarty /** * Returns an array containing template variables * - * @param string $name + * @param string $name * * @return array */ @@ -418,7 +421,7 @@ class SmartyBC extends Smarty /** * Returns an array containing config variables * - * @param string $name + * @param string $name * * @return array */ @@ -442,7 +445,7 @@ class SmartyBC extends Smarty /** * return a reference to a registered object * - * @param string $name + * @param string $name * * @return object */ diff --git a/vendor/smarty/smarty/libs/bootstrap.php b/vendor/smarty/smarty/libs/bootstrap.php index dad72fcb1..2c830468e 100644 --- a/vendor/smarty/smarty/libs/bootstrap.php +++ b/vendor/smarty/smarty/libs/bootstrap.php @@ -1,5 +1,5 @@ @@ -7,11 +7,10 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - -/* +/** * Load and register Smarty Autoloader */ if (!class_exists('Smarty_Autoloader')) { - require dirname(__FILE__) . '/Autoloader.php'; + include dirname(__FILE__) . '/Autoloader.php'; } Smarty_Autoloader::register(true); diff --git a/vendor/smarty/smarty/libs/debug.tpl b/vendor/smarty/smarty/libs/debug.tpl index 5526cbca8..edc7bef98 100644 --- a/vendor/smarty/smarty/libs/debug.tpl +++ b/vendor/smarty/smarty/libs/debug.tpl @@ -113,10 +113,10 @@
      {foreach $template_data as $template} {$template.name} -
         +
         (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"}) -
      +
      {/foreach}
      {/if} @@ -127,7 +127,7 @@ {foreach $assigned_vars as $vars}

      ${$vars@key}

      - {if isset($vars['nocache'])}Nocache
      {/if} + {if isset($vars['nocache'])}Nocache
      {/if} {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if}

      Value

      {$vars['value']|debug_print_var:10:80 nofilter} diff --git a/vendor/smarty/smarty/libs/plugins/block.textformat.php b/vendor/smarty/smarty/libs/plugins/block.textformat.php index 310a420ee..5e494637e 100644 --- a/vendor/smarty/smarty/libs/plugins/block.textformat.php +++ b/vendor/smarty/smarty/libs/plugins/block.textformat.php @@ -20,7 +20,6 @@ * - indent_char - string (" ") * - wrap_boundary - boolean (true) * - * * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat} * (Smarty online manual) * @@ -39,10 +38,15 @@ function smarty_block_textformat($params, $content, Smarty_Internal_Template $te return; } if (Smarty::$_MBSTRING) { - $template->_checkPlugins(array(array('function' => 'smarty_modifier_mb_wordwrap', - 'file' => SMARTY_PLUGINS_DIR . 'modifier.mb_wordwrap.php'))); + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_modifier_mb_wordwrap', + 'file' => SMARTY_PLUGINS_DIR . 'modifier.mb_wordwrap.php' + ) + ) + ); } - $style = null; $indent = 0; $indent_first = 0; @@ -51,47 +55,48 @@ function smarty_block_textformat($params, $content, Smarty_Internal_Template $te $wrap_char = "\n"; $wrap_cut = false; $assign = null; - foreach ($params as $_key => $_val) { switch ($_key) { case 'style': case 'indent_char': case 'wrap_char': case 'assign': - $$_key = (string) $_val; + $$_key = (string)$_val; break; - case 'indent': case 'indent_first': case 'wrap': - $$_key = (int) $_val; + $$_key = (int)$_val; break; - case 'wrap_cut': - $$_key = (bool) $_val; + $$_key = (bool)$_val; break; - default: trigger_error("textformat: unknown attribute '{$_key}'"); } } - if ($style === 'email') { $wrap = 72; } // split into paragraphs $_paragraphs = preg_split('![\r\n]{2}!', $content); - foreach ($_paragraphs as &$_paragraph) { if (!$_paragraph) { continue; } // convert mult. spaces & special chars to single space $_paragraph = - preg_replace(array('!\s+!' . Smarty::$_UTF8_MODIFIER, - '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER), - array(' ', - ''), $_paragraph); + preg_replace( + array( + '!\s+!' . Smarty::$_UTF8_MODIFIER, + '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER + ), + array( + ' ', + '' + ), + $_paragraph + ); // indent first line if ($indent_first > 0) { $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph; @@ -108,7 +113,6 @@ function smarty_block_textformat($params, $content, Smarty_Internal_Template $te } } $_output = implode($wrap_char . $wrap_char, $_paragraphs); - if ($assign) { $template->assign($assign, $_output); } else { diff --git a/vendor/smarty/smarty/libs/plugins/function.counter.php b/vendor/smarty/smarty/libs/plugins/function.counter.php index 9610362d9..a4129e77c 100644 --- a/vendor/smarty/smarty/libs/plugins/function.counter.php +++ b/vendor/smarty/smarty/libs/plugins/function.counter.php @@ -5,7 +5,6 @@ * @package Smarty * @subpackage PluginsFunction */ - /** * Smarty {counter} function plugin * Type: function @@ -24,50 +23,40 @@ function smarty_function_counter($params, $template) { static $counters = array(); - $name = (isset($params[ 'name' ])) ? $params[ 'name' ] : 'default'; if (!isset($counters[ $name ])) { $counters[ $name ] = array('start' => 1, 'skip' => 1, 'direction' => 'up', 'count' => 1); } $counter =& $counters[ $name ]; - if (isset($params[ 'start' ])) { - $counter[ 'start' ] = $counter[ 'count' ] = (int) $params[ 'start' ]; + $counter[ 'start' ] = $counter[ 'count' ] = (int)$params[ 'start' ]; } - if (!empty($params[ 'assign' ])) { $counter[ 'assign' ] = $params[ 'assign' ]; } - if (isset($counter[ 'assign' ])) { $template->assign($counter[ 'assign' ], $counter[ 'count' ]); } - if (isset($params[ 'print' ])) { - $print = (bool) $params[ 'print' ]; + $print = (bool)$params[ 'print' ]; } else { $print = empty($counter[ 'assign' ]); } - if ($print) { $retval = $counter[ 'count' ]; } else { $retval = null; } - if (isset($params[ 'skip' ])) { $counter[ 'skip' ] = $params[ 'skip' ]; } - if (isset($params[ 'direction' ])) { $counter[ 'direction' ] = $params[ 'direction' ]; } - if ($counter[ 'direction' ] === 'down') { $counter[ 'count' ] -= $counter[ 'skip' ]; } else { $counter[ 'count' ] += $counter[ 'skip' ]; } - return $retval; } diff --git a/vendor/smarty/smarty/libs/plugins/function.cycle.php b/vendor/smarty/smarty/libs/plugins/function.cycle.php index b871524fc..07ffcc5e2 100644 --- a/vendor/smarty/smarty/libs/plugins/function.cycle.php +++ b/vendor/smarty/smarty/libs/plugins/function.cycle.php @@ -5,7 +5,6 @@ * @package Smarty * @subpackage PluginsFunction */ - /** * Smarty {cycle} function plugin * Type: function @@ -29,34 +28,29 @@ * {cycle name=row values="one,two,three" reset=true} * {cycle name=row} * - * - * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle} + * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle} * (Smarty online manual) - * @author Monte Ohrt - * @author credit to Mark Priatel - * @author credit to Gerard - * @author credit to Jason Sweat - * @version 1.3 + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 * * @param array $params parameters * @param Smarty_Internal_Template $template template object * * @return string|null */ - function smarty_function_cycle($params, $template) { static $cycle_vars; - $name = (empty($params[ 'name' ])) ? 'default' : $params[ 'name' ]; - $print = (isset($params[ 'print' ])) ? (bool) $params[ 'print' ] : true; - $advance = (isset($params[ 'advance' ])) ? (bool) $params[ 'advance' ] : true; - $reset = (isset($params[ 'reset' ])) ? (bool) $params[ 'reset' ] : false; - + $print = (isset($params[ 'print' ])) ? (bool)$params[ 'print' ] : true; + $advance = (isset($params[ 'advance' ])) ? (bool)$params[ 'advance' ] : true; + $reset = (isset($params[ 'reset' ])) ? (bool)$params[ 'reset' ] : false; if (!isset($params[ 'values' ])) { if (!isset($cycle_vars[ $name ][ 'values' ])) { trigger_error('cycle: missing \'values\' parameter'); - return; } } else { @@ -65,41 +59,34 @@ function smarty_function_cycle($params, $template) } $cycle_vars[ $name ][ 'values' ] = $params[ 'values' ]; } - if (isset($params[ 'delimiter' ])) { $cycle_vars[ $name ][ 'delimiter' ] = $params[ 'delimiter' ]; } elseif (!isset($cycle_vars[ $name ][ 'delimiter' ])) { $cycle_vars[ $name ][ 'delimiter' ] = ','; } - if (is_array($cycle_vars[ $name ][ 'values' ])) { $cycle_array = $cycle_vars[ $name ][ 'values' ]; } else { $cycle_array = explode($cycle_vars[ $name ][ 'delimiter' ], $cycle_vars[ $name ][ 'values' ]); } - if (!isset($cycle_vars[ $name ][ 'index' ]) || $reset) { $cycle_vars[ $name ][ 'index' ] = 0; } - if (isset($params[ 'assign' ])) { $print = false; $template->assign($params[ 'assign' ], $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]); } - if ($print) { $retval = $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]; } else { $retval = null; } - if ($advance) { if ($cycle_vars[ $name ][ 'index' ] >= count($cycle_array) - 1) { $cycle_vars[ $name ][ 'index' ] = 0; } else { - $cycle_vars[ $name ][ 'index' ] ++; + $cycle_vars[ $name ][ 'index' ]++; } } - return $retval; } diff --git a/vendor/smarty/smarty/libs/plugins/function.fetch.php b/vendor/smarty/smarty/libs/plugins/function.fetch.php index 9539e1fcc..768761b23 100644 --- a/vendor/smarty/smarty/libs/plugins/function.fetch.php +++ b/vendor/smarty/smarty/libs/plugins/function.fetch.php @@ -5,7 +5,6 @@ * @package Smarty * @subpackage PluginsFunction */ - /** * Smarty {fetch} plugin * Type: function @@ -26,20 +25,16 @@ function smarty_function_fetch($params, $template) { if (empty($params[ 'file' ])) { trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE); - return; } - // strip file protocol if (stripos($params[ 'file' ], 'file://') === 0) { $params[ 'file' ] = substr($params[ 'file' ], 7); } - $protocol = strpos($params[ 'file' ], '://'); if ($protocol !== false) { $protocol = strtolower(substr($params[ 'file' ], 0, $protocol)); } - if (isset($template->smarty->security_policy)) { if ($protocol) { // remote resource (or php stream, …) @@ -53,7 +48,6 @@ function smarty_function_fetch($params, $template) } } } - $content = ''; if ($protocol === 'http') { // http fetch @@ -104,7 +98,6 @@ function smarty_function_fetch($params, $template) if (!empty($param_value)) { if (!preg_match('![\w\d-]+: .+!', $param_value)) { trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE); - return; } else { $extra_headers[] = $param_value; @@ -118,10 +111,9 @@ function smarty_function_fetch($params, $template) break; case 'proxy_port': if (!preg_match('!\D!', $param_value)) { - $proxy_port = (int) $param_value; + $proxy_port = (int)$param_value; } else { trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE); - return; } break; @@ -137,16 +129,14 @@ function smarty_function_fetch($params, $template) break; case 'timeout': if (!preg_match('!\D!', $param_value)) { - $timeout = (int) $param_value; + $timeout = (int)$param_value; } else { trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE); - return; } break; default: trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE); - return; } } @@ -156,10 +146,8 @@ function smarty_function_fetch($params, $template) } else { $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout); } - if (!$fp) { trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE); - return; } else { if ($_is_proxy) { @@ -187,23 +175,19 @@ function smarty_function_fetch($params, $template) if (!empty($user) && !empty($pass)) { fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n"); } - fputs($fp, "\r\n"); while (!feof($fp)) { $content .= fgets($fp, 4096); } fclose($fp); $csplit = preg_split("!\r\n\r\n!", $content, 2); - $content = $csplit[ 1 ]; - if (!empty($params[ 'assign_headers' ])) { $template->assign($params[ 'assign_headers' ], preg_split("!\r\n!", $csplit[ 0 ])); } } } else { trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE); - return; } } else { @@ -212,7 +196,6 @@ function smarty_function_fetch($params, $template) throw new SmartyException("{fetch} cannot read resource '" . $params[ 'file' ] . "'"); } } - if (!empty($params[ 'assign' ])) { $template->assign($params[ 'assign' ], $content); } else { diff --git a/vendor/smarty/smarty/libs/plugins/function.html_checkboxes.php b/vendor/smarty/smarty/libs/plugins/function.html_checkboxes.php index d654caba6..302358edd 100644 --- a/vendor/smarty/smarty/libs/plugins/function.html_checkboxes.php +++ b/vendor/smarty/smarty/libs/plugins/function.html_checkboxes.php @@ -29,25 +29,29 @@ * - assign (optional) - assign the output as an array to this variable * - escape (optional) - escape the content (not value), defaults to true * - * - * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} * (Smarty online manual) - * @author Christopher Kvarme - * @author credits to Monte Ohrt - * @version 1.0 + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 * * @param array $params parameters * @param Smarty_Internal_Template $template template object * * @return string - * @uses smarty_function_escape_special_chars() + * @uses smarty_function_escape_special_chars() * @throws \SmartyException */ function smarty_function_html_checkboxes($params, Smarty_Internal_Template $template) { - $template->_checkPlugins(array(array('function' => 'smarty_function_escape_special_chars', - 'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php'))); - + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_function_escape_special_chars', + 'file' => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php' + ) + ) + ); $name = 'checkbox'; $values = null; $options = null; @@ -57,31 +61,25 @@ function smarty_function_html_checkboxes($params, Smarty_Internal_Template $temp $labels = true; $label_ids = false; $output = null; - $extra = ''; - foreach ($params as $_key => $_val) { switch ($_key) { case 'name': case 'separator': - $$_key = (string) $_val; + $$_key = (string)$_val; break; - case 'escape': case 'labels': case 'label_ids': - $$_key = (bool) $_val; + $$_key = (bool)$_val; break; - case 'options': - $$_key = (array) $_val; + $$_key = (array)$_val; break; - case 'values': case 'output': - $$_key = array_values((array) $_val); + $$_key = array_values((array)$_val); break; - case 'checked': case 'selected': if (is_array($_val)) { @@ -89,57 +87,61 @@ function smarty_function_html_checkboxes($params, Smarty_Internal_Template $temp foreach ($_val as $_sel) { if (is_object($_sel)) { if (method_exists($_sel, '__toString')) { - $_sel = smarty_function_escape_special_chars((string) $_sel->__toString()); + $_sel = smarty_function_escape_special_chars((string)$_sel->__toString()); } else { - trigger_error('html_checkboxes: selected attribute contains an object of class \'' . - get_class($_sel) . '\' without __toString() method', E_USER_NOTICE); + trigger_error( + 'html_checkboxes: selected attribute contains an object of class \'' . + get_class($_sel) . '\' without __toString() method', + E_USER_NOTICE + ); continue; } } else { - $_sel = smarty_function_escape_special_chars((string) $_sel); + $_sel = smarty_function_escape_special_chars((string)$_sel); } $selected[ $_sel ] = true; } } elseif (is_object($_val)) { if (method_exists($_val, '__toString')) { - $selected = smarty_function_escape_special_chars((string) $_val->__toString()); + $selected = smarty_function_escape_special_chars((string)$_val->__toString()); } else { - trigger_error('html_checkboxes: selected attribute is an object of class \'' . get_class($_val) . - '\' without __toString() method', E_USER_NOTICE); + trigger_error( + 'html_checkboxes: selected attribute is an object of class \'' . get_class($_val) . + '\' without __toString() method', + E_USER_NOTICE + ); } } else { - $selected = smarty_function_escape_special_chars((string) $_val); + $selected = smarty_function_escape_special_chars((string)$_val); } break; - case 'checkboxes': - trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', - E_USER_WARNING); - $options = (array) $_val; + trigger_error( + 'html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', + E_USER_WARNING + ); + $options = (array)$_val; break; - case 'assign': break; - case 'strict': break; - case 'disabled': case 'readonly': if (!empty($params[ 'strict' ])) { if (!is_scalar($_val)) { - trigger_error("html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute", - E_USER_NOTICE); + trigger_error( + "html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute", + E_USER_NOTICE + ); } - if ($_val === true || $_val === $_key) { $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"'; } - break; } // omit break; to fall through! - + // no break default: if (!is_array($_val)) { $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"'; @@ -149,34 +151,49 @@ function smarty_function_html_checkboxes($params, Smarty_Internal_Template $temp break; } } - if (!isset($options) && !isset($values)) { return ''; } /* raise error here? */ - $_html_result = array(); - if (isset($options)) { foreach ($options as $_key => $_val) { $_html_result[] = - smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, - $label_ids, $escape); + smarty_function_html_checkboxes_output( + $name, + $_key, + $_val, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape + ); } } else { foreach ($values as $_i => $_key) { $_val = isset($output[ $_i ]) ? $output[ $_i ] : ''; $_html_result[] = - smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, - $label_ids, $escape); + smarty_function_html_checkboxes_output( + $name, + $_key, + $_val, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape + ); } } - if (!empty($params[ 'assign' ])) { $template->assign($params[ 'assign' ], $_html_result); } else { return implode("\n", $_html_result); } } + /** * @param $name * @param $value @@ -190,59 +207,69 @@ function smarty_function_html_checkboxes($params, Smarty_Internal_Template $temp * * @return string */ -function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels, - $label_ids, $escape = true) -{ +function smarty_function_html_checkboxes_output( + $name, + $value, + $output, + $selected, + $extra, + $separator, + $labels, + $label_ids, + $escape = true +) { $_output = ''; - if (is_object($value)) { if (method_exists($value, '__toString')) { - $value = (string) $value->__toString(); + $value = (string)$value->__toString(); } else { - trigger_error('html_options: value is an object of class \'' . get_class($value) . - '\' without __toString() method', E_USER_NOTICE); - + trigger_error( + 'html_options: value is an object of class \'' . get_class($value) . + '\' without __toString() method', + E_USER_NOTICE + ); return ''; } } else { - $value = (string) $value; + $value = (string)$value; } - if (is_object($output)) { if (method_exists($output, '__toString')) { - $output = (string) $output->__toString(); + $output = (string)$output->__toString(); } else { - trigger_error('html_options: output is an object of class \'' . get_class($output) . - '\' without __toString() method', E_USER_NOTICE); - + trigger_error( + 'html_options: output is an object of class \'' . get_class($output) . + '\' without __toString() method', + E_USER_NOTICE + ); return ''; } } else { - $output = (string) $output; + $output = (string)$output; } - if ($labels) { if ($label_ids) { - $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_', - $name . '_' . $value)); + $_id = smarty_function_escape_special_chars( + preg_replace( + '![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, + '_', + $name . '_' . $value + ) + ); $_output .= '