V1.0 (check Readme.md)

This commit is contained in:
Root srvweb 2020-05-02 01:00:35 +02:00
parent 0d9ead8873
commit 2b285ac34e
77 changed files with 44158 additions and 713 deletions

View file

@ -2,8 +2,12 @@ Options -Indexes +FollowSymLinks -SymLinksIfOwnerMatch
RewriteEngine on
## Sécurité
RewriteCond %{REQUEST_URI} jquery-file-upload.html [NC]
RewriteRule .* - [L]
## Sécurité
#RewriteRule ^files/([0-9]+-[0-9]{1,2})/.key-[0-9]{12} /index.php?action=403
RewriteRule ^files/(.+) /index.php?action=403
RewriteRule ^(.+).key-[0-9]{12}$ /index.php?action=403

View file

@ -7,7 +7,8 @@ PHP file sharing service [free of rights](https://en.wikipedia.org/wiki/Open_sou
- HTTP serveur htaccess compatible (url rewriting enable)
- PHP 5.6 minimum
- PHP GD lib
- PHP GD lib
- ImageMagick convert binary (option)
- No nessecary database
## Installation
@ -45,10 +46,17 @@ to
- drag and drop for upload
- limit by ip+cookies (sqlite) (limit abuse)
- crypt files
- Rendre l'upload progress plus jolie
- Ajout de fichier dans un répetoire déjà uploadé
- captcha / anti bot
- "signaler un fichier"
- mimeTypes restriction
- 1.0
- jQuery-File-Upload implemented : https://github.com/blueimp/jQuery-File-Upload/
- Resize image befor upload
- Preview audio/video/image befor upload
- Config add variable :
- minUploadPerFile, acceptFileTypes, imageAutoOrient
- Deprecated : mimeTypes restriction
- Add on existent sharing
- 0.2
- Mod gallery if images
- Passowrd for access
@ -88,4 +96,4 @@ David Mercereau [david #arobase# mercereau #point# info](http://david.mercereau.
## Translation
* oc : Quentin PAGÈS
* fr/en : David Mercereau
* fr/en : David Mercereau

View file

@ -11,47 +11,37 @@ expireCronFreq: 86400 # juste for cron web, in second (exemple 86400 =
expireDay:
- 1
- 7
- 15
- 30
- 90
- 180
- 365
expireDayDefault : 7
expireDayDefault : 15
imageResize: # Propose resize images
- 0 # 0 = no resize
- 300
- 800
- 1024
- 1920
- 2048
- 4096
passwordUniqKey: uiphv7olXzvghRanRCxF # get random here : https://www.random.org/strings/?num=1&len=20&digits=on&upperalpha=on&loweralpha=on&unique=on&format=html&rnd=new
passwordTimeRemember: '+2 hours' # https://www.php.net/manual/fr/function.strtotime.php
deleteAfterAccessDefault: 1
imageResizeDefault : 1024
maxUploadPerFile: 30M # Exemple 100K, 30M, 12G
maxUploadPerFile: 30M
minUploadPerFile: 1 # Exemple 100K, 30M, 12G
maxUploadTotal: 90M # Exemple 100K, 30M, 12G
maxUploadNb: 100
mimeTypesConduct: allow # allow = Allow this, deny the rest / deny = Deny this, allow the rest
mimeTypes: # pattern for pgrep_match https://www.php.net/manual/function.preg-match.php
- ^text\/
- ^image\/
- ^audio\/
- ^video\/
- ^font\/
- ^application\/x-bzip
- ^application\/x-csh$
- ^application\/msword$
- ^application\/vnd.openxmlformats-officedocument.
- ^application\/epub+zip$
- ^application\/vnd.oasis.opendocument.
- ^application\/ogg
- ^application\/pdf$
- ^application\/x-rar-compressed$
- ^application\/vnd.ms-powerpoint$
- ^application\/x-tar$
- ^application\/vnd.visio$
- ^application\/vnd.ms-excel$
- ^application\/zip$
- ^application\/x-7z-compressed$
acceptFileTypes: '/(\.|\/)(pdf|od[a-z]|doc[a-z]?|xls[a-z]?|csv|ppt[a-z]?|7z|zip|bz|bz2|rar|tar|gz|tgz|txt|md|gif|jpe?g|png|bmp|ico|mp3|aac|mid|wav|ov[a-z]|web.?|avi|mp[a-z]?g|mp.+|wm.+|xml|iso|torrent)$/i'
#~ 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:
imageLibrary: 0
#~ If set 2 :
imageConvertBin: 'convert'
imageIdentifyBin: 'identify'
imageAutoOrient: true
checkUpdate: 86400 # in seconds or "false" for disable
similarServicesView: true
similarServicesLink:
- <a href="https://send.firefox.com">Firefox Send</a>

511
index.php
View file

@ -1,5 +1,5 @@
<?php
define('VERSION', '0.2');
define('VERSION', '1.0');
if (!is_readable('./config.yaml')) {
exit('Error: The configuration file is not present, move config.yaml.default to config.yaml');
}
@ -17,6 +17,7 @@ if (isset($_GET['id'])){
$id = null;
}
/* Language */
if (isset($_GET['langueChange'])) {
$locale = lang2locale($_GET['langueChange']);
@ -203,14 +204,15 @@ if ($passwordForm == false) {
var Config_maxUploadPerFile = <?= convertHumain2octect($config['maxUploadPerFile']) ?>
var Config_maxUploadTotal = <?= convertHumain2octect($config['maxUploadTotal']) ?>
var Config_maxUploadNb = <?= $config['maxUploadNb'] ?>
var Config_mimeTypesConduct = '<?= $config['mimeTypesConduct'] ?>'
var Config_mimeTypes = ['helloWorld'<?php foreach ($config['mimeTypes'] as $mimeTypes) { echo ', \''.$mimeTypes.'\'' ; } ?>];
var Msg_errorFileSize = '<?php printf(_('this file exceeds the allowed size %s'), $config['maxUploadPerFile']) ?>';
var Msg_errorTotalSize = '<?php printf(_('The total size of the files exceeds the allowed size : %s'), $config['maxUploadTotal']) ?>';
var Msg_errorUploadNb = '<?php printf(_('You can not send more than %d files at a time'), $config['maxUploadNb']) ?>';
var Msg_errorFileType = '<?php printf(_('this type of file isn\\\'t allow')) ?>';
var filesUploadQueu=0;
</script>
<script src="<?= $config['baseUrl'] ?>lib/upload.js"></script>
<link rel="stylesheet" href="<?= $config['baseUrl'] ?>lib/style.css" />
<link rel="stylesheet" href="<?= $config['baseUrl'] ?>lib/css-file-icons.css" />
<link rel="apple-touch-icon" sizes="180x180" href="<?= $config['baseUrl'] ?>/apple-touch-icon.png">
@ -226,9 +228,21 @@ if ($passwordForm == false) {
$( document ).tooltip();
} );
</script>
<!-- Bootstrap styles -->
<!--
<link rel="stylesheet" href="<?= $config['baseUrl'] ?>lib/bootstrap.min.css" />
-->
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"
/>
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
<link rel="stylesheet" href="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/css/jquery.fileupload.css" />
<link rel="stylesheet" href="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/css/jquery.fileupload-ui.css" />
</head>
<body>
<div id="langues">
<?php
foreach($langueEtLocalDispo as $langShort=>$lang) {
@ -242,7 +256,7 @@ if ($passwordForm == false) {
?>
</div>
<div id="languesLegende" style="display: none"></div>
<div id="page-wrap">
<div id="page-wrap">
<?php
if ($config['maintenanceMod'] == true && $config['mainteneurIp'] != $_SERVER['REMOTE_ADDR']) {
echo '<h1>'._('Maintenance').'</h2>';
@ -283,14 +297,119 @@ if ($passwordForm == false) {
if ($passwordForm == true) {
$action = 'password';
}
$echoNewUpload = '<div class="newUpload"><a href="'.$config['baseUrl'].'" rel="tooltip" class="bulles" title="'._('Send a new file').'"><img src="'.$config['baseUrl'].'/lib/upload.svg" /></a>
<a rel="tooltip" class="bulles myFiles" title="'._('See the files already sent').'" href="'.$config['baseUrl'].'/My"><img src="'.$config['baseUrl'].'/lib/folder.svg" /></a>
'.$similarServicesLink.'</div>
<script>
if (localStorage.getItem(\'myFiles\')) {
$(\'.myFiles\').show();
$echoNewUploadPub = '<div id="newUploadPub"><a href="'.$config['baseUrl'].'">'._('Send / share your files').'</a></div>';
$echoNewUpload = '<div id="newUpload" class="newUpload"><noscript><h3>You must have JavaScript enabled in order to use this site. Please enable JavaScript and then reload this page in order to continue. </h3> </noscript>
<!-- The file upload form used as target for the file upload widget -->
<form
id="fileupload"
action=""
method="POST"
enctype="multipart/form-data"
>
<input type="hidden" value="" id="files_key" name="key" />
<input type="hidden" value="" id="files_id" name="id" />
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="fileupload-buttonbar">
<div class="expire-button">'._('Expire').' : <select name="expire" id="expire">';
foreach ($config['expireDay'] as $expireDay) {
$dayOrDays=_('days');
if ($expireDay == 1) {
$dayOrDays=_('day');
}
if ($expireDay == $config['expireDayDefault']) {
$echoNewUpload .= '<option value="'.$expireDay.'" selected="selected">'.$expireDay.' '.$dayOrDays.'</option>';
} else {
$echoNewUpload .= '<option value="'.$expireDay.'" >'.$expireDay.' '.$dayOrDays.'</option>';
}
}
$echoNewUpload .= '
</select></div>
<div class="boutton">
<!-- The fileinput-button span is used to style the file input field as button -->
<span id="ButtonAdd" class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>'._('Add files...').'</span>
<input type="file" name="files[]" multiple />
</span>
<button id="ButtonStart" type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>'._('Start upload').'</span>
</button>
<button id="ButtonReset" type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>'._('Cancel upload').'</span>
</button>
<button id="ButtonMyFiles" type="reset" onclick="location.href=\''.$config['baseUrl'].'/My\';" class="bulles myFiles btn btn-info">
<i class="glyphicon glyphicon-folder-open"></i>
<span>'._('See the files already sent').'</span>
</button>
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<div id="redirectToFiles">Redirect to '.$config['baseUrl'].'<span id="redirectToFilesId"></span>/ in progress...</div>
<div class="error" id="maxUploadTotalError">'.
_('The total limit per upload is ').$config['maxUploadTotal']
.'</div>
<!-- The global progress state -->
<div class="fileupload-progress fade">
<!-- The global progress bar -->
<div
class="progress progress-striped active"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar progress-bar-success"
style="width: 0%;"
></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended">&nbsp;</div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped">
<tbody class="files"></tbody>
</table>
<div class="shareUrlPrint file fileJust1 read input">'._('The sharing will be accessible from').' : <input class="copy read fileAll" name="read" type="text" value="'.$config['baseUrl'].$id.'/" id="shareUrl" readonly=""></div>
<a id="uploadOptionsLinkShow" class="uploadOptionsLink">'._('Options').' &#8642;</a>
<div id="uploadOptions">
<a id="uploadOptionsLinkHide" class="uploadOptionsLink">'._('Options').' &#8638;</a>
<p id="resizeForm">'._('Images resize').' : <select name="resize" id="resize">';
foreach ($config['imageResize'] as $imageResize) {
$imageResizeName = $imageResize.'px';
$imageResizeValue = $imageResize;
if ($imageResize == 0) {
$imageResizeName = _('No resizing');
$imageResizeValue=999999;
}
</script>';
if ($imageResize == $config['imageResizeDefault']) {
$echoNewUpload .= '<option value="'.$imageResize.'" selected="selected">'.$imageResizeName.'</option>';
} else {
$echoNewUpload .= '<option value="'.$imageResize.'" >'.$imageResizeName.'</option>';
}
}
$echoNewUpload .= '</select></p>
<p id="uploadOptionPassword"><input type="checkbox" name="passwordCheckbox" id="passwordCheckbox" />'._('Protect with password').'<span id="passwordForm"> : <br /><input type="password" name="password" id="password" autocomplete="off" /></span></p>
<p id="uploadOptionAccess"><input type="checkbox" name="accessCheckbox" id="accessCheckbox" />'._('Delete after access').'<span id="accessForm"> : <br /><input title="'._('Number of accesses before deletion (1 minimum)').'" type="number" min="1" max="999999" step="1" name="access" id="access" value="'.$config['deleteAfterAccessDefault'].'" /></span></p>
</div>
</form>
<div>
</div>
<div class="limit"><p>'.
_('The limit per file is ').$config['maxUploadPerFile']
.'</p><p>'.
_('The total limit per upload is ').$config['maxUploadTotal']
.'</p></div>
<script>
if (localStorage.getItem(\'myFiles\')) {
$(\'.myFiles\').show();
}
</script></div>';
switch ($action) {
case 'ErrorUploadDir':
echo '<div class="highlight-1">';
@ -298,7 +417,8 @@ if ($passwordForm == false) {
echo '</div>';
break;
case 'password':
echo '<h1>'.$config['shortTitle'].' : '.$config['title'].'</h1>';
echo '<h1><a href="'.$config['baseUrl'].'">'.$config['shortTitle'].'</a> : '.$config['title'].'</h1>';
echo $echoNewUploadPub;
if (isset($_POST['password']) && $passwordInvalid == true) {
echo '<div class="highlight-1">';
echo _('Error: Incorrect password');
@ -330,7 +450,8 @@ if ($passwordForm == false) {
echo $echoNewUpload;
break;
case 'html':
echo '<h1>'.$config['shortTitle'].' : '.$config['title'].'</h1>';
echo '<h1><a href="'.$config['baseUrl'].'">'.$config['shortTitle'].'</a> : '.$config['title'].'</h1>';
echo $echoNewUploadPub;
$expire=explode('-', $id);
$dateExpire=date('d/m/Y H:m', $expire[0]);
$dStart = new DateTime(date('Y-m-d', $expire[0]));
@ -397,10 +518,10 @@ if ($passwordForm == false) {
echo '<div style="float: left; border: 1px solid #C6C6C6;" class="file file'.$idFile.' icone">';
if (preg_match('/^image\/(png|jpeg|gif)$/', mime_content_type($pathInfo['dirname'].'/'.$pathInfo['basename']))) {
if (!is_file($pathInfo['dirname'].'/.'.$pathInfo['basename'].'.gallery.small')) {
resize_image($pathInfo['dirname'].'/'.$pathInfo['basename'], $pathInfo['dirname'].'/.'.$pathInfo['basename'].'.gallery.small' , 250, 250);
resize_image($pathInfo['dirname'].'/'.$pathInfo['basename'], $pathInfo['dirname'].'/.'.$pathInfo['basename'].'.gallery.small' , 330, 330);
}
if (is_file($pathInfo['dirname'].'/.'.$pathInfo['basename'].'.gallery.small')) {
echo '<div class="item" data-src="'.$config['baseUrl'].$id.'/'.$fileInUploadDirId.'"><img width="250" src="'.$config['baseUrl'].$id.'/.'.$pathInfo['basename'].'.gallery.small" /></a></div>';
echo '<div class="item" data-src="'.$config['baseUrl'].$id.'/'.$fileInUploadDirId.'"><img width="330" src="'.$config['baseUrl'].$id.'/.'.$pathInfo['basename'].'.gallery.small" /></a></div>';
} else {
echo '<a href="'.$linkDownload.'" target="_blank"><div class="fi fi-'.$pathInfo['extension'].' fi-size-xl"><div class="fi-content">'.$pathInfo['extension'].'</div></div></a>';
}
@ -432,7 +553,7 @@ if ($passwordForm == false) {
$pathInfo = pathinfo($uploadDirId.'/'.$fileInUploadDirId);
$linkDownload=$config['baseUrl'].'dl/'.$id.'/'.$fileInUploadDirId;
echo '<div class="viewNormal fileGlobal file'.$idFile.' file-ext-'.$pathInfo['extension'].'" >';
echo '<div class="file file'.$idFile.' icone delete"><a href="'.$config['baseUrl'].'del/'.$id.'/KEYHERE/'.$pathInfo['basename'].'" class="deleteLink"><img src="'.$config['baseUrl'].'/lib/trash.svg" /></a></div>';
echo '<div class="file file'.$idFile.' icone delete"><a href="'.$config['baseUrl'].'del/'.$id.'/KEYHERE/'.$pathInfo['basename'].'" class="deleteLink">azer<img src="'.$config['baseUrl'].'/lib/trash.svg" /></a></div>';
echo '<div class="file file'.$idFile.' icone">';
if (preg_match('/^image\/(png|jpeg|gif)$/', mime_content_type($pathInfo['dirname'].'/'.$pathInfo['basename']))) {
if (!is_file($pathInfo['dirname'].'/.'.$pathInfo['basename'].'.small')) {
@ -460,7 +581,9 @@ if ($passwordForm == false) {
}
echo '</div>';
}
echo '<div id="addToShare"><h3>'._('Add files to this share').'</h3>';
echo $echoNewUpload;
echo '</div>';
?>
<script type="text/javascript">
$(document).ready(function() {
@ -480,7 +603,12 @@ if ($passwordForm == false) {
var searchWithId = storageMyFiles.items.filter(function(e) { return e.id === '<?= $id ?>'; })
var keyForThis = Object.values(searchWithId[0])[1];
$('.deleteAll').show();
$('.delete').show();
$('.delete').show();
$('#files_key').val(keyForThis);
$('#uploadOptionPassword').hide();
$('#uploadOptionAccess').hide();
$('.expire-button').hide();
$('#addToShare').show();
var links = $('.deleteLink');
for(var i = 0; i< links.length; i++){
var oldLink = links[i].href;
@ -493,7 +621,11 @@ if ($passwordForm == false) {
var newLink = oldLink.replace('KEYHERE', keyForThis);
links[i].href = newLink;
}
} else {
$('#addToShare').hide();
}
} else {
$('#addToShare').hide();
}
function deleteLast(href) {
@ -502,7 +634,6 @@ if ($passwordForm == false) {
var key = false;
for (var i = 0; i < hrefSplit.length; i++) {
var regexTimestamp = RegExp('^[0-9]+-[0-9]{1,2}$');
console.log(hrefSplit[i]);
if (regexTimestamp.test(hrefSplit[i])) {
id=hrefSplit[i];
}
@ -554,9 +685,6 @@ if ($passwordForm == false) {
return false;
}
});
<?php
// $nbFile
?>
</script>
<?php
@ -564,6 +692,7 @@ if ($passwordForm == false) {
case 'myFiles':
?>
<h1><?= $config['shortTitle'] ?> : <?= _('My files') ?></h1>
<?= $echoNewUploadPub ?>
<p><?= _('Online file sharing service <a href="https://en.wikipedia.org/wiki/Open_source">free of rights</a> (license <a href="https://en.wikipedia.org/wiki/Beerware">Beerware</a>) and free.') ?></p>
<table id="myFilesTab">
<tr><th> - </th><th><?= _('Nb of files') ?></th><th><?= _('Creation date ') ?></th><th><?= _('Expiration date') ?></th><th><?= _('Size') ?></th><th><?= _('Remaining access') ?></th><th><?= _('Password') ?></th><th><?= _('Link') ?></th></tr>
@ -619,12 +748,14 @@ if ($passwordForm == false) {
echo $echoNewUpload;
break;
case '403':
echo '<h1>'.$config['shortTitle'].' : 403 '._('Unauthorized access').'</h1>';
echo '<h1><a href="'.$config['baseUrl'].'">'.$config['shortTitle'].'</a> : 403 '._('Unauthorized access').'</h1>';
echo $echoNewUploadPub;
echo '<p>'._('Unauthorized access').'</p>';
echo $echoNewUpload;
break;
case '404':
echo '<h1>'.$config['shortTitle'].' : 404 '._('Not Found').'</h1>';
echo '<h1><a href="'.$config['baseUrl'].'">'.$config['shortTitle'].'</a> : 404 '._('Not Found').'</h1>';
echo $echoNewUploadPub;
echo '<p>'._('This sharing does not exist, it has probably expired').'</p>';
echo $echoNewUpload;
break;
@ -632,7 +763,7 @@ if ($passwordForm == false) {
?>
<h1><?= $config['shortTitle'] ?> : <?= $config['title'] ?></h1>
<h1><a href="<?= $config['baseUrl'] ?>"><?= $config['shortTitle'] ?></a> : <?= $config['title'] ?></h1>
<?php @include_once('./start-home.php'); ?>
<p><?= _('Online file sharing service <a href="https://en.wikipedia.org/wiki/Open_source">free of rights</a> (license <a href="https://en.wikipedia.org/wiki/Beerware">Beerware</a>) and free.') ?></p>
<div id="preUpload"></div>
@ -640,56 +771,9 @@ if ($passwordForm == false) {
<div id="result"></div>
<div class="uploadArea">
<div id="uploadInput"><input title="<?= _('Choose one or more files') ?>" type="file" id="files" name="files[]" multiple/></div>
<div class="newUpload"><img title="<?= _('Send file') ?>" class="btn-upload" src="<?= $config['baseUrl'] ?>/lib/upload.svg" />
<a class="myFiles" title="<?= _('See the files already sent') ?>" href="<?= $config['baseUrl'] ?>/My"><img src="<?= $config['baseUrl'] ?>/lib/folder.svg" /></a>
<script>
if (localStorage.getItem('myFiles')) {
$('.myFiles').show();
}
</script></div>
<div><?= _('Expire') ?> : <select name="expire" id="expire">
<?php
foreach ($config['expireDay'] as $expireDay) {
$dayOrDays=_('days');
if ($expireDay == 1) {
$dayOrDays=_('day');
}
if ($expireDay == $config['expireDayDefault']) {
echo '<option value="'.$expireDay.'" selected="selected">'.$expireDay.' '.$dayOrDays.'</option>';
} else {
echo '<option value="'.$expireDay.'" >'.$expireDay.' '.$dayOrDays.'</option>';
}
}
?>
</select></div>
<a id="uploadOptionsLinkShow" class="uploadOptionsLink"><?= _('Options') ?> &#8642;</a>
<div id="uploadOptions">
<a id="uploadOptionsLinkHide" class="uploadOptionsLink"><?= _('Options') ?> &#8638;</a>
<p><input type="checkbox" name="passwordCheckbox" id="passwordCheckbox" /><?= _('Protect with password') ?><span id="passwordForm"> : <br /><input type="password" name="password" id="password" autocomplete="off" /></span></p>
<p id="uploadOptionAccess"><input type="checkbox" name="accessCheckbox" id="accessCheckbox" /><?= _('Delete after access') ?><span id="accessForm"> : <br /><input title="<?= _('Number of accesses before deletion (1 minimum)') ?> "type="number" min="1" max="999999" step="1" name="access" id="access" value="<?= $config['deleteAfterAccessDefault'] ?>" /></span></p>
</div>
<div id="resizeForm"><?= _('Images resize') ?> : <select name="resize" id="resize">
<?php
foreach ($config['imageResize'] as $imageResize) {
$imageResizeName = $imageResize.'px';
if ($imageResize == 0) {
$imageResizeName = _('No resizing');
}
if ($imageResize == $config['imageResizeDefault']) {
echo '<option value="'.$imageResize.'" selected="selected">'.$imageResizeName.'</option>';
} else {
echo '<option value="'.$imageResize.'" >'.$imageResizeName.'</option>';
}
}
?>
</select></div>
<div class="limit"><?php printf(_('The limit per file is %dM, and the total limit per upload is %dM'), $config['maxUploadPerFile'], $config['maxUploadTotal']); ?></div>
<?= $echoNewUpload ?>
<?= $similarServicesLink ?>
</div>
<!-- For progress bars -->
<div class="progress"></div>
<?php
@include_once('./end-home.php');
}
@ -741,7 +825,286 @@ if ($passwordForm == false) {
</div>
<div id="bg">
<img src="<?= $config['backgroundImage'] ?>" alt="">
</div>
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
{% if (window.innerWidth > 480 || !o.options.loadImageFileTypes.test(file.type)) { %}
<p class="name">{%=file.name%}</p>
{% } %}
<strong class="error text-danger"></strong>
</td>
<td>
<p class="size">Processing...</p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
</td>
<td>
{% if (!o.options.autoUpload && o.options.edit && o.options.loadImageFileTypes.test(file.type)) { %}
<button class="btn btn-success edit" data-index="{%=i%}" disabled>
<i class="glyphicon glyphicon-edit"></i>
<span>Edit</span>
</button>
{% } %}
{% if (!i && !o.options.autoUpload) { %}
<button style="display: none" class="btn btn-primary start" disabled>
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
{% } %}
{% if (!i) { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span><?= _('Cancel') ?></span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td>
<span class="preview">
{% if (file.thumbnailUrl) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
{% } %}
</span>
</td>
<td>
{% if (window.innerWidth > 480 || !file.thumbnailUrl) { %}
<p class="name">
{% if (file.url) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
{% } else { %}
<span>{%=file.name%}</span>
{% } %}
</p>
{% } %}
{% if (file.error) { %}
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span><?= _('Cancel') ?></span>
</button>
</td>
</tr>
{% } %}
</script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<!--
<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
-->
<script src="<?= $config['baseUrl'] ?>lib/blueimp/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<!--
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
-->
<script src="<?= $config['baseUrl'] ?>lib/blueimp/load-image.all.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<!--
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
-->
<script src="<?= $config['baseUrl'] ?>lib/blueimp/canvas-to-blob.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload.js"></script>
<!-- The File Upload processing plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload-process.js"></script>
<!-- The File Upload image preview & resize plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload-image.js"></script>
<!-- The File Upload audio preview plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload-audio.js"></script>
<!-- The File Upload video preview plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload-video.js"></script>
<!-- The File Upload validation plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload-validate.js"></script>
<!-- The File Upload user interface plugin -->
<script src="<?= $config['baseUrl'] ?>lib/jQuery-File-Upload/js/jquery.fileupload-ui.js"></script>
<script type="text/javascript">
function convertHumain2octect(value) {
var regexKB = RegExp('KB$');
var regexMB = RegExp('MB$');
var regexGB = RegExp('GB$');
if (regexKB.test(value)) {
return parseFloat(fileSize)*1024;
}else if (regexMB.test(value)) {
return parseFloat(fileSize)*1024*1024;
}else if (regexGB.test(value)) {
return parseFloat(fileSize)*1024*1024*1024;
}
}
function convertOctect2Humain(value) {
if (value > 1000000000) {
return (value/1024/1024/1024).toFixed(2) + ' Go';
}else if (value > 1000000) {
return (value/1024/1024).toFixed(2) + ' Mo';
}else if (value > 1000) {
return (value/1024).toFixed(2) + ' Ko';
} else {
return value;
}
}
function checkQuotaFiles() {
<?php
if ($action == 'html') {
$fileAlreadyUploadSizeTotal=0;
$uploadDir=$config['uploadDir'].'/'.$id.'/';
foreach (scandir($uploadDir) as $fileAlreadyUpload) {
if (is_file($uploadDir.$fileAlreadyUpload)) {
$fileAlreadyUploadSizeTotal=filesize($uploadDir.$fileAlreadyUpload)+$fileAlreadyUploadSizeTotal;
}
}
echo 'var totalSize='.$fileAlreadyUploadSizeTotal.';';
} else {
echo 'var totalSize=0;';
}
?>
//~ console.log(totalSize);
findUploadFiles=$('#fileupload').find('.size').get();
for(var i = 0; i< findUploadFiles.length; i++){
fileSize=findUploadFiles[i].innerText;
totalSize=totalSize+convertHumain2octect(fileSize);
}
if (totalSize > <?= convertHumain2octect($config['maxUploadTotal']) ?>) {
$('#maxUploadTotalError').show();
$('#ButtonAdd').hide();
$('#ButtonStart').hide();
} else {
$('#maxUploadTotalError').hide();
$('#ButtonAdd').show();
$('#ButtonStart').show();
}
if (findUploadFiles.length > 0) {
$('#ButtonReset').show();
} else {
$('#ButtonReset').hide();
$('#ButtonStart').hide();
}
//~ console.log(totalSize);
return true;
}
$('#fileupload').fileupload({
url: '<?= $config['baseUrl']?>/upload.php',
added: function (e) {
checkQuotaFiles();
},
started: function (e) {
console.log('started');
$('.shareUrlPrint').show();
$('.expire-button').hide();
$('#uploadOptionsLinkShow').hide();
$('#uploadOptions').hide();
$('#ButtonStart').hide();
$('#ButtonMyFiles').hide();
$('#ButtonAdd').hide();
},
// Se déclenche
finished: function (e, data) {
// Si ce n'est pas une annulatoin mais bien une fin d'upload
if (data.errorThrown != 'abort') {
// On mémorise l'upload dans le localStorage
if (localStorage.getItem('myFiles')) {
var data = JSON.parse(localStorage.getItem('myFiles'));
} else {
var data = {items: []};
}
// S'il n'existe pas déjà
if (data.items.filter(function(e) { return e.id === $('#files_id').val(); }).length == 0) {
data.items.push(
{id: $('#files_id').val(), key: $('#files_key').val()}
);
localStorage.setItem('myFiles', JSON.stringify(data));
}
}
},
failed: function (e, data) {
// Si un upload est en cours
if (data.loaded > 0) {
//~ console.log(data);
location.href='<?= $config['baseUrl']?>/'+$('#files_id').val()+'/';
$('#files_id').val(idGen());
$('#shareUrl').val('<?= $config['baseUrl'] ?>/' + $('#files_id').val() + '/');
var keyGen = Math.floor(Math.random() * (999999999999 - 100000000000) + 100000000000);
$('#files_key').val(keyGen);
} else {
checkQuotaFiles();
}
}
});
// Enable iframe cross-domain access via redirect option:
//~ $('#fileupload').fileupload(
//~ 'option',
//~ 'redirect',
//~ window.location.href.replace(/\/[^/]*$/, 'lib/jQuery-File-Upload-master//cors/result.html?%s')
//~ );
function redirectToFiles() {
location.replace('<?= $config['baseUrl']?>/'+ $('#files_id').val() + '/');
}
$('#fileupload').fileupload('option', {
// 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
),
imageMaxWidth: $('#resize').val(),
imageMaxHeight: $('#resize').val(),
maxFileSize: <?= convertHumain2octect($config['maxUploadPerFile']) ?>,
minFileSize: <?= convertHumain2octect($config['minUploadPerFile']) ?>,
maxNumberOfFiles: <?= $config['maxUploadNb'] ?>,
sequentialUploads: true,
limitConcurrentUploads: 1, // To limit the number of concurrent uploads, set this option to an integer value greater than 0.
acceptFileTypes: <?= $config['acceptFileTypes'] ?>
}).on('fileuploadprogressall', function (e, data) {
if (data.loaded == data.total) {
$('#ButtonReset').hide();
$('.btn.btn-warning.cancel').hide();
$('#redirectToFiles').show();
$('.redirectToFilesId').text($('#files_id').val());
setTimeout(redirectToFiles, 1000);
}
});
<?php if ($action == 'html') { ?>
$('#files_id').val('<?= $id ?>');
<?php } else { ?>
$('#files_id').val(idGen());
var keyGen = Math.floor(Math.random() * (999999999999 - 100000000000) + 100000000000);
$('#files_key').val(keyGen);
<?php } ?>
$('#shareUrl').val('<?= $config['baseUrl'] ?>/' + $('#files_id').val() + '/');
</script>
<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
<!--[if (gte IE 8)&(lt IE 10)]>
<script src="js/cors/jquery.xdr-transport.js"></script>
<![endif]-->
</body>
</html>
<?php

213
jquery-file-upload.html Executable file
View file

@ -0,0 +1,213 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery File Upload Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Bootstrap styles -->
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"
/>
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
<link rel="stylesheet" href="./lib/jQuery-File-Upload-master/css/jquery.fileupload.css" />
<link rel="stylesheet" href="./lib/jQuery-File-Upload-master/css/jquery.fileupload-ui.css" />
<!-- CSS adjustments for browsers with JavaScript disabled -->
<!--
<noscript
><link rel="stylesheet" href="./lib/jQuery-File-Upload-master/css/jquery.fileupload-noscript.css"
/></noscript>
<noscript
><link rel="stylesheet" href="./lib/jQuery-File-Upload-master/css/jquery.fileupload-ui-noscript.css"
/></noscript>
-->
</head>
<body>
<div class="container">
<noscript><h3>You must have JavaScript enabled in order to use this site. Please enable JavaScript and then reload this page in order to continue. </h3> </noscript>
<!-- The file upload form used as target for the file upload widget -->
<form
id="fileupload"
action=""
method="POST"
enctype="multipart/form-data"
>
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple />
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="col-lg-5 fileupload-progress fade">
<!-- The global progress bar -->
<div
class="progress progress-striped active"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar progress-bar-success"
style="width: 0%;"
></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended">&nbsp;</div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped">
<tbody class="files"></tbody>
</table>
</form>
</div>
<!--
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev"></a>
<a class="next"></a>
<a class="close">×</a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
-->
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
{% if (window.innerWidth > 480 || !o.options.loadImageFileTypes.test(file.type)) { %}
<p class="name">{%=file.name%}</p>
{% } %}
<strong class="error text-danger"></strong>
</td>
<td>
<p class="size">Processing...</p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
</td>
<td>
{% if (!o.options.autoUpload && o.options.edit && o.options.loadImageFileTypes.test(file.type)) { %}
<button class="btn btn-success edit" data-index="{%=i%}" disabled>
<i class="glyphicon glyphicon-edit"></i>
<span>Edit</span>
</button>
{% } %}
{% if (!i && !o.options.autoUpload) { %}
<button style="display: none" class="btn btn-primary start" disabled>
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
{% } %}
{% if (!i) { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td>
<span class="preview">
{% if (file.thumbnailUrl) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
{% } %}
</span>
</td>
<td>
{% if (window.innerWidth > 480 || !file.thumbnailUrl) { %}
<p class="name">
{% if (file.url) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
{% } else { %}
<span>{%=file.name%}</span>
{% } %}
</p>
{% } %}
{% if (file.error) { %}
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
</td>
</tr>
{% } %}
</script>
<script
src="./lib/jquery-3.1.0.min.js"
crossorigin="anonymous"
></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="./lib/jQuery-File-Upload-master/js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<!--
<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
-->
<script src="./lib/blueimp-tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<!--
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
-->
<script src="./lib/blueimp-load-image.all.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<!--
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
-->
<script src="./lib/blueimp-canvas-to-blob.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload.js"></script>
<!-- The File Upload processing plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload-process.js"></script>
<!-- The File Upload image preview & resize plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload-image.js"></script>
<!-- The File Upload audio preview plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload-audio.js"></script>
<!-- The File Upload video preview plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload-video.js"></script>
<!-- The File Upload validation plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload-validate.js"></script>
<!-- The File Upload user interface plugin -->
<script src="./lib/jQuery-File-Upload-master/js/jquery.fileupload-ui.js"></script>
<!-- The main application script -->
<script src="./lib/jQuery-File-Upload-master/js/f2l.js"></script>
<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
<!--[if (gte IE 8)&(lt IE 10)]>
<script src="js/cors/jquery.xdr-transport.js"></script>
<![endif]-->
</body>
</html>

Binary file not shown.

View file

@ -7,240 +7,322 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-11-20 01:37+0100\n"
"PO-Revision-Date: 2019-11-20 01:47+0100\n"
"POT-Creation-Date: 2020-05-01 23:52+0200\n"
"PO-Revision-Date: 2020-05-02 00:48+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.2.4\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: cron.php:7
#: cron.php:8
msgid "Start the command in the file2link directory"
msgstr "Lancer la commande dans le répertoire de travail file2link"
#: cron.php:10
#: cron.php:11
msgid "Completed"
msgstr "Terminé"
#: cron.php:12
#: cron.php:13
msgid "expireCron is not at \"cli\" mod (in config.yaml)"
msgstr "expireCron n'est pas à la valeur \"cli\" (dans le config.yaml)"
#: functions.php:111
#: functions.php:94
msgid "Expired"
msgstr "Expiré"
#: index.php:66
#, php-format
msgid ""
"In coherence with your configuration (config.yaml) you must increase the PHP "
"configuration upload_max_filesize to %s"
msgstr ""
"En cohérence avec votre configuration (config.yaml), vous devez modifier la "
"configuration PHP upload_max_filesize à %s"
#: index.php:69
#, php-format
msgid ""
"In coherence with your configuration (config.yaml) you must increase the PHP "
"configuration post_max_size to %s"
msgstr ""
"En cohérence avec votre configuration (config.yaml), vous devez modifier la "
"configuration PHP post_max_size à %s"
msgid "In coherence with your configuration (config.yaml) you must increase the PHP configuration upload_max_filesize to %s"
msgstr "En cohérence avec votre configuration (config.yaml), vous devez modifier la configuration PHP upload_max_filesize à %s"
#: index.php:72
#, php-format
msgid ""
"In coherence with your configuration (config.yaml) you must increase the PHP "
"configuration max_file_uploads to %s"
msgstr ""
"En cohérence avec votre configuration (config.yaml), vous devez modifier la "
"configuration PHP max_file_uploads à %s"
msgid "In coherence with your configuration (config.yaml) you must increase the PHP configuration post_max_size to %s"
msgstr "En cohérence avec votre configuration (config.yaml), vous devez modifier la configuration PHP post_max_size à %s"
#: index.php:171 upload.php:43
#: index.php:75
#, php-format
msgid "In coherence with your configuration (config.yaml) you must increase the PHP configuration max_file_uploads to %s"
msgstr "En cohérence avec votre configuration (config.yaml), vous devez modifier la configuration PHP max_file_uploads à %s"
#: index.php:207
#, php-format
msgid "this file exceeds the allowed size %s"
msgstr "ce fichier dépasse la taille autorisée %s"
#: index.php:172
#: index.php:208
#, php-format
msgid "The total size of the files exceeds the allowed size : %s"
msgstr "La taille totale des fichiers dépasse la taille autorisée: %s"
#: index.php:173
#: index.php:209
#, php-format
msgid "You can not send more than %d files at a time"
msgstr "Vous ne pouvez pas envoyer plus de %d fichiers à la fois"
#: index.php:174
#: index.php:210
#, php-format
msgid "this type of file isn\\'t allow"
msgstr "ce type de fichier nautorise pas"
#: index.php:210
#: index.php:265
msgid "Maintenance"
msgstr "Maintenance"
#: index.php:216
#: index.php:271
msgid "Mode Maintenance as true"
msgstr "Le mode maintenance est activé"
#: index.php:223
#: index.php:278
msgid "Similar services"
msgstr "Services similaires"
#: index.php:245
msgid "Send a new file"
msgstr "Envoyez un nouveau fichier"
#: index.php:303
msgid "Send / share your files"
msgstr "Envoyer/partager vos fichier"
#: index.php:246
msgid "See the files already sent"
msgstr "Voir les fichiers déjà envoyés"
#: index.php:256
#, php-format
msgid ""
"Error: The directory (%s) is not writable, please contact the service "
"administrator"
msgstr ""
"Erreur: le répertoire (%s) n'est pas accessible en écriture, veuillez "
"contacter l'administrateur du service"
#: index.php:267 index.php:269
msgid "The requested page does not exist"
msgstr "La page demandée n'existe pas"
#: index.php:289
#, php-format
msgid "These files will be automatically deleted on %s, ie in %d days"
msgstr ""
"Ces fichiers seront automatiquement supprimés le %s, c'est-à-dire dans %d "
"jours"
#: index.php:301
msgid "Error: Nothing to display"
msgstr "Erreur: rien à afficher"
#: index.php:305
msgid "This page"
msgstr "Cette page"
#: index.php:312
msgid "All"
msgstr "Tout"
#: index.php:312
msgid "Delete all (permanently)"
msgstr "Supprimer tout (définitivement)"
#: index.php:313 index.php:314 index.php:343 index.php:344
msgid "Click to copy the link to the clipboard"
msgstr "Cliquer pour copier le lien dans le presse papier"
#: index.php:339
msgid "Size"
msgstr "Taille"
#: index.php:340
msgid "Type"
msgstr "Type"
#: index.php:371
msgid "My files"
msgstr "Mes fichiers"
#: index.php:372 index.php:425
msgid ""
"Online file sharing service <a href=\"https://en.wikipedia.org/wiki/"
"Open_source\">free of rights</a> (license <a href=\"https://en.wikipedia.org/"
"wiki/Beerware\">Beerware</a>) and free."
msgstr ""
"Service de partage de fichiers en ligne <a href=\"https://en.wikipedia.org/"
"wiki/Open_source\"> libre de droits </a> (licence <a href = \"https://en."
"wikipedia.org/wiki/Beerware \"> Bière </a>) et gratuite."
#: index.php:377 index.php:439
#: index.php:316
msgid "Expire"
msgstr "Expiration"
#: index.php:377
msgid "Link"
msgstr "Lien"
#: index.php:318
msgid "days"
msgstr "jours"
#: index.php:400
msgid "No files, maybe all of them have expired."
msgstr "Aucun fichier, peut-être que tous ont expiré."
#: index.php:403
msgid "All your files have expired."
msgstr "Tous vos fichiers ont expiré."
#: index.php:410 index.php:411
msgid "Unauthorized access"
msgstr "Accès non autorisé"
#: index.php:415
msgid "Not Found"
msgstr "Introuvable"
#: index.php:416
msgid "This sharing does not exist, it has probably expired"
msgstr "Ce partage n'existe pas, il a probablement expiré"
#: index.php:443 index.php:445
#: index.php:320
msgid "day"
msgstr "jour"
#: index.php:450
#: index.php:334
msgid "Add files..."
msgstr "Ajouter un fichier"
#: index.php:339
msgid "Start upload"
msgstr "Démarrer l'envoi"
#: index.php:343
msgid "Cancel upload"
msgstr "Annuler l'envoi"
#: index.php:347
msgid "See the files already sent"
msgstr "Voir les fichiers déjà envoyés"
#: index.php:354 index.php:408
msgid "The total limit per upload is "
msgstr "La limite totale par envoi est de "
#: index.php:379
msgid "The sharing will be accessible from"
msgstr "Le partage sera accessible avec"
#: index.php:381 index.php:383
msgid "Options"
msgstr "Options"
#: index.php:384
msgid "Images resize"
msgstr "Redimensionner les images"
#: index.php:455
#: index.php:389
msgid "No resizing"
msgstr "Pas de redimensionnement"
#: index.php:465
#, php-format
msgid "The limit per file is %dM, and the total limit per upload is %dM"
msgstr ""
"La limite par fichier est de %dM et la limite totale par téléchargement est "
"de %dM"
#: index.php:399
msgid "Protect with password"
msgstr "Protéger avec un mot de passe"
#: index.php:475
#: index.php:400
msgid "Delete after access"
msgstr "Supprimer après l'accès"
#: index.php:400
msgid "Number of accesses before deletion (1 minimum)"
msgstr "Nombre d'accès avant suppression (1 minimum)"
#: index.php:406
msgid "The limit per file is "
msgstr "La limite par fichier est "
#: index.php:419
#, php-format
msgid "Error: The directory (%s) is not writable, please contact the service administrator"
msgstr "Erreur: le répertoire (%s) n'est pas accessible en écriture, veuillez contacter l'administrateur du service"
#: index.php:427
msgid "Error: Incorrect password"
msgstr "Erreur: mot de passe incorrect"
#: index.php:431
msgid "This file is protected by a password, thank you to indicate it below"
msgstr "Ce fichier est protégé par un mot de passe, merci de l'indiquer ci-dessous"
#: index.php:447 index.php:449
msgid "The requested page does not exist"
msgstr "La page demandée n'existe pas"
#: index.php:470
#, php-format
msgid "These files will be automatically deleted on %s, ie in %d days"
msgstr "Ces fichiers seront automatiquement supprimés le %s, c'est-à-dire dans %d jours"
#: index.php:478
#, php-format
msgid "These files will be automatically deleted in %d access"
msgstr "Ces fichiers seront automatiquement supprimés après %d accès"
#: index.php:497
msgid "View in list mode "
msgstr "Afficher en mode liste "
#: index.php:499
msgid "View in gallery mode "
msgstr "Afficher en mode galerie "
#: index.php:504
msgid "Error: Nothing to display"
msgstr "Erreur: rien à afficher"
#: index.php:509
msgid "This page"
msgstr "Cette page"
#: index.php:544
msgid "All"
msgstr "Tout"
#: index.php:544
msgid "Delete all (permanently)"
msgstr "Supprimer tout (définitivement)"
#: index.php:545 index.php:547 index.php:549 index.php:580 index.php:581
msgid "Click to copy the link to the clipboard"
msgstr "Cliquer pour copier le lien dans le presse papier"
#: index.php:576 index.php:701
msgid "Size"
msgstr "Taille"
#: index.php:577
msgid "Type"
msgstr "Type"
#: index.php:587
msgid "Add files to this share"
msgstr "Ajouter des fichiers à ce partage"
#: index.php:671
msgid "Are you sure you want to delete everything?"
msgstr "Voulez-vous vraiment tout supprimer?"
#: index.php:679
msgid "Are you sure you want to delete it?"
msgstr "Es-tu sûr de vouloir le supprimer?"
#: index.php:697
msgid "My files"
msgstr "Mes fichiers"
#: index.php:699 index.php:771
msgid "Online file sharing service <a href=\"https://en.wikipedia.org/wiki/Open_source\">free of rights</a> (license <a href=\"https://en.wikipedia.org/wiki/Beerware\">Beerware</a>) and free."
msgstr "Service de partage de fichiers en ligne <a href=\"https://en.wikipedia.org/wiki/Open_source\"> libre de droits </a> (licence <a href = \"https://en.wikipedia.org/wiki/Beerware \"> Bière </a>) et gratuite."
#: index.php:701
msgid "Nb of files"
msgstr "Nb de fichiers"
#: index.php:701
msgid "Creation date "
msgstr "Date de création "
#: index.php:701
msgid "Expiration date"
msgstr "Date d'expiration"
#: index.php:701
msgid "Remaining access"
msgstr "Accès restant"
#: index.php:701
msgid "Password"
msgstr "Mot de passe"
#: index.php:701 my.php:64
msgid "Link"
msgstr "Lien"
#: index.php:744
msgid "All your files have expired."
msgstr "Tous vos fichiers ont expiré."
#: index.php:746
msgid "No files, maybe all of them have expired."
msgstr "Aucun fichier, peut-être que tous ont expiré."
#: index.php:754 index.php:756
msgid "Unauthorized access"
msgstr "Accès non autorisé"
#: index.php:760
msgid "Not Found"
msgstr "Introuvable"
#: index.php:762
msgid "This sharing does not exist, it has probably expired"
msgstr "Ce partage n'existe pas, il a probablement expiré"
#: index.php:785
msgid "By"
msgstr "Par"
#: index.php:475
#: index.php:785
msgid "Git repository"
msgstr "Source git"
#: index.php:476
#: index.php:786
msgid "version"
msgstr "version"
#: index.php:476
msgid ""
"is an open software licensed <a href=\"https://en.wikipedia.org/wiki/Beerware"
"\">Beerware</a>"
msgstr ""
"est un logiciel libre sous licence <a href=\"https://en.wikipedia.org/wiki/"
"Beerware\"> Beerware </a>"
#: index.php:786
msgid "is an open software licensed <a href=\"https://en.wikipedia.org/wiki/Beerware\">Beerware</a>"
msgstr "est un logiciel libre sous licence <a href=\"https://en.wikipedia.org/wiki/Beerware\"> Beerware </a>"
#: upload.php:37
#, php-format
msgid "this type of file isn't allow"
msgstr "ce type de fichier n'est pas autorisé"
#: index.php:865 index.php:903
msgid "Cancel"
msgstr "Annuler"
#: upload.php:49
#, php-format
msgid "The total size of the files exceeds the allowed size %s"
msgstr "La taille totale des fichiers dépasse la taille autorisée %s"
#: my.php:42
msgid "Multi"
msgstr "Multi"
#: upload.php:71
#, php-format
msgid "Unknown error"
msgstr "Erreur inconnue"
#: my.php:57
msgid "Unlimited"
msgstr "Illimité"
#: my.php:60
msgid "Yes"
msgstr "Oui"
#: my.php:62
msgid "No"
msgstr "Non"
#~ msgid "Send a new file"
#~ msgstr "Envoyez un nouveau fichier"
#~ msgid "The limit per file is %dM, and the total limit per upload is %dM"
#~ msgstr "La limite par fichier est de %dM et la limite totale par téléchargement est de %dM"
#~ msgid "this type of file isn't allow"
#~ msgstr "ce type de fichier n'est pas autorisé"
#~ msgid "The total size of the files exceeds the allowed size %s"
#~ msgstr "La taille totale des fichiers dépasse la taille autorisée %s"
#~ msgid "Unknown error"
#~ msgstr "Erreur inconnue"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-05 14:57+0100\n"
"POT-Creation-Date: 2020-05-01 23:52+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -29,266 +29,285 @@ msgstr ""
msgid "expireCron is not at \"cli\" mod (in config.yaml)"
msgstr ""
#: functions.php:93
#: functions.php:94
msgid "Expired"
msgstr ""
#: index.php:68
#: index.php:69
#, php-format
msgid ""
"In coherence with your configuration (config.yaml) you must increase the PHP "
"configuration upload_max_filesize to %s"
msgstr ""
#: index.php:71
#: index.php:72
#, php-format
msgid ""
"In coherence with your configuration (config.yaml) you must increase the PHP "
"configuration post_max_size to %s"
msgstr ""
#: index.php:74
#: index.php:75
#, php-format
msgid ""
"In coherence with your configuration (config.yaml) you must increase the PHP "
"configuration max_file_uploads to %s"
msgstr ""
#: index.php:208 upload.php:59
#: index.php:207
#, php-format
msgid "this file exceeds the allowed size %s"
msgstr ""
#: index.php:209
#: index.php:208
#, php-format
msgid "The total size of the files exceeds the allowed size : %s"
msgstr ""
#: index.php:210
#: index.php:209
#, php-format
msgid "You can not send more than %d files at a time"
msgstr ""
#: index.php:211
#: index.php:210
#, php-format
msgid "this type of file isn\\'t allow"
msgstr ""
#: index.php:248
#: index.php:265
msgid "Maintenance"
msgstr ""
#: index.php:254
#: index.php:271
msgid "Mode Maintenance as true"
msgstr ""
#: index.php:261
#: index.php:278
msgid "Similar services"
msgstr ""
#: index.php:286
msgid "Send a new file"
#: index.php:303
msgid "Send / share your files"
msgstr ""
#: index.php:287 index.php:645
#: index.php:316
msgid "Expire"
msgstr ""
#: index.php:318
msgid "days"
msgstr ""
#: index.php:320
msgid "day"
msgstr ""
#: index.php:334
msgid "Add files..."
msgstr ""
#: index.php:339
msgid "Start upload"
msgstr ""
#: index.php:343
msgid "Cancel upload"
msgstr ""
#: index.php:347
msgid "See the files already sent"
msgstr ""
#: index.php:297
#: index.php:354 index.php:408
msgid "The total limit per upload is "
msgstr ""
#: index.php:379
msgid "The sharing will be accessible from"
msgstr ""
#: index.php:381 index.php:383
msgid "Options"
msgstr ""
#: index.php:384
msgid "Images resize"
msgstr ""
#: index.php:389
msgid "No resizing"
msgstr ""
#: index.php:399
msgid "Protect with password"
msgstr ""
#: index.php:400
msgid "Delete after access"
msgstr ""
#: index.php:400
msgid "Number of accesses before deletion (1 minimum)"
msgstr ""
#: index.php:406
msgid "The limit per file is "
msgstr ""
#: index.php:419
#, php-format
msgid ""
"Error: The directory (%s) is not writable, please contact the service "
"administrator"
msgstr ""
#: index.php:304
#: index.php:427
msgid "Error: Incorrect password"
msgstr ""
#: index.php:308
#: index.php:431
msgid "This file is protected by a password, thank you to indicate it below"
msgstr ""
#: index.php:324 index.php:326
#: index.php:447 index.php:449
msgid "The requested page does not exist"
msgstr ""
#: index.php:346
#: index.php:470
#, php-format
msgid "These files will be automatically deleted on %s, ie in %d days"
msgstr ""
#: index.php:354
#: index.php:478
#, php-format
msgid "These files will be automatically deleted in %d access"
msgstr ""
#: index.php:373
#: index.php:497
msgid "View in list mode "
msgstr ""
#: index.php:375
#: index.php:499
msgid "View in gallery mode "
msgstr ""
#: index.php:380
#: index.php:504
msgid "Error: Nothing to display"
msgstr ""
#: index.php:385
#: index.php:509
msgid "This page"
msgstr ""
#: index.php:420
#: index.php:544
msgid "All"
msgstr ""
#: index.php:420
#: index.php:544
msgid "Delete all (permanently)"
msgstr ""
#: index.php:421 index.php:423 index.php:425 index.php:456 index.php:457
#: index.php:545 index.php:547 index.php:549 index.php:580 index.php:581
msgid "Click to copy the link to the clipboard"
msgstr ""
#: index.php:452 index.php:569
#: index.php:576 index.php:701
msgid "Size"
msgstr ""
#: index.php:453
#: index.php:577
msgid "Type"
msgstr ""
#: index.php:537
#: index.php:587
msgid "Add files to this share"
msgstr ""
#: index.php:671
msgid "Are you sure you want to delete everything?"
msgstr ""
#: index.php:545
#: index.php:679
msgid "Are you sure you want to delete it?"
msgstr ""
#: index.php:566
#: index.php:697
msgid "My files"
msgstr ""
#: index.php:567 index.php:637
#: index.php:699 index.php:771
msgid ""
"Online file sharing service <a href=\"https://en.wikipedia.org/wiki/"
"Open_source\">free of rights</a> (license <a href=\"https://en.wikipedia.org/"
"wiki/Beerware\">Beerware</a>) and free."
msgstr ""
#: index.php:569
#: index.php:701
msgid "Nb of files"
msgstr ""
#: index.php:569
#: index.php:701
msgid "Creation date "
msgstr ""
#: index.php:569
#: index.php:701
msgid "Expiration date"
msgstr ""
#: index.php:569
#: index.php:701
msgid "Remaining access"
msgstr ""
#: index.php:569
#: index.php:701
msgid "Password"
msgstr ""
#: index.php:569 my.php:64
#: index.php:701 my.php:64
msgid "Link"
msgstr ""
#: index.php:612
#: index.php:744
msgid "All your files have expired."
msgstr ""
#: index.php:614
#: index.php:746
msgid "No files, maybe all of them have expired."
msgstr ""
#: index.php:622 index.php:623
#: index.php:754 index.php:756
msgid "Unauthorized access"
msgstr ""
#: index.php:627
#: index.php:760
msgid "Not Found"
msgstr ""
#: index.php:628
#: index.php:762
msgid "This sharing does not exist, it has probably expired"
msgstr ""
#: index.php:643
msgid "Choose one or more files"
msgstr ""
#: index.php:644
msgid "Send file"
msgstr ""
#: index.php:651
msgid "Expire"
msgstr ""
#: index.php:654
msgid "days"
msgstr ""
#: index.php:656
msgid "day"
msgstr ""
#: index.php:666 index.php:668
msgid "Options"
msgstr ""
#: index.php:669
msgid "Protect with password"
msgstr ""
#: index.php:670
msgid "Delete after access"
msgstr ""
#: index.php:670
msgid "Number of accesses before deletion (1 minimum)"
msgstr ""
#: index.php:673
msgid "Images resize"
msgstr ""
#: index.php:678
msgid "No resizing"
msgstr ""
#: index.php:688
#, php-format
msgid "The limit per file is %dM, and the total limit per upload is %dM"
msgstr ""
#: index.php:698
#: index.php:785
msgid "By"
msgstr ""
#: index.php:698
#: index.php:785
msgid "Git repository"
msgstr ""
#: index.php:699
#: index.php:786
msgid "version"
msgstr ""
#: index.php:699
#: index.php:786
msgid ""
"is an open software licensed <a href=\"https://en.wikipedia.org/wiki/Beerware"
"\">Beerware</a>"
msgstr ""
#: index.php:865 index.php:903
msgid "Cancel"
msgstr ""
#: my.php:42
msgid "Multi"
msgstr ""
@ -304,18 +323,3 @@ msgstr ""
#: my.php:62
msgid "No"
msgstr ""
#: upload.php:53
#, php-format
msgid "this type of file isn't allow"
msgstr ""
#: upload.php:65
#, php-format
msgid "The total size of the files exceeds the allowed size %s"
msgstr ""
#: upload.php:87
#, php-format
msgid "Unknown error"
msgstr ""

View file

@ -1,5 +1,7 @@
cp lib/functions.php .
cp lib/UploadHandler.php .
xgettext *.php -o lang/messages.pot --from-code="UTF-8"
msgmerge --no-wrap -N lang/fr/LC_MESSAGES/messages.po lang/messages.pot
msgmerge --no-wrap -N lang/fr/LC_MESSAGES/messages.po lang/messages.pot > lang/fr/LC_MESSAGES/messages.mo
msgmerge --no-wrap -N lang/fr/LC_MESSAGES/messages.po lang/messages.pot > lang/fr/LC_MESSAGES/messages.po_new
mv lang/fr/LC_MESSAGES/messages.po_new lang/fr/LC_MESSAGES/messages.po
rm functions.php
rm UploadHandler.php

1505
lib/UploadHandler.php Normal file

File diff suppressed because it is too large Load diff

1
lib/blueimp/canvas-to-blob.min.js vendored Normal file
View file

@ -0,0 +1 @@
!function(t){"use strict";var a=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,b=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),f=b&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),B=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,s=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,r=(b||B)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,o,n,a,r,i,l,u,c;if(!(e=t.match(s)))throw new Error("invalid data URI");for(o=e[2]?e[1]:"text/plain"+(e[3]||";charset=US-ASCII"),n=!!e[4],a=t.slice(e[0].length),r=(n?atob:decodeURIComponent)(a),i=new ArrayBuffer(r.length),l=new Uint8Array(i),u=0;u<r.length;u+=1)l[u]=r.charCodeAt(u);return b?new Blob([f?l:i],{type:o}):((c=new B).append(i),c.getBlob(o))};t.HTMLCanvasElement&&!a.toBlob&&(a.mozGetAsFile?a.toBlob=function(t,e,o){var n=this;setTimeout(function(){o&&a.toDataURL&&r?t(r(n.toDataURL(e,o))):t(n.mozGetAsFile("blob",e))})}:a.toDataURL&&r&&(a.msToBlob?a.toBlob=function(t,e,o){var n=this;setTimeout(function(){(e&&"image/png"!==e||o)&&a.toDataURL&&r?t(r(n.toDataURL(e,o))):t(n.msToBlob(e))})}:a.toBlob=function(t,e,o){var n=this;setTimeout(function(){t(r(n.toDataURL(e,o)))})})),"function"==typeof define&&define.amd?define(function(){return r}):"object"==typeof module&&module.exports?module.exports=r:t.dataURLtoBlob=r}(window);

1
lib/blueimp/load-image.all.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
lib/blueimp/tmpl.min.js vendored Normal file
View file

@ -0,0 +1 @@
!function(e){"use strict";var r=function(e,n){var t=/[^\w\-.:]/.test(e)?new Function(r.arg+",tmpl","var _e=tmpl.encode"+r.helper+",_s='"+e.replace(r.regexp,r.func)+"';return _s;"):r.cache[e]=r.cache[e]||r(r.load(e));return n?t(n,r):function(e){return t(e,r)}};r.cache={},r.load=function(e){return document.getElementById(e).innerHTML},r.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,r.func=function(e,n,t,r,c,u){return n?{"\n":"\\n","\r":"\\r","\t":"\\t"," ":" "}[n]||"\\"+n:t?"="===t?"'+_e("+r+")+'":"'+("+r+"==null?'':"+r+")+'":c?"';":u?"_s+='":void 0},r.encReg=/[<>&"'\x00]/g,r.encMap={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;","'":"&#39;"},r.encode=function(e){return(null==e?"":""+e).replace(r.encReg,function(e){return r.encMap[e]||""})},r.arg="o",r.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return r}):"object"==typeof module&&module.exports?module.exports=r:e.tmpl=r}(this);

6
lib/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
aria-hidden="true"
focusable="false"
data-prefix="far"
data-icon="folder"
class="svg-inline--fa fa-folder fa-w-16"
role="img"
viewBox="0 0 512 412"
version="1.1"
id="svg4"
sodipodi:docname="folder.svg"
width="512"
height="412"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1440"
inkscape:window-height="875"
id="namedview6"
showgrid="false"
inkscape:zoom="0.4609375"
inkscape:cx="256"
inkscape:cy="256"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M 464,78 H 272 L 217.37,23.37 c -6,-6 -14.14,-9.37 -22.63,-9.37 H 48 C 21.49,14 0,35.49 0,62 v 288 c 0,26.51 21.49,48 48,48 h 416 c 26.51,0 48,-21.49 48,-48 V 126 C 512,99.49 490.51,78 464,78 Z m 0,272 H 48 V 62 h 140.12 l 54.63,54.63 c 6,6 14.14,9.37 22.63,9.37 H 464 Z"
id="path2"
clip-path="none"
inkscape:connector-curvature="0"
style="fill:currentColor" />
</svg>

Before

Width:  |  Height:  |  Size: 2 KiB

1
lib/jQuery-File-Upload/.github/FUNDING.yml vendored Executable file
View file

@ -0,0 +1 @@
github: [blueimp]

View file

@ -0,0 +1,84 @@
name: Test
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: npm install
run: npm install
env:
CI: true
- name: lint
run: npm run lint
env:
CI: true
mocha:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: chmod
run: chmod -R 777 server/php/files
- name: docker-compose build
run: docker-compose build example mocha
- name: mocha
run: docker-compose run --rm mocha
- name: docker-compose logs
if: always()
run: docker-compose logs example
- name: docker-compose down
if: always()
run: docker-compose down -v
wdio-chrome:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: chmod
run: chmod -R 777 server/php/files wdio/reports
- name: docker-compose build
run: docker-compose build example
- name: wdio chrome
run: docker-compose run --rm wdio
- name: docker-compose logs
if: always()
run: docker-compose logs example
- name: docker-compose down
if: always()
run: docker-compose down -v
- name: Upload reports
if: always()
uses: actions/upload-artifact@master
with:
name: reports
path: wdio/reports
wdio-firefox:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: chmod
run: chmod -R 777 server/php/files wdio/reports
- name: docker-compose build
run: docker-compose build example
- name: wdio firefox
run: docker-compose run --rm wdio conf/firefox.js
- name: docker-compose logs
if: always()
run: docker-compose logs example
- name: docker-compose down
if: always()
run: docker-compose down -v
- name: Upload reports
if: always()
uses: actions/upload-artifact@master
with:
name: reports
path: wdio/reports

3
lib/jQuery-File-Upload/.gitignore vendored Executable file
View file

@ -0,0 +1,3 @@
*.pyc
.env
node_modules

View file

@ -0,0 +1,20 @@
MIT License
Copyright © 2010 Sebastian Tschan, https://blueimp.net
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.

225
lib/jQuery-File-Upload/README.md Executable file
View file

@ -0,0 +1,225 @@
# jQuery File Upload
## Contents
- [Description](#description)
- [Demo](#demo)
- [Features](#features)
- [Security](#security)
- [Setup](#setup)
- [Requirements](#requirements)
- [Mandatory requirements](#mandatory-requirements)
- [Optional requirements](#optional-requirements)
- [Cross-domain requirements](#cross-domain-requirements)
- [Browsers](#browsers)
- [Desktop browsers](#desktop-browsers)
- [Mobile browsers](#mobile-browsers)
- [Extended browser support information](#extended-browser-support-information)
- [Testing](#testing)
- [Support](#support)
- [License](#license)
## Description
> File Upload widget with multiple file selection, drag&amp;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.
## Demo
[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
## Features
- **Multiple file upload:**
Allows to select multiple files at once and upload them simultaneously.
- **Drag & Drop support:**
Allows to upload files by dragging them from your desktop or file manager and
dropping them on your browser window.
- **Upload progress bar:**
Shows a progress bar indicating the upload progress for individual files and
for all uploads combined.
- **Cancelable uploads:**
Individual file uploads can be canceled to stop the upload progress.
- **Resumable uploads:**
Aborted uploads can be resumed with browsers supporting the Blob API.
- **Chunked uploads:**
Large files can be uploaded in smaller chunks with browsers supporting the
Blob API.
- **Client-side image resizing:**
Images can be automatically resized on client-side with browsers supporting
the required JS APIs.
- **Preview images, audio and video:**
A preview of image, audio and video files can be displayed before uploading
with browsers supporting the required APIs.
- **No browser plugins (e.g. Adobe Flash) required:**
The implementation is based on open standards like HTML5 and JavaScript and
requires no additional browser plugins.
- **Graceful fallback for legacy browsers:**
Uploads files via XMLHttpRequests if supported and uses iframes as fallback
for legacy browsers.
- **HTML file upload form fallback:**
Allows progressive enhancement by using a standard HTML file upload form as
widget element.
- **Cross-site file uploads:**
Supports uploading files to a different domain with cross-site XMLHttpRequests
or iframe redirects.
- **Multiple plugin instances:**
Allows to use multiple plugin instances on the same webpage.
- **Customizable and extensible:**
Provides an API to set individual options and define callback methods for
various upload events.
- **Multipart and file contents stream uploads:**
Files can be uploaded as standard "multipart/form-data" or file contents
stream (HTTP PUT file upload).
- **Compatible with any server-side application platform:**
Works with any server-side platform (PHP, Python, Ruby on Rails, Java,
Node.js, Go etc.) that supports standard HTML form file uploads.
## Security
⚠️ Please read the [VULNERABILITIES](VULNERABILITIES.md) document for a list of
fixed vulnerabilities
Please also read the [SECURITY](SECURITY.md) document for instructions on how to
securely configure your Webserver for file uploads.
## Setup
jQuery File Upload can be installed via [NPM](https://www.npmjs.com/):
```sh
npm install blueimp-file-upload
```
This allows you to include [jquery.fileupload.js](js/jquery.fileupload.js) and
its extensions via `node_modules`, e.g:
```html
<script src="node_modules/blueimp-file-upload/js/jquery.fileupload.js"></script>
```
The widget can then be initialized on a file upload form the following way:
```js
$('#fileupload').fileupload();
```
For further information, please refer to the following guides:
- [Main documentation page](https://github.com/blueimp/jQuery-File-Upload/wiki)
- [List of all available Options](https://github.com/blueimp/jQuery-File-Upload/wiki/Options)
- [The plugin API](https://github.com/blueimp/jQuery-File-Upload/wiki/API)
- [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
- [How to use only the basic plugin.](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
## Requirements
### Mandatory requirements
- [jQuery](https://jquery.com/) v1.7+
- [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v1.9+
(included): Required for the basic File Upload plugin, but very lightweight
without any other dependencies from the jQuery UI suite.
- [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js)
(included): Required for
[browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
### Optional requirements
- [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates)
v3+: Used to render the selected and uploaded files for the Basic Plus UI and
jQuery UI versions.
- [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image)
v2+: Required for the image previews and resizing functionality.
- [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob)
v3+:Required for the image previews and resizing functionality.
- [blueimp Gallery](https://github.com/blueimp/Gallery) v2+: Used to display the
uploaded images in a lightbox.
- [Bootstrap](https://getbootstrap.com/) v3+: Used for the demo design.
- [Glyphicons](https://glyphicons.com/) Icon set used by Bootstrap.
### Cross-domain requirements
[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads)
using the
[Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js)
require a redirect back to the origin server to retrieve the upload results. The
[example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js)
makes use of
[result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html)
as a static redirect page for the origin server.
The repository also includes the
[jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js),
which enables limited cross-domain AJAX requests in Microsoft Internet Explorer
8 and 9 (IE 10 supports cross-domain XHR requests).
The XDomainRequest object allows GET and POST requests only and doesn't support
file uploads. It is used on the
[Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files
from the cross-domain demo file upload service.
## Browsers
### Desktop browsers
The File Upload plugin is regularly tested with the latest browser versions and
supports the following minimal versions:
- Google Chrome
- Apple Safari 4.0+
- Mozilla Firefox 3.0+
- Opera 11.0+
- Microsoft Internet Explorer 6.0+
### Mobile browsers
The File Upload plugin has been tested with and supports the following mobile
browsers:
- Apple Safari on iOS 6.0+
- Google Chrome on iOS 6.0+
- Google Chrome on Android 4.0+
- Default Browser on Android 2.3+
- Opera Mobile 12.0+
### Extended browser support information
For a detailed overview of the features supported by each browser version and
known operating system / browser bugs, please have a look at the
[Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
## Testing
The project comes with three sets of tests:
1. Code linting using [ESLint](https://eslint.org/).
2. Unit tests using [Mocha](https://mochajs.org/).
3. End-to-end tests using [blueimp/wdio](https://github.com/blueimp/wdio).
To run the tests, follow these steps:
1. Start [Docker](https://docs.docker.com/).
2. Install development dependencies:
```sh
npm install
```
3. Run the tests:
```sh
npm test
```
## Support
This project is actively maintained, but there is no official support channel.
If you have a question that another developer might help you with, please post
to
[Stack Overflow](https://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload)
and tag your question with `blueimp jquery file upload`.
## License
Released under the [MIT license](https://opensource.org/licenses/MIT).

View file

@ -0,0 +1,209 @@
# File Upload Security
## Contents
- [Introduction](#introduction)
- [Purpose of this project](#purpose-of-this-project)
- [Mitigations against file upload risks](#mitigations-against-file-upload-risks)
- [Prevent code execution on the server](#prevent-code-execution-on-the-server)
- [Prevent code execution in the browser](#prevent-code-execution-in-the-browser)
- [Prevent distribution of malware](#prevent-distribution-of-malware)
- [Secure file upload serving configurations](#secure-file-upload-serving-configurations)
- [Apache config](#apache-config)
- [NGINX config](#nginx-config)
- [Secure image processing configurations](#secure-image-processing-configurations)
- [ImageMagick config](#imagemagick-config)
## Introduction
For an in-depth understanding of the potential security risks of providing file
uploads and possible mitigations, please refer to the
[OWASP - Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload)
documentation.
To securely setup the project to serve uploaded files, please refer to the
sample
[Secure file upload serving configurations](#secure-file-upload-serving-configurations).
To mitigate potential vulnerabilities in image processing libraries, please
refer to the
[Secure image processing configurations](#secure-image-processing-configurations).
By default, all sample upload handlers allow only upload of image files, which
mitigates some attack vectors, but should not be relied on as the only
protection.
Please also have a look at the
[list of fixed vulnerabilities](VULNERABILITIES.md) in jQuery File Upload, which
relates mostly to the sample server-side upload handlers and how they have been
configured.
## Purpose of this project
Please note that this project is not a complete file management product, but
foremost a client-side file upload library for [jQuery](https://jquery.com/).
The server-side sample upload handlers are just examples to demonstrate the
client-side file upload functionality.
To make this very clear, there is **no user authentication** by default:
- **everyone can upload files**
- **everyone can delete uploaded files**
In some cases this can be acceptable, but for most projects you will want to
extend the sample upload handlers to integrate user authentication, or implement
your own.
It is also up to you to configure your Webserver to securely serve the uploaded
files, e.g. using the
[sample server configurations](#secure-file-upload-serving-configurations).
## Mitigations against file upload risks
### Prevent code execution on the server
To prevent execution of scripts or binaries on server-side, the upload directory
must be configured to not execute files in the upload directory (e.g.
`server/php/files` as the default for the PHP upload handler) and only treat
uploaded files as static content.
The recommended way to do this is to configure the upload directory path to
point outside of the web application root.
Then the Webserver can be configured to serve files from the upload directory
with their default static files handler only.
Limiting file uploads to a whitelist of safe file types (e.g. image files) also
mitigates this issue, but should not be the only protection.
### Prevent code execution in the browser
To prevent execution of scripts on client-side, the following headers must be
sent when delivering generic uploaded files to the client:
```
Content-Type: application/octet-stream
X-Content-Type-Options: nosniff
```
The `Content-Type: application/octet-stream` header instructs browsers to
display a download dialog instead of parsing it and possibly executing script
content e.g. in HTML files.
The `X-Content-Type-Options: nosniff` header prevents browsers to try to detect
the file mime type despite the given content-type header.
For known safe files, the content-type header can be adjusted using a
**whitelist**, e.g. sending `Content-Type: image/png` for PNG files.
### Prevent distribution of malware
To prevent attackers from uploading and distributing malware (e.g. computer
viruses), it is recommended to limit file uploads only to a whitelist of safe
file types.
Please note that the detection of file types in the sample file upload handlers
is based on the file extension and not the actual file content. This makes it
still possible for attackers to upload malware by giving their files an image
file extension, but should prevent automatic execution on client computers when
opening those files.
It does not protect at all from exploiting vulnerabilities in image display
programs, nor from users renaming file extensions to inadvertently execute the
contained malicious code.
## Secure file upload serving configurations
The following configurations serve uploaded files as static files with the
proper headers as
[mitigation against file upload risks](#mitigations-against-file-upload-risks).
Please do not simply copy&paste these configurations, but make sure you
understand what they are doing and that you have implemented them correctly.
> Always test your own setup and make sure that it is secure!
e.g. try uploading PHP scripts (as "example.php", "example.php.png" and
"example.png") to see if they get executed by your Webserver.
### Apache config
Add the following directive to the Apache config, replacing the directory path
with the absolute path to the upload directory:
```ApacheConf
<Directory "/path/to/project/server/php/files">
# 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:
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
ForceType none
Header unset Content-Disposition
</FilesMatch>
# 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
</Directory>
```
### NGINX config
Add the following directive to the NGINX config, replacing the directory path
with the absolute path to the upload directory:
```Nginx
location ^~ /path/to/project/server/php/files {
root html;
default_type application/octet-stream;
types {
image/gif gif;
image/jpeg jpg;
image/png png;
}
add_header X-Content-Type-Options 'nosniff';
if ($request_filename ~ /(((?!\.(jpg)|(png)|(gif)$)[^/])+$)) {
add_header Content-Disposition 'attachment; filename="$1"';
# Add X-Content-Type-Options again, as using add_header in a new context
# dismisses all previous add_header calls:
add_header X-Content-Type-Options 'nosniff';
}
}
```
## Secure image processing configurations
The following configuration mitigates
[potential image processing vulnerabilities with ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick)
by limiting the attack vectors to a small subset of image types
(`GIF/JPEG/PNG`).
Please also consider using alternative, safer image processing libraries like
[libvips](https://github.com/libvips/libvips) or
[imageflow](https://github.com/imazen/imageflow).
## ImageMagick config
It is recommended to disable all non-required ImageMagick coders via
[policy.xml](https://wiki.debian.org/imagemagick/security).
To do so, locate the ImageMagick `policy.xml` configuration file and add the
following policies:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- ... -->
<policymap>
<!-- ... -->
<policy domain="delegate" rights="none" pattern="*" />
<policy domain="coder" rights="none" pattern="*" />
<policy domain="coder" rights="read | write" pattern="{GIF,JPEG,JPG,PNG}" />
</policymap>
```

View file

@ -0,0 +1,118 @@
# List of fixed vulnerabilities
## Contents
- [Potential vulnerabilities with PHP+ImageMagick](#potential-vulnerabilities-with-phpimagemagick)
- [Remote code execution vulnerability in the PHP component](#remote-code-execution-vulnerability-in-the-php-component)
- [Open redirect vulnerability in the GAE components](#open-redirect-vulnerability-in-the-gae-components)
- [Cross-site scripting vulnerability in the Iframe Transport](#cross-site-scripting-vulnerability-in-the-iframe-transport)
## Potential vulnerabilities with PHP+ImageMagick
> Mitigated: 2018-10-25 (GMT)
The sample [PHP upload handler](server/php/UploadHandler.php) before
[v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1)
did not validate file signatures before invoking
[ImageMagick](https://www.imagemagick.org/) (via
[Imagick](https://php.net/manual/en/book.imagick.php)).
Verifying those
[magic bytes](https://en.wikipedia.org/wiki/List_of_file_signatures) mitigates
potential vulnerabilities when handling input files other than `GIF/JPEG/PNG`.
Please also configure ImageMagick to only enable the coders required for
`GIF/JPEG/PNG` processing, e.g. with the sample
[ImageMagick config](SECURITY.md#imagemagick-config).
**Further information:**
- Commit containing the mitigation:
[fe44d34](https://github.com/blueimp/jQuery-File-Upload/commit/fe44d34be43be32c6b8d507932f318dababb25dd)
- [ImageTragick](https://imagetragick.com/)
- [CERT Vulnerability Note VU#332928](https://www.kb.cert.org/vuls/id/332928)
- [ImageMagick CVE entries](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=imagemagick)
## Remote code execution vulnerability in the PHP component
> Fixed: 2018-10-23 (GMT)
The sample [PHP upload handler](server/php/UploadHandler.php) before
[v9.24.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.24.1)
allowed to upload all file types by default.
This opens up a remote code execution vulnerability, unless the server is
configured to not execute (PHP) files in the upload directory
(`server/php/files`).
The provided [.htaccess](server/php/files/.htaccess) file includes instructions
for Apache to disable script execution, however
[.htaccess support](https://httpd.apache.org/docs/current/howto/htaccess.html)
is disabled by default since Apache `v2.3.9` via
[AllowOverride Directive](https://httpd.apache.org/docs/current/mod/core.html#allowoverride).
**You are affected if you:**
1. A) Uploaded jQuery File Upload < `v9.24.1` on a Webserver that executes files
with `.php` as part of the file extension (e.g. "example.php.png"), e.g.
Apache with `mod_php` enabled and the following directive (_not a recommended
configuration_):
```ApacheConf
AddHandler php5-script .php
```
B) Uploaded jQuery File Upload < `v9.22.1` on a Webserver that executes files
with the file extension `.php`, e.g. Apache with `mod_php` enabled and the
following directive:
```ApacheConf
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
```
2. Did not actively configure your Webserver to not execute files in the upload
directory (`server/php/files`).
3. Are running Apache `v2.3.9+` with the default `AllowOverride` Directive set
to `None` or another Webserver with no `.htaccess` support.
**How to fix it:**
1. Upgrade to the latest version of jQuery File Upload.
2. Configure your Webserver to not execute files in the upload directory, e.g.
with the [sample Apache configuration](SECURITY.md#apache-config)
**Further information:**
- Commits containing the security fix:
[aeb47e5](https://github.com/blueimp/jQuery-File-Upload/commit/aeb47e51c67df8a504b7726595576c1c66b5dc2f),
[ad4aefd](https://github.com/blueimp/jQuery-File-Upload/commit/ad4aefd96e4056deab6fea2690f0d8cf56bb2d7d)
- [Full disclosure post on Hacker News](https://news.ycombinator.com/item?id=18267309).
- [CVE-2018-9206](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9206)
- [OWASP - Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload)
## Open redirect vulnerability in the GAE components
> Fixed: 2015-06-12 (GMT)
The sample Google App Engine upload handlers before
v[9.10.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/9.10.1)
accepted any URL as redirect target, making it possible to use the Webserver's
domain for phishing attacks.
**Further information:**
- Commit containing the security fix:
[f74d2a8](https://github.com/blueimp/jQuery-File-Upload/commit/f74d2a8c3e3b1e8e336678d2899facd5bcdb589f)
- [OWASP - Unvalidated Redirects and Forwards Cheat Sheet](https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet)
## Cross-site scripting vulnerability in the Iframe Transport
> Fixed: 2012-08-09 (GMT)
The [redirect page](cors/result.html) for the
[Iframe Transport](js/jquery.iframe-transport.js) before commit
[4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a)
(_fixed in all tagged releases_) allowed executing arbitrary JavaScript in the
context of the Webserver.
**Further information:**
- Commit containing the security fix:
[4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a)
- [OWASP - Cross-site Scripting (XSS)](<https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)>)

View file

@ -0,0 +1,85 @@
<!DOCTYPE html>
<!--
/*
* jQuery File Upload Plugin postMessage API
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery File Upload Plugin postMessage API</title>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f"
crossorigin="anonymous"
></script>
</head>
<body>
<script>
'use strict';
var origin = /^https:\/\/example.org/,
target = new RegExp('^(http(s)?:)?\\/\\/' + location.host + '\\/');
$(window).on('message', function (e) {
e = e.originalEvent;
var s = e.data,
xhr = $.ajaxSettings.xhr(),
f;
if (!origin.test(e.origin)) {
throw new Error('Origin "' + e.origin + '" does not match ' + origin);
}
if (!target.test(e.data.url)) {
throw new Error(
'Target "' + e.data.url + '" does not match ' + target
);
}
$(xhr.upload).on('progress', function (ev) {
ev = ev.originalEvent;
e.source.postMessage(
{
id: s.id,
type: ev.type,
timeStamp: ev.timeStamp,
lengthComputable: ev.lengthComputable,
loaded: ev.loaded,
total: ev.total
},
e.origin
);
});
s.xhr = function () {
return xhr;
};
if (!(s.data instanceof Blob)) {
f = new FormData();
$.each(s.data, function (i, v) {
f.append(v.name, v.value);
});
s.data = f;
}
$.ajax(s).always(function (result, statusText, jqXHR) {
if (!jqXHR.done) {
jqXHR = result;
result = null;
}
e.source.postMessage(
{
id: s.id,
status: jqXHR.status,
statusText: statusText,
result: result,
headers: jqXHR.getAllResponseHeaders()
},
e.origin
);
});
});
</script>
</body>
</html>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<!--
/*
* jQuery Iframe Transport Plugin Redirect Page
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
-->
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery Iframe Transport Plugin Redirect Page</title>
</head>
<body>
<script>
document.body.innerText = document.body.textContent = decodeURIComponent(
window.location.search.slice(1)
);
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
@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;
}

View file

@ -0,0 +1,17 @@
@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;
}

View file

@ -0,0 +1,61 @@
@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
*/
.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;
}
.toggle[type='checkbox'] {
transform: scale(2);
margin-left: 10px;
}
@media (max-width: 767px) {
.fileupload-buttonbar .btn {
margin-bottom: 5px;
}
.fileupload-buttonbar .delete,
.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%;
}
}

View file

@ -0,0 +1,37 @@
@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%;
}
}

View file

@ -0,0 +1,59 @@
version: '3.7'
services:
example:
build: server/php
ports:
- 127.0.0.1:80:80
- ${SERVER_HOST:-127.0.0.1}:${SERVER_PORT-}:80
volumes:
- .:/var/www/html
mocha:
image: blueimp/mocha-chrome
command: http://example/test
environment:
- WAIT_FOR_HOSTS=example:80
depends_on:
- example
chromedriver:
image: blueimp/chromedriver
init: true
tmpfs: /tmp
environment:
- DISABLE_X11=false
- ENABLE_VNC=true
- EXPOSE_X11=true
volumes:
- ./wdio/assets:/home/webdriver/assets:ro
ports:
- 127.0.0.1:5900:5900
geckodriver:
image: blueimp/geckodriver
init: true
tmpfs: /tmp
shm_size: 2g
environment:
- DISABLE_X11=false
- ENABLE_VNC=true
- EXPOSE_X11=true
volumes:
- ./wdio/assets:/home/webdriver/assets:ro
ports:
- 127.0.0.1:5901:5900
wdio:
image: blueimp/wdio
init: true
read_only: true
tmpfs:
- /tmp
environment:
- WAIT_FOR_HOSTS= chromedriver:4444 geckodriver:4444 example:80
- WINDOWS_HOST
- MACOS_ASSETS_DIR=$PWD/wdio/assets/
- WINDOWS_ASSETS_DIR
volumes:
- ./wdio:/opt:ro
- ./wdio/reports:/opt/reports
depends_on:
- chromedriver
- geckodriver
- example

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

283
lib/jQuery-File-Upload/index.html Executable file
View file

@ -0,0 +1,283 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery File Upload Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Generic page styles -->
<style>
#navigation {
margin: 10px 0;
}
@media (max-width: 767px) {
#title,
#description {
display: none;
}
}
</style>
<!-- blueimp Gallery styles -->
<link
rel="stylesheet"
href="https://blueimp.github.io/Gallery/css/blueimp-gallery.min.css"
/>
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
<link rel="stylesheet" href="css/jquery.fileupload.css" />
<link rel="stylesheet" href="css/jquery.fileupload-ui.css" />
<!-- CSS adjustments for browsers with JavaScript disabled -->
<noscript
><link rel="stylesheet" href="css/jquery.fileupload-noscript.css"
/></noscript>
<noscript
><link rel="stylesheet" href="css/jquery.fileupload-ui-noscript.css"
/></noscript>
</head>
<body>
<div class="container">
<!-- The file upload form used as target for the file upload widget -->
<form
id="fileupload"
action=""
method="POST"
enctype="multipart/form-data"
>
<!-- Redirect browsers with JavaScript disabled to the origin page -->
<noscript
><input
type="hidden"
name="redirect"
value="https://blueimp.github.io/jQuery-File-Upload/"
/></noscript>
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple />
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete selected</span>
</button>
<input type="checkbox" class="toggle" />
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="col-lg-5 fileupload-progress fade">
<!-- The global progress bar -->
<div
class="progress progress-striped active"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar progress-bar-success"
style="width: 0%;"
></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended">&nbsp;</div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped">
<tbody class="files"></tbody>
</table>
</form>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Demo Notes</h3>
</div>
<div class="panel-body">
<ul>
<li>
The maximum file size for uploads in this demo is
<strong>999 KB</strong> (default file size is unlimited).
</li>
<li>
Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in
this demo (by default there is no file type restriction).
</li>
<li>
Uploaded files will be deleted automatically after
<strong>5 minutes or less</strong> (demo files are stored in
memory).
</li>
<li>
You can <strong>drag &amp; drop</strong> files from your desktop
on this webpage (see
<a
href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support"
>Browser support</a
>).
</li>
<li>
Please refer to the
<a href="https://github.com/blueimp/jQuery-File-Upload"
>project website</a
>
and
<a href="https://github.com/blueimp/jQuery-File-Upload/wiki"
>documentation</a
>
for more information.
</li>
<li>
Built with the
<a href="https://getbootstrap.com/">Bootstrap</a> CSS framework
and Icons from <a href="https://glyphicons.com/">Glyphicons</a>.
</li>
</ul>
</div>
</div>
</div>
<!-- The blueimp Gallery widget -->
<div
id="blueimp-gallery"
class="blueimp-gallery blueimp-gallery-controls"
data-filter=":even"
>
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev"></a>
<a class="next"></a>
<a class="close">×</a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
{% if (window.innerWidth > 480 || !o.options.loadImageFileTypes.test(file.type)) { %}
<p class="name">{%=file.name%}</p>
{% } %}
<strong class="error text-danger"></strong>
</td>
<td>
<p class="size">Processing...</p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
</td>
<td>
{% if (!o.options.autoUpload && o.options.edit && o.options.loadImageFileTypes.test(file.type)) { %}
<button class="btn btn-success edit" data-index="{%=i%}" disabled>
<i class="glyphicon glyphicon-edit"></i>
<span>Edit</span>
</button>
{% } %}
{% if (!i && !o.options.autoUpload) { %}
<button class="btn btn-primary start" disabled>
<i class="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
{% } %}
{% if (!i) { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td>
<span class="preview">
{% if (file.thumbnailUrl) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
{% } %}
</span>
</td>
<td>
{% if (window.innerWidth > 480 || !file.thumbnailUrl) { %}
<p class="name">
{% if (file.url) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
{% } else { %}
<span>{%=file.name%}</span>
{% } %}
</p>
{% } %}
{% if (file.error) { %}
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
{% if (file.deleteUrl) { %}
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" name="delete" value="1" class="toggle">
{% } else { %}
<button class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"
integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh"
crossorigin="anonymous"
></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<!-- blueimp Gallery script -->
<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script src="js/jquery.fileupload.js"></script>
<!-- The File Upload processing plugin -->
<script src="js/jquery.fileupload-process.js"></script>
<!-- The File Upload image preview & resize plugin -->
<script src="js/jquery.fileupload-image.js"></script>
<!-- The File Upload audio preview plugin -->
<script src="js/jquery.fileupload-audio.js"></script>
<!-- The File Upload video preview plugin -->
<script src="js/jquery.fileupload-video.js"></script>
<!-- The File Upload validation plugin -->
<script src="js/jquery.fileupload-validate.js"></script>
<!-- The File Upload user interface plugin -->
<script src="js/jquery.fileupload-ui.js"></script>
<!-- The main application script -->
<script src="js/demo.js"></script>
<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
<!--[if (gte IE 8)&(lt IE 10)]>
<script src="js/cors/jquery.xdr-transport.js"></script>
<![endif]-->
</body>
</html>

View file

@ -0,0 +1,126 @@
/*
* 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 */
(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 = $('<a>').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 = $(
'<iframe style="display:none;" src="' +
options.postMessage +
'" name="' +
message.id +
'"></iframe>'
)
.on('load', function () {
$.each(names, function (i, name) {
message[name] = options[name];
});
message.dataType = message.dataType.replace('postmessage ', '');
$(window).on(eventName, function (event) {
var e = event.originalEvent;
var data = e.data;
var 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).off(eventName);
}
}
});
iframe[0].contentWindow.postMessage(message, target);
})
.appendTo(document.body);
},
abort: function () {
if (iframe) {
iframe.remove();
}
}
};
}
});
});

View file

@ -0,0 +1,97 @@
/*
* 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, 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) ? '&' : '?';
/**
* Callback wrapper function
*
* @param {number} status HTTP status code
* @param {string} statusText HTTP status text
* @param {object} [responses] Content-type specific responses
* @param {string} [responseHeaders] Response headers string
*/
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();
}
}
};
}
});
}
});

View file

@ -0,0 +1,87 @@
/*
* jQuery File Upload Demo
* 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 $ */
$(function () {
'use strict';
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: 'lib/jQuery-File-Upload-master/server/php/'
});
// Enable iframe cross-domain access via redirect option:
$('#fileupload').fileupload(
'option',
'redirect',
window.location.href.replace(/\/[^/]*$/, 'lib/jQuery-File-Upload-master//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 () {
$('<div class="alert alert-danger"/>')
.text('Upload server currently unavailable - ' + new Date())
.appendTo('#fileupload');
});
}
} else {
$('#fileupload').fileupload('option', {
// 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
),
imageMaxWidth: 100,
imageMaxHeight: 100,
maxFileSize: 9999999,
acceptFileTypes: /(\.|\/)(txt|gif|jpe?g|png)$/i
});
// 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')
// eslint-disable-next-line new-cap
.call(this, $.Event('done'), { result: result });
});
}
});

View file

@ -0,0 +1,101 @@
/*
* 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
*/
/* global define, require */
(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;
}
}
});
});

View file

@ -0,0 +1,351 @@
/*
* 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
*/
/* global define, require */
(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',
maxMetaDataSize: '@',
disableImageHead: '@',
disableMetaDataParsers: '@',
disableExif: '@',
disableExifThumbnail: '@',
disableExifOffsets: '@',
includeExifTags: '@',
excludeExifTags: '@',
disableIptc: '@',
disableIptcOffsets: '@',
includeIptcTags: '@',
excludeIptcTags: '@',
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: true,
// 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],
// eslint-disable-next-line new-cap
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;
}
// eslint-disable-next-line no-param-reassign
options = $.extend({ canvas: true }, options);
var that = this,
// eslint-disable-next-line new-cap
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 browser oriented images:
if (loadImage.orientation) {
data.orientation = data.orientation || options.orientation;
}
// 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],
// eslint-disable-next-line new-cap
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,
// eslint-disable-next-line new-cap
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 that = this,
file = data.files[data.index],
// eslint-disable-next-line new-cap
dfd = $.Deferred();
if (data.orientation && data.exifOffsets) {
// Reset Exif Orientation data:
loadImage.writeExifData(data.imageHead, data, 'Orientation', 1);
}
loadImage.replaceHead(file, data.imageHead, function (blob) {
blob.name = file.name;
data.files[data.index] = blob;
dfd.resolveWith(that, [data]);
});
return dfd.promise();
},
// 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;
}
}
});
});

View file

@ -0,0 +1,169 @@
/*
* 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
*/
/* global define, require */
(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,
// eslint-disable-next-line new-cap
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) {
// eslint-disable-next-line new-cap
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) {
// eslint-disable-next-line new-cap
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;
// eslint-disable-next-line new-cap
this._processingQueue = $.Deferred().resolveWith(this).promise();
}
});
});

View file

@ -0,0 +1,759 @@
/*
* 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
*/
/* global define, require */
(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 class to show/hide UI elements:
showElementClass: 'in',
// 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('.edit,.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('&nbsp;');
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) {
// eslint-disable-next-line new-cap
var promise = deferred || $.Deferred();
this._finishedUploads.push(promise);
return promise;
},
_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.on('dragstart', function (e) {
try {
e.originalEvent.dataTransfer.setData(
'DownloadURL',
[type, name, url].join(':')
);
} catch (ignore) {
// Ignore exceptions
}
});
},
_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).empty().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();
},
_editHandler: function (e) {
e.preventDefault();
if (!this.options.edit) return;
var that = this,
button = $(e.currentTarget),
template = button.closest('.template-upload'),
data = template.data('data'),
index = button.data().index;
this.options.edit(data.files[index]).then(function (file) {
if (!file) return;
data.files[index] = file;
data.context.addClass('processing');
template.find('.edit,.start').prop('disabled', true);
$(that.element)
.fileupload('process', data)
.always(function () {
template
.find('.size')
.text(that._formatFileSize(data.files[index].size));
data.context.removeClass('processing');
that._renderPreviews(data);
})
.done(function () {
template.find('.edit,.start').prop('disabled', false);
})
.fail(function () {
template.find('.edit').prop('disabled', false);
var error = data.files[index].error;
if (error) {
template.find('.error').text(error);
}
});
});
},
_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) {
// eslint-disable-next-line new-cap
var dfd = $.Deferred();
if (
$.support.transition &&
node.hasClass('fade') &&
node.is(':visible')
) {
var transitionEndHandler = function (e) {
// Make sure we don't respond to other transition events
// in the container element, e.g. from button elements:
if (e.target === node[0]) {
node.off($.support.transition.end, transitionEndHandler);
dfd.resolveWith(node);
}
};
node
.on($.support.transition.end, transitionEndHandler)
.toggleClass(this.options.showElementClass);
} else {
node.toggleClass(this.options.showElementClass);
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 .edit': this._editHandler,
'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();
}
});
});

View file

@ -0,0 +1,119 @@
/*
* 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 */
(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;
}
// eslint-disable-next-line new-cap
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();
}
}
});
});

View file

@ -0,0 +1,101 @@
/*
* 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
*/
/* global define, require */
(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;
}
}
});
});

1597
lib/jQuery-File-Upload/js/jquery.fileupload.js vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,221 @@
/*
* 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 */
(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:
// eslint-disable-next-line no-script-url
var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
form,
iframe,
addParamChar;
return {
send: function (_, completeCallback) {
form = $('<form style="display:none;"></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 = $(
'<iframe src="' +
initialIframeSrc +
'" name="iframe-transport-' +
counter +
'"></iframe>'
).on('load', function () {
var fileInputClones,
paramNames = $.isArray(options.paramName)
? options.paramName
: [options.paramName];
iframe.off('load').on('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):
$('<iframe src="' + initialIframeSrc + '"></iframe>').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) {
$('<input type="hidden"/>')
.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.
iframe.off('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());
}
}
});
});

View file

@ -0,0 +1,808 @@
/*! jQuery UI - v1.12.1+0b7246b6eeadfa9e2696e22f3230f6452f8129dc - 2020-02-20
* http://jqueryui.com
* Includes: widget.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */
/* global define, require */
/* eslint-disable no-param-reassign, new-cap, jsdoc/require-jsdoc */
(function (factory) {
'use strict';
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(window.jQuery);
}
})(function ($) {
('use strict');
$.ui = $.ui || {};
$.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/
// Support: jQuery 1.9.x or older
// $.expr[ ":" ] is deprecated.
if (!$.expr.pseudos) {
$.expr.pseudos = $.expr[':'];
}
// Support: jQuery 1.11.x or older
// $.unique has been renamed to $.uniqueSort
if (!$.uniqueSort) {
$.uniqueSort = $.unique;
}
var widgetUuid = 0;
var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
var widgetSlice = Array.prototype.slice;
$.cleanData = (function (orig) {
return function (elems) {
var events, elem, i;
// eslint-disable-next-line eqeqeq
for (i = 0; (elem = elems[i]) != null; i++) {
// Only trigger remove when necessary to save time
events = $._data(elem, 'events');
if (events && events.remove) {
$(elem).triggerHandler('remove');
}
}
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.pseudos[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 (
widgetHasOwnProperty.call(input[inputIndex], 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: '<div>',
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 bindRemoveEvent() {
options.element.each(function (_, element) {
var isTracked = $.map(that.classesElementLookup, function (elements) {
return elements;
}).some(function (elements) {
return elements.is(element);
});
if (!isTracked) {
that._on($(element), {
remove: '_untrackClassesElement'
});
}
});
}
function processClassString(classes, checkOption) {
var current, i;
for (i = 0; i < classes.length; i++) {
current = that.classesElementLookup[classes[i]] || $();
if (options.add) {
bindRemoveEvent();
current = $(
$.uniqueSort(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]]);
}
}
}
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());
}
});
this._off($(event.target));
},
_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);
// 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) {
var instance = this;
function handlerProxy() {
return (typeof handler === 'string'
? instance[handler]
: handler
).apply(instance, arguments);
}
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();
});
}
};
});
});

3149
lib/jQuery-File-Upload/package-lock.json generated Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,116 @@
{
"name": "blueimp-file-upload",
"version": "10.13.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",
"peerDependencies": {
"jquery": ">=1.7"
},
"optionalDependencies": {
"blueimp-canvas-to-blob": "3",
"blueimp-load-image": "3",
"blueimp-tmpl": "3"
},
"devDependencies": {
"eslint": "6",
"eslint-config-blueimp": "1",
"eslint-config-prettier": "6",
"eslint-plugin-jsdoc": "22",
"eslint-plugin-prettier": "3",
"prettier": "2",
"stylelint": "13",
"stylelint-config-prettier": "8",
"stylelint-config-recommended": "3"
},
"stylelint": {
"extends": [
"stylelint-config-recommended",
"stylelint-config-prettier"
],
"ignoreFiles": [
"css/*.min.css",
"css/vendor/*",
"test/vendor/*"
]
},
"eslintConfig": {
"extends": [
"blueimp",
"plugin:jsdoc/recommended",
"plugin:prettier/recommended"
],
"env": {
"browser": true
}
},
"eslintIgnore": [
"js/*.min.js",
"test/vendor"
],
"prettier": {
"arrowParens": "avoid",
"proseWrap": "always",
"singleQuote": true,
"trailingComma": "none"
},
"scripts": {
"lint": "stylelint '**/*.css' && eslint .",
"unit": "docker-compose run --rm mocha",
"wdio": "docker-compose run --rm wdio",
"test": "npm run lint && npm run unit && npm run wdio && npm run wdio -- conf/firefox.js",
"posttest": "docker-compose down -v",
"preversion": "npm test",
"postversion": "git push --tags origin master && npm publish"
},
"files": [
"css/jquery.fileupload-noscript.css",
"css/jquery.fileupload-ui-noscript.css",
"css/jquery.fileupload-ui.css",
"css/jquery.fileupload.css",
"img/loading.gif",
"img/progressbar.gif",
"js/cors/jquery.postmessage-transport.js",
"js/cors/jquery.xdr-transport.js",
"js/vendor/jquery.ui.widget.js",
"js/jquery.fileupload-audio.js",
"js/jquery.fileupload-image.js",
"js/jquery.fileupload-process.js",
"js/jquery.fileupload-ui.js",
"js/jquery.fileupload-validate.js",
"js/jquery.fileupload-video.js",
"js/jquery.fileupload.js",
"js/jquery.iframe-transport.js"
],
"main": "js/jquery.fileupload.js"
}

View file

@ -0,0 +1 @@
{"files":[{"name":"24022018-DSC03137 (1).JPG","size":315424,"url":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/files\/24022018-DSC03137%20%281%29.JPG","deleteUrl":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/index.php?file=24022018-DSC03137%20%281%29.JPG&_method=DELETE","deleteType":"POST"},{"name":"24022018-DSC03137 (2).JPG","size":315424,"url":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/files\/24022018-DSC03137%20%282%29.JPG","deleteUrl":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/index.php?file=24022018-DSC03137%20%282%29.JPG&_method=DELETE","deleteType":"POST"},{"name":"24022018-DSC03137.JPG","size":315424,"url":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/files\/24022018-DSC03137.JPG","deleteUrl":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/index.php?file=24022018-DSC03137.JPG&_method=DELETE","deleteType":"POST"},{"name":"S\u00e9lection_001 (1).png","size":164055,"url":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/files\/S%C3%A9lection_001%20%281%29.png","deleteUrl":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/index.php?file=S%C3%A9lection_001%20%281%29.png&_method=DELETE","deleteType":"POST"},{"name":"S\u00e9lection_001.png","size":164055,"url":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/files\/S%C3%A9lection_001.png","deleteUrl":"https:\/\/dl.zici.fr\/dev\/lib\/jQuery-File-Upload-master\/server\/php\/index.php?file=S%C3%A9lection_001.png&_method=DELETE","deleteType":"POST"}]}

View file

@ -0,0 +1,38 @@
FROM php:7.4-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=/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/*

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
*
!.gitignore
!.htaccess

View file

@ -0,0 +1,26 @@
# 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:
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
ForceType none
Header unset Content-Disposition
</FilesMatch>
# 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

View file

@ -0,0 +1,15 @@
<?php
/*
* jQuery File Upload Plugin PHP 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
*/
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
$upload_handler = new UploadHandler();

View file

@ -0,0 +1,49 @@
<!DOCTYPE html>
<!--
/*
* jQuery File Upload 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
*/
-->
<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery File Upload Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="vendor/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="vendor/mocha.js"></script>
<script src="vendor/chai.js"></script>
<script>
mocha.setup('bdd');
</script>
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"
integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ"
crossorigin="anonymous"
></script>
<script src="../js/vendor/jquery.ui.widget.js"></script>
<script src="../js/jquery.iframe-transport.js"></script>
<script src="../js/jquery.fileupload.js"></script>
<script src="../js/jquery.fileupload-process.js"></script>
<script src="../js/jquery.fileupload-image.js"></script>
<script src="../js/jquery.fileupload-audio.js"></script>
<script src="../js/jquery.fileupload-video.js"></script>
<script src="../js/jquery.fileupload-validate.js"></script>
<script src="unit.js"></script>
<script>
mocha.checkLeaks();
mocha.run();
</script>
</body>
</html>

View file

@ -0,0 +1,989 @@
/*
* jQuery File Upload Test
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
/* global beforeEach, afterEach, describe, it */
/* eslint-disable new-cap */
(function (expect, $) {
'use strict';
var canCreateBlob = !!window.dataURLtoBlob;
// 80x60px GIF image (color black, base64 data):
var b64DataGIF =
'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
'OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofE' +
'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7';
var imageUrlGIF = 'data:image/gif;base64,' + b64DataGIF;
var blobGIF = canCreateBlob && window.dataURLtoBlob(imageUrlGIF);
// 2x1px JPEG (color white, with the Exif orientation flag set to 6 and the
// IPTC ObjectName (2:5) set to 'objectname'):
var b64DataJPEG =
'/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAA' +
'BgASAAAAAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAA8cAgUACm9iamVj' +
'dG5hbWUA/9sAQwABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB' +
'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/9sAQwEBAQEBAQEBAQEBAQEBAQEB' +
'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB' +
'/8AAEQgAAQACAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH' +
'CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGh' +
'CCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldY' +
'WVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1' +
'tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8B' +
'AAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAEC' +
'dwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBka' +
'JicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWG' +
'h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ' +
'2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A/v4ooooA/9k=';
var imageUrlJPEG = 'data:image/jpeg;base64,' + b64DataJPEG;
var blobJPEG = canCreateBlob && window.dataURLtoBlob(imageUrlJPEG);
var fileGIF, fileJPEG, files, items, eventObject;
var uploadURL = '../server/php/';
/**
* Creates a fileupload form and adds it to the DOM
*
* @returns {object} jQuery node
*/
function createFileuploadForm() {
return $('<form><input type="file" name="files[]" multiple></form>')
.prop({
action: uploadURL,
method: 'POST',
enctype: 'multipart/form-data'
})
.css({ display: 'none' })
.appendTo(document.body);
}
/**
* Deletes all files from the upload server
*
* @param {Array} files Response files list
* @param {Function} callback Callback function
*/
function deleteFiles(files, callback) {
$.when(
files.map(function (file) {
return $.ajax({
type: file.deleteType,
url: file.deleteUrl
});
})
).always(function () {
callback();
});
}
beforeEach(function () {
fileGIF = new File([blobGIF], 'example.gif', { type: 'image/gif' });
fileJPEG = new File([blobJPEG], 'example.jpg', { type: 'image/jpeg' });
files = [fileGIF, fileJPEG];
items = [
{
getAsFile: function () {
return files[0];
}
},
{
getAsFile: function () {
return files[1];
}
}
];
eventObject = {
originalEvent: {
dataTransfer: { files: files, types: ['Files'] },
clipboardData: { items: items }
}
};
});
afterEach(function (done) {
$.getJSON(uploadURL).then(function (result) {
deleteFiles(result.files, done);
});
});
describe('Initialization', function () {
var form;
beforeEach(function () {
form = createFileuploadForm();
});
afterEach(function () {
form.remove();
});
it('widget', function () {
form.fileupload();
expect(form.data('blueimp-fileupload')).to.be.an('object');
});
it('file input', function () {
form.fileupload();
expect(form.fileupload('option', 'fileInput').length).to.equal(1);
});
it('drop zone', function () {
form.fileupload();
expect(form.fileupload('option', 'dropZone').length).to.equal(1);
});
it('paste zone', function () {
form.fileupload({ pasteZone: document });
expect(form.fileupload('option', 'pasteZone').length).to.equal(1);
});
it('data attributes', function () {
form.attr('data-url', 'https://example.org');
form.fileupload();
expect(form.fileupload('option', 'url')).to.equal('https://example.org');
expect(form.data('blueimp-fileupload')).to.be.an('object');
});
it('event listeners', function () {
var eventsData = {};
form.fileupload({
autoUpload: false,
pasteZone: document,
dragover: function () {
eventsData.dragover = true;
},
dragenter: function () {
eventsData.dragenter = true;
},
dragleave: function () {
eventsData.dragleave = true;
},
drop: function (e, data) {
eventsData.drop = data;
},
paste: function (e, data) {
eventsData.paste = data;
},
change: function () {
eventsData.change = true;
}
});
form
.fileupload('option', 'fileInput')
.trigger($.Event('change', eventObject));
expect(eventsData.change).to.equal(true);
form
.fileupload('option', 'dropZone')
.trigger($.Event('dragover', eventObject))
.trigger($.Event('dragenter', eventObject))
.trigger($.Event('dragleave', eventObject))
.trigger($.Event('drop', eventObject));
expect(eventsData.dragover).to.equal(true);
expect(eventsData.dragenter).to.equal(true);
expect(eventsData.dragleave).to.equal(true);
expect(eventsData.drop.files).to.deep.equal(files);
form
.fileupload('option', 'pasteZone')
.trigger($.Event('paste', eventObject));
expect(eventsData.paste.files).to.deep.equal(files);
});
});
describe('API', function () {
var form;
beforeEach(function () {
form = createFileuploadForm().fileupload({
dataType: 'json',
autoUpload: false
});
});
afterEach(function () {
form.remove();
});
it('destroy', function () {
var eventsData = {};
form.fileupload('option', {
pasteZone: document,
dragover: function () {
eventsData.dragover = true;
},
dragenter: function () {
eventsData.dragenter = true;
},
dragleave: function () {
eventsData.dragleave = true;
},
drop: function (e, data) {
eventsData.drop = data;
},
paste: function (e, data) {
eventsData.paste = data;
},
change: function () {
eventsData.change = true;
}
});
var fileInput = form.fileupload('option', 'fileInput');
var dropZone = form.fileupload('option', 'dropZone');
var pasteZone = form.fileupload('option', 'pasteZone');
form.fileupload('destroy');
expect(form.data('blueimp-fileupload')).to.equal();
fileInput.trigger($.Event('change', eventObject));
expect(eventsData.change).to.equal();
dropZone
.trigger($.Event('dragover', eventObject))
.trigger($.Event('dragenter', eventObject))
.trigger($.Event('dragleave', eventObject))
.trigger($.Event('drop', eventObject));
expect(eventsData.dragover).to.equal();
expect(eventsData.dragenter).to.equal();
expect(eventsData.dragleave).to.equal();
expect(eventsData.drop).to.equal();
pasteZone.trigger($.Event('paste', eventObject));
expect(eventsData.paste).to.equal();
});
it('disable', function () {
var eventsData = {};
form.fileupload('option', {
pasteZone: document,
dragover: function () {
eventsData.dragover = true;
},
dragenter: function () {
eventsData.dragenter = true;
},
dragleave: function () {
eventsData.dragleave = true;
},
drop: function (e, data) {
eventsData.drop = data;
},
paste: function (e, data) {
eventsData.paste = data;
},
change: function () {
eventsData.change = true;
}
});
form.fileupload('disable');
form
.fileupload('option', 'fileInput')
.trigger($.Event('change', eventObject));
expect(eventsData.change).to.equal();
form
.fileupload('option', 'dropZone')
.trigger($.Event('dragover', eventObject))
.trigger($.Event('dragenter', eventObject))
.trigger($.Event('dragleave', eventObject))
.trigger($.Event('drop', eventObject));
expect(eventsData.dragover).to.equal();
expect(eventsData.dragenter).to.equal();
expect(eventsData.dragleave).to.equal();
expect(eventsData.drop).to.equal();
form
.fileupload('option', 'pasteZone')
.trigger($.Event('paste', eventObject));
expect(eventsData.paste).to.equal();
});
it('enable', function () {
var eventsData = {};
form.fileupload('option', {
pasteZone: document,
dragover: function () {
eventsData.dragover = true;
},
dragenter: function () {
eventsData.dragenter = true;
},
dragleave: function () {
eventsData.dragleave = true;
},
drop: function (e, data) {
eventsData.drop = data;
},
paste: function (e, data) {
eventsData.paste = data;
},
change: function () {
eventsData.change = true;
}
});
form.fileupload('disable');
form.fileupload('enable');
form
.fileupload('option', 'fileInput')
.trigger($.Event('change', eventObject));
expect(eventsData.change).to.equal(true);
form
.fileupload('option', 'dropZone')
.trigger($.Event('dragover', eventObject))
.trigger($.Event('dragenter', eventObject))
.trigger($.Event('dragleave', eventObject))
.trigger($.Event('drop', eventObject));
expect(eventsData.dragover).to.equal(true);
expect(eventsData.dragenter).to.equal(true);
expect(eventsData.dragleave).to.equal(true);
expect(eventsData.drop.files).to.deep.equal(files);
form
.fileupload('option', 'pasteZone')
.trigger($.Event('paste', eventObject));
expect(eventsData.paste.files).to.deep.equal(files);
});
it('option', function () {
var eventsData = {};
form.fileupload('option', 'drop', function (e, data) {
eventsData.drop = data;
});
var dropZone = form
.fileupload('option', 'dropZone')
.trigger($.Event('drop', eventObject));
expect(eventsData.drop.files).to.deep.equal(files);
delete eventsData.drop;
form.fileupload('option', 'dropZone', null);
dropZone.trigger($.Event('drop', eventObject));
expect(eventsData.drop).to.equal();
form.fileupload('option', {
dropZone: dropZone
});
dropZone.trigger($.Event('drop', eventObject));
expect(eventsData.drop.files).to.deep.equal(files);
});
it('add', function () {
var eventData = [];
form.fileupload('option', 'add', function (e, data) {
eventData.push(data);
});
form.fileupload('add', { files: files });
expect(eventData.length).to.equal(2);
expect(eventData[0].files[0]).to.equal(files[0]);
expect(eventData[1].files[0]).to.equal(files[1]);
});
it('send', function (done) {
this.slow(200);
form.fileupload('send', { files: files }).complete(function (result) {
var uploadedFiles = result.responseJSON.files;
expect(uploadedFiles.length).to.equal(2);
expect(uploadedFiles[0].type).to.equal(files[0].type);
expect(uploadedFiles[0].error).to.equal();
expect(uploadedFiles[1].type).to.equal(files[1].type);
expect(uploadedFiles[1].error).to.equal();
done();
});
});
});
describe('Callbacks', function () {
var form;
beforeEach(function () {
form = createFileuploadForm().fileupload({ dataType: 'json' });
});
afterEach(function () {
form.remove();
});
it('add', function () {
var eventData = [];
form.fileupload('option', 'add', function (e, data) {
eventData.push(data);
});
form.fileupload('add', { files: files });
expect(eventData.length).to.equal(2);
expect(eventData[0].files[0]).to.equal(files[0]);
expect(eventData[1].files[0]).to.equal(files[1]);
});
it('submit', function (done) {
this.slow(200);
var eventData = [];
form.fileupload('option', {
submit: function (e, data) {
eventData.push(data);
},
stop: function () {
if (eventData.length < 2) return;
expect(eventData[0].files[0]).to.equal(files[0]);
expect(eventData[1].files[0]).to.equal(files[1]);
done();
}
});
form.fileupload('add', { files: files });
});
it('send', function (done) {
this.slow(200);
var eventData = [];
form.fileupload('option', {
send: function (e, data) {
eventData.push(data);
},
stop: function () {
expect(eventData.length).to.equal(1);
expect(eventData[0].files).to.deep.equal(files);
done();
}
});
form.fileupload('send', { files: files });
});
it('done', function (done) {
this.slow(200);
var eventData = [];
form.fileupload('option', {
done: function (e, data) {
eventData.push(data);
},
stop: function () {
if (eventData.length < 2) return;
expect(eventData[0].result.files.length).to.equal(1);
expect(eventData[1].result.files.length).to.equal(1);
done();
}
});
form.fileupload('add', { files: files });
});
it('fail', function (done) {
this.slow(200);
var eventData = [];
form.fileupload('option', {
url: uploadURL + '404',
fail: function (e, data) {
eventData.push(data);
},
stop: function () {
if (eventData.length < 2) return;
expect(eventData[0].result).to.equal();
expect(eventData[1].result).to.equal();
done();
}
});
form.fileupload('add', { files: files });
});
it('always', function (done) {
this.slow(200);
var eventData = [];
form.fileupload('option', {
always: function (e, data) {
eventData.push(data);
},
stop: function () {
if (eventData.length < 2) {
expect(eventData[0].result).to.equal();
form.fileupload('add', { files: [fileGIF] });
return;
}
expect(eventData[1].result.files.length).to.equal(1);
done();
}
});
form.fileupload('add', { files: [fileGIF], url: uploadURL + '404' });
});
it('progress', function (done) {
this.slow(200);
var loaded;
var total;
form.fileupload('option', {
progress: function (e, data) {
loaded = data.loaded;
total = data.total;
expect(loaded).to.be.at.most(total);
},
stop: function () {
expect(loaded).to.equal(total);
done();
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('progressall', function (done) {
this.slow(200);
var loaded;
var total;
var completed = 0;
form.fileupload('option', {
progressall: function (e, data) {
loaded = data.loaded;
total = data.total;
expect(loaded).to.be.at.most(total);
},
always: function () {
completed++;
},
stop: function () {
if (completed < 2) return;
expect(loaded).to.equal(total);
done();
}
});
form.fileupload('add', { files: files });
});
it('start', function (done) {
this.slow(200);
var started;
form.fileupload('option', {
start: function () {
started = true;
},
stop: function () {
expect(started).to.equal(true);
done();
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('stop', function (done) {
this.slow(200);
form.fileupload('option', {
stop: function () {
done();
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('dragover', function () {
var eventsData = {};
form.fileupload('option', {
autoUpload: false,
dragover: function () {
eventsData.dragover = true;
}
});
form
.fileupload('option', 'dropZone')
.trigger($.Event('dragover', eventObject));
expect(eventsData.dragover).to.equal(true);
});
it('dragenter', function () {
var eventsData = {};
form.fileupload('option', {
autoUpload: false,
dragenter: function () {
eventsData.dragenter = true;
}
});
form
.fileupload('option', 'dropZone')
.trigger($.Event('dragenter', eventObject));
expect(eventsData.dragenter).to.equal(true);
});
it('dragleave', function () {
var eventsData = {};
form.fileupload('option', {
autoUpload: false,
dragleave: function () {
eventsData.dragleave = true;
}
});
form
.fileupload('option', 'dropZone')
.trigger($.Event('dragleave', eventObject));
expect(eventsData.dragleave).to.equal(true);
});
it('drop', function () {
var eventsData = {};
form.fileupload('option', {
autoUpload: false,
drop: function (e, data) {
eventsData.drop = data;
}
});
form
.fileupload('option', 'dropZone')
.trigger($.Event('drop', eventObject));
expect(eventsData.drop.files).to.deep.equal(files);
});
it('paste', function () {
var eventsData = {};
form.fileupload('option', {
autoUpload: false,
pasteZone: document,
paste: function (e, data) {
eventsData.paste = data;
}
});
form
.fileupload('option', 'pasteZone')
.trigger($.Event('paste', eventObject));
expect(eventsData.paste.files).to.deep.equal(files);
});
it('change', function () {
var eventsData = {};
form.fileupload('option', {
autoUpload: false,
change: function () {
eventsData.change = true;
}
});
form
.fileupload('option', 'fileInput')
.trigger($.Event('change', eventObject));
expect(eventsData.change).to.equal(true);
});
});
describe('Options', function () {
var form;
beforeEach(function () {
form = createFileuploadForm();
});
afterEach(function () {
form.remove();
});
it('paramName', function (done) {
form.fileupload({
send: function (e, data) {
expect(data.paramName[0]).to.equal(
form.fileupload('option', 'fileInput').prop('name')
);
done();
return false;
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('url', function (done) {
form.fileupload({
send: function (e, data) {
expect(data.url).to.equal(form.prop('action'));
done();
return false;
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('type', function (done) {
form.fileupload({
type: 'PUT',
send: function (e, data) {
expect(data.type).to.equal('PUT');
done();
return false;
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('replaceFileInput', function () {
form.fileupload();
var fileInput = form.fileupload('option', 'fileInput');
fileInput.trigger($.Event('change', eventObject));
expect(form.fileupload('option', 'fileInput')[0]).to.not.equal(
fileInput[0]
);
form.fileupload('option', 'replaceFileInput', false);
fileInput = form.fileupload('option', 'fileInput');
fileInput.trigger($.Event('change', eventObject));
expect(form.fileupload('option', 'fileInput')[0]).to.equal(fileInput[0]);
});
it('forceIframeTransport', function (done) {
form.fileupload({
forceIframeTransport: 'PUT',
send: function (e, data) {
expect(data.dataType.substr(0, 6)).to.equal('iframe');
done();
return false;
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('singleFileUploads', function (done) {
form.fileupload({
singleFileUploads: false,
send: function (e, data) {
expect(data.files).to.deep.equal(files);
done();
return false;
}
});
form.fileupload('add', { files: files });
});
it('limitMultiFileUploads', function (done) {
var completed = 0;
form.fileupload({
singleFileUploads: false,
limitMultiFileUploads: 2,
send: function (e, data) {
expect(data.files).to.deep.equal(files);
completed++;
if (completed < 2) return;
done();
return false;
}
});
form.fileupload('add', { files: files.concat(files) });
});
it('limitMultiFileUploadSize', function (done) {
var completed = 0;
form.fileupload({
singleFileUploads: false,
limitMultiFileUploadSize: files[0].size + files[1].size,
limitMultiFileUploadSizeOverhead: 0,
send: function (e, data) {
expect(data.files).to.deep.equal(files);
completed++;
if (completed < 2) return;
done();
return false;
}
});
form.fileupload('add', { files: files.concat(files) });
});
it('sequentialUploads', function (done) {
this.slow(400);
var completed = 0;
var events = [];
form.fileupload({
sequentialUploads: true,
dataType: 'json',
send: function () {
events.push('send');
},
always: function () {
events.push('complete');
completed++;
},
stop: function () {
if (completed === 4) {
expect(events.join(',')).to.equal(
[
'send',
'complete',
'send',
'complete',
'send',
'complete',
'send',
'complete'
].join(',')
);
done();
}
}
});
form.fileupload('add', { files: files.concat(files) });
});
it('limitConcurrentUploads', function (done) {
this.slow(800);
var completed = 0;
var loadCount = 0;
form.fileupload({
limitConcurrentUploads: 2,
dataType: 'json',
send: function () {
loadCount++;
expect(loadCount).to.be.at.most(2);
},
always: function () {
completed++;
loadCount--;
},
stop: function () {
if (completed === 8) {
done();
}
}
});
form.fileupload('add', {
files: files.concat(files).concat(files).concat(files)
});
});
it('multipart', function (done) {
form.fileupload({
multipart: false,
send: function (e, data) {
expect(data.contentType).to.equal(fileGIF.type);
expect(data.headers['Content-Disposition']).to.equal(
'attachment; filename="' + fileGIF.name + '"'
);
done();
return false;
}
});
form.fileupload('add', { files: [fileGIF] });
});
it('uniqueFilenames', function (done) {
form.fileupload({
uniqueFilenames: {},
send: function (e, data) {
var formFiles = data.data.getAll('files[]');
expect(formFiles[0].name).to.equal(fileGIF.name);
expect(formFiles[1].name).to.equal(
fileGIF.name.replace('.gif', ' (1).gif')
);
expect(formFiles[2].name).to.equal(
fileGIF.name.replace('.gif', ' (2).gif')
);
done();
return false;
}
});
form.fileupload('send', { files: [fileGIF, fileGIF, fileGIF] });
});
it('maxChunkSize', function (done) {
this.slow(400);
var events = [];
form.fileupload({
maxChunkSize: 32,
dataType: 'json',
chunkbeforesend: function () {
events.push('chunkbeforesend');
},
chunksend: function () {
events.push('chunksend');
},
chunkdone: function () {
events.push('chunkdone');
},
done: function (e, data) {
var uploadedFile = data.result.files[0];
expect(uploadedFile.type).to.equal(fileGIF.type);
expect(uploadedFile.size).to.equal(fileGIF.size);
},
stop: function () {
expect(events.join(',')).to.equal(
[
'chunkbeforesend',
'chunksend',
'chunkdone',
'chunkbeforesend',
'chunksend',
'chunkdone',
'chunkbeforesend',
'chunksend',
'chunkdone',
'chunkbeforesend',
'chunksend',
'chunkdone'
].join(',')
);
done();
}
});
form.fileupload('send', { files: [fileGIF] });
});
it('acceptFileTypes', function (done) {
var processData;
form.fileupload({
acceptFileTypes: /^image\/gif$/,
singleFileUploads: false,
processalways: function (e, data) {
processData = data;
},
processstop: function () {
expect(processData.files[0].error).to.equal();
expect(processData.files[1].error).to.equal(
form.fileupload('option').i18n('acceptFileTypes')
);
done();
}
});
form.fileupload('add', { files: files });
});
it('maxFileSize', function (done) {
var processData;
form.fileupload({
maxFileSize: 200,
singleFileUploads: false,
processalways: function (e, data) {
processData = data;
},
processstop: function () {
expect(processData.files[0].error).to.equal();
expect(processData.files[1].error).to.equal(
form.fileupload('option').i18n('maxFileSize')
);
done();
}
});
form.fileupload('add', { files: files });
});
it('minFileSize', function (done) {
var processData;
form.fileupload({
minFileSize: 200,
singleFileUploads: false,
processalways: function (e, data) {
processData = data;
},
processstop: function () {
expect(processData.files[0].error).to.equal(
form.fileupload('option').i18n('minFileSize')
);
expect(processData.files[1].error).to.equal();
done();
}
});
form.fileupload('add', { files: files });
});
it('maxNumberOfFiles', function (done) {
var processData;
form.fileupload({
maxNumberOfFiles: 2,
getNumberOfFiles: function () {
return 2;
},
singleFileUploads: false,
processalways: function (e, data) {
processData = data;
},
processstop: function () {
expect(processData.files[0].error).to.equal(
form.fileupload('option').i18n('maxNumberOfFiles')
);
expect(processData.files[1].error).to.equal(
form.fileupload('option').i18n('maxNumberOfFiles')
);
done();
}
});
form.fileupload('add', { files: files });
});
});
})(this.chai.expect, this.jQuery);

10854
lib/jQuery-File-Upload/test/vendor/chai.js vendored Executable file

File diff suppressed because it is too large Load diff

325
lib/jQuery-File-Upload/test/vendor/mocha.css vendored Executable file
View file

@ -0,0 +1,325 @@
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul,
#mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1,
#mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #c09853;
}
#mocha .test.pass.slow .duration {
background: #b94a48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: #fff;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
#mocha .test .html-error {
overflow: auto;
color: black;
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
max-width: 85%; /*(1)*/
max-width: -webkit-calc(100% - 42px);
max-width: -moz-calc(100% - 42px);
max-width: calc(100% - 42px); /*(2)*/
max-height: 300px;
word-wrap: break-word;
border-bottom-color: #ddd;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-box-shadow: 0 1px 3px #eee;
box-shadow: 0 1px 3px #eee;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
#mocha .test .html-error pre.error {
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: 0;
-moz-box-shadow: 0;
box-shadow: 0;
padding: 0;
margin: 0;
margin-top: 18px;
max-height: none;
}
/**
* (1): approximate for browsers not supporting calc
* (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
* ^^ seriously
*/
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
max-width: 85%; /*(1)*/
max-width: -webkit-calc(100% - 42px);
max-width: -moz-calc(100% - 42px);
max-width: calc(100% - 42px); /*(2)*/
word-wrap: break-word;
border-bottom-color: #ddd;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-box-shadow: 0 1px 3px #eee;
box-shadow: 0 1px 3px #eee;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition:opacity 200ms;
-moz-transition:opacity 200ms;
-o-transition:opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
/**
* Set safe initial values, so mochas .progress does not inherit these
* properties from Bootstrap .progress (which causes .progress height to
* equal line height set in Bootstrap).
*/
height: auto;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
background-color: initial;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
#mocha-stats canvas {
width: 40px;
height: 40px;
}
#mocha code .comment { color: #ddd; }
#mocha code .init { color: #2f6fad; }
#mocha code .string { color: #5890ad; }
#mocha code .keyword { color: #8a6343; }
#mocha code .number { color: #2f6fad; }
@media screen and (max-device-width: 480px) {
#mocha {
margin: 60px 0px;
}
#mocha #stats {
position: absolute;
}
}

18178
lib/jQuery-File-Upload/test/vendor/mocha.js vendored Executable file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,10 @@
'use strict'
module.exports = {
env: {
node: true
},
parserOptions: {
ecmaVersion: 2019
}
}

View file

@ -0,0 +1,9 @@
'use strict'
module.exports = {
arrowParens: 'avoid',
proseWrap: 'always',
semi: false,
singleQuote: true,
trailingComma: 'none'
}

View file

@ -0,0 +1,20 @@
MIT License
Copyright © 2019 Sebastian Tschan, https://blueimp.net
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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

View file

@ -0,0 +1,85 @@
#!/bin/sh
#
# Adds TCP/UDP port forwarding rules to the pf firewall (MacOS/BSD).
#
# Adds rules for both TCP and UDP in addition to those from /etc/pf.conf.
# Requires an existing rdr-anchor entry in /etc/pf.conf.
# Only adds rules temporarily, without changing any files.
#
# Usage: ./forward-ports.sh [[nic:]port=[ip:]port [...]]
#
# If no network interface is given, forwards from all interfaces.
# If no IP is given, forwards to 127.0.0.1.
# If no port forwarding rule is given, resets to the rules from /etc/pf.conf.
#
# e.g. forwarding ports 80 and 443 on network interface en0 to ports 8080 and
# 8443 on localhost respectively:
# ./forward-ports.sh en0:80=8080 en0:443=8443
#
# Copyright 2019, Sebastian Tschan
# https://blueimp.net
#
# Licensed under the MIT license:
# https://opensource.org/licenses/MIT
#
set -e
RULES=
NEWLINE='
'
print_usage_exit() {
if [ -n "$RULES" ]; then
printf '\nError in custom rules:\n%s\n' "$RULES" >&2
fi
echo "Usage: $0 [[nic:]port=[ip:]port [...]]" >&2
exit 1
}
print_nat_rules() {
echo
echo 'Loaded NAT rules:'
sudo pfctl -s nat 2>/dev/null
echo
}
# Print usage and exit if option arguments like "-h" are used:
if [ "${1#-}" != "$1" ]; then print_usage_exit; fi
while test $# -gt 0; do
# Separate the from=to parts:
from=${1%=*}
to=${1#*=}
# If from part has a nic defined, extract it, else forward from all:
case "$from" in
*:*) nic="on ${from%:*}";;
*) nic=;;
esac
# Extract the port to forward from:
from_port=${from##*:}
# If to part has an IP defined, extract it, else forward to 127.0.0.1:
case "$to" in
*:*) to_ip=${to%:*};;
*) to_ip=127.0.0.1;;
esac
# Extract the port to forward to:
to_port=${to##*:}
# Create the packet filter (pf) forwarding rule for both TCP and UDP:
rule=$(
printf \
'rdr pass %s inet proto %s from any to any port %s -> %s port %s' \
"$nic" '{tcp udp}' "$from_port" "$to_ip" "$to_port"
)
# Add it to the list of rules:
RULES="$RULES$rule$NEWLINE"
shift
done
# Add the rules after the line matching "rdr-anchor" in /etc/pf.conf, print the
# combined rules to STDOUT and load the rules into pf from STDIN.
# Finally, display the loaded NAT rules or print the script usage on failure:
# shellcheck disable=SC2015
printf %s "$RULES" | sed -e '/rdr-anchor/r /dev/stdin' /etc/pf.conf |
sudo pfctl -Ef - 2>/dev/null && print_nat_rules || print_usage_exit

View file

@ -0,0 +1,43 @@
#!/bin/sh
if [ "$1" = -t ]; then
BIN='/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
shift
else
BIN=safaridriver
fi
SCREEN='Capture screen'
if [ -z "$1" ]; then
OUTPUT=$(ffmpeg -f avfoundation -list_devices true -i - 2>&1 | grep "$SCREEN")
if [ "$(echo "$OUTPUT" | grep -c ^)" -gt 1 ]; then
echo 'Please select the input device by entering its [index] number:' >&2
echo "$OUTPUT" >&2
read -r INDEX
fi
else
INDEX=$1
fi
echo 'Starting safaridriver on 127.0.0.1:4444 ...' >&2
"$BIN" -p 4444 & pid=$!
# shellcheck disable=SC2064
trap "kill $pid; exit" INT TERM
echo 'Starting mjpeg-server on 127.0.0.1:9000 ...' >&2
mjpeg-server -a 127.0.0.1:9000 -- ffmpeg \
-loglevel error \
-probesize 32 \
-fpsprobesize 0 \
-analyzeduration 0 \
-fflags nobuffer \
-f avfoundation \
-capture_cursor 1 \
-r "${FPS:-15}" \
-pixel_format yuyv422 \
-i "${INDEX:-$SCREEN}" \
-f mpjpeg \
-q "${QUALITY:-2}" \
-

View file

@ -0,0 +1,40 @@
'use strict'
/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
hostname: 'chromedriver',
path: '/',
capabilities: [
{
// Set maxInstances to 1 if screen recordings are enabled:
// maxInstances: 1,
browserName: 'chrome',
'goog:chromeOptions': {
// Disable headless mode if screen recordings are enabled:
args: ['--headless', '--window-size=1440,900']
}
}
],
logLevel: 'warn',
reporters: ['spec'],
framework: 'mocha',
mochaOpts: {
timeout: 60000
},
specs: ['test/specs/**/*.js'],
maximizeWindow: true,
screenshots: {
saveOnFail: true
},
videos: {
enabled: false,
resolution: '1440x900',
startDelay: 500,
stopDelay: 500
},
assetsDir: '/home/webdriver/assets/',
baseUrl: 'http://example'
}
exports.config = Object.assign({}, require('../hooks'), config)

View file

@ -0,0 +1,23 @@
'use strict'
/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
hostname: process.env.WINDOWS_HOST || 'host.docker.internal',
capabilities: [
{
// Set maxInstances to 1 if screen recordings are enabled:
// maxInstances: 1,
browserName: 'MicrosoftEdge'
}
],
videos: {
enabled: false,
inputFormat: 'mjpeg',
startDelay: 500,
stopDelay: 500
},
assetsDir: process.env.WINDOWS_ASSETS_DIR || process.env.MACOS_ASSETS_DIR
}
exports.config = Object.assign({}, require('./chrome').config, config)

View file

@ -0,0 +1,25 @@
'use strict'
/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
hostname: 'geckodriver',
capabilities: [
{
// geckodriver supports no parallel sessions:
maxInstances: 1,
browserName: 'firefox',
'moz:firefoxOptions': {
//args: ['-headless', '--window-size=1440,900']
}
}
],
videos: {
enabled: true,
resolution: '1440x900',
startDelay: 500,
stopDelay: 500
}
}
exports.config = Object.assign({}, require('./chrome').config, config)

View file

@ -0,0 +1,24 @@
'use strict'
/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
hostname: process.env.WINDOWS_HOST || 'host.docker.internal',
port: 4445,
capabilities: [
{
// IEDriverServer supports no parallel sessions:
maxInstances: 1,
browserName: 'internet explorer'
}
],
videos: {
enabled: true,
inputFormat: 'mjpeg',
startDelay: 500,
stopDelay: 500
},
assetsDir: process.env.WINDOWS_ASSETS_DIR
}
exports.config = Object.assign({}, require('./chrome').config, config)

View file

@ -0,0 +1,24 @@
'use strict'
/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
// Docker for Mac host address:
hostname: 'host.docker.internal',
capabilities: [
{
// safaridriver supports no parallel sessions:
maxInstances: 1,
browserName: 'safari'
}
],
videos: {
enabled: true,
inputFormat: 'mjpeg',
startDelay: 500,
stopDelay: 500
},
assetsDir: process.env.MACOS_ASSETS_DIR
}
exports.config = Object.assign({}, require('./chrome').config, config)

View file

@ -0,0 +1,27 @@
'use strict'
/* global browser, Promise */
const cmds = require('wdio-screen-commands')
/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
before: async () => {
global.Should = require('chai').should()
browser.addCommand('saveScreenshotByName', cmds.saveScreenshotByName)
browser.addCommand('saveAndDiffScreenshot', cmds.saveAndDiffScreenshot)
if (browser.config.maximizeWindow) await browser.maximizeWindow()
},
beforeTest: async test => {
await cmds.startScreenRecording(test)
},
afterTest: async test => {
await Promise.all([
cmds.stopScreenRecording(test),
cmds.saveScreenshotByTest(test)
])
}
}
module.exports = config

View file

@ -0,0 +1,2 @@
*
!/.gitignore

View file

@ -0,0 +1,75 @@
'use strict'
/* global browser, $, $$ */
/* eslint-disable class-methods-use-this */
class FileUpload {
get fileinput() {
return $('.fileinput-button input')
}
get start() {
return $('.fileupload-buttonbar .start')
}
get toggle() {
return $('.fileupload-buttonbar .toggle')
}
get remove() {
return $('.fileupload-buttonbar .delete')
}
get processing() {
return $$('.files .processing')
}
get uploads() {
return $$('.files .template-upload')
}
get downloads() {
return $$('.files .template-download')
}
get checked() {
return $$('.files .toggle:checked')
}
/**
* Opens the file upload form.
*
* @param {number} [timeout] Wait timeout
* @returns {FileUpload} FileUpload object
*/
open(timeout) {
browser.url('/')
this.fileinput.waitForExist(timeout)
return this
}
/**
* Uploads files.
*
* @param {Array<string>} files Files to upload
* @param {number} [timeout] Wait timeout
* @returns {FileUpload} FileUpload object
*/
upload(files, timeout) {
this.fileinput.addValue(files.join('\n'))
browser.waitUntil(() => !this.processing.length, timeout)
this.start.click()
browser.waitUntil(() => !!this.downloads.length, timeout)
browser.waitUntil(() => !this.uploads.length, timeout)
return this
}
/**
* Deletes uploaded files.
*
* @param {number} [timeout] Wait timeout
* @returns {FileUpload} FileUpload object
*/
delete(timeout) {
this.toggle.click()
browser.waitUntil(
() => this.downloads.length === this.checked.length,
timeout
)
this.remove.click()
browser.waitUntil(() => !this.downloads.length, timeout)
return this
}
}
module.exports = new FileUpload()

View file

@ -0,0 +1,23 @@
'use strict'
/* global browser, describe, it */
const FileUpload = require('../pages/file-upload')
const assetsDir = browser.config.assetsDir
describe('File Upload', () => {
if (!assetsDir) return
it('uploads files', () => {
FileUpload.open().upload([
assetsDir + 'black+white-60x40.gif',
assetsDir + 'black+white-3x2.jpg'
])
browser.saveAndDiffScreenshot('Files uploaded')
})
it('deletes files', () => {
FileUpload.open().delete()
browser.saveAndDiffScreenshot('Files deleted')
})
})

View file

@ -0,0 +1,4 @@
'use strict'
// Default to the Chrome config:
exports.config = require('./conf/chrome').config

View file

@ -66,18 +66,11 @@ body{
width: 90%;
}
}
@media screen and (min-width: 800px) {
@media screen and (min-width: 1000px) {
#page-wrap {
width: 600px;
width: 800px;
}
}
.uploadArea {
text-align: center;
}
.uploadArea div {
margin: 30px;
}
.uploadResult {
font-weight: bold;
}
@ -87,10 +80,12 @@ body{
.uploadResult.nok {
color: #FF0000;
}
#resizeForm {
#ButtonStart,
#ButtonReset {
display: none;
}
.limit {
margin-top: 20px;
text-align: center;
color: #7E7E7E;
}
@ -98,12 +93,12 @@ a {
color:#07396A;
text-decoration:underline;
}
.progress {
#fileupload .expire-button,
#fileupload .boutton {
text-align: center;
padding: 20px;
}
progress {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
}
@media screen and (max-width: 800px) {
@ -175,10 +170,14 @@ progress {
float: left;
width: 25px;
}
.file.input a {
color: #000000;
}
.file.delete,
.deleteAll {
width: 15px;
width: 45px;
float: right;
}
input.copy {
@ -193,12 +192,17 @@ input.copy {
#accessForm,
#passwordForm,
#uploadOptions,
#redirectToFiles,
#addToShare,
.shareUrlPrint,
.delete,
.deleteAll,
.myFiles {
display: none;
}
.passwordForm {
.passwordForm;
#redirectToFiles {
text-align:center;
}
#myFilesTab {
@ -212,6 +216,11 @@ input.copy {
color: #07396A;
text-decoration: none;
}
#newUploadPub {
text-align:center;
font-size: 120%;
margin: 10px;
}
.newUpload {
text-align: center;
margin: 10px;
@ -221,9 +230,21 @@ input.copy {
.newUpload img{
width: 100px;
}
.error.myFiles0 {
.similarServices {
text-align: center;
}
#redirectToFiles {
font-style:bold;
}
.error.myFiles0,
#maxUploadTotalError {
text-align:center;
}
#maxUploadTotalError {
font-style: bold;
color: red;
display: none;
}
.fileGlobal.fileAll,
.fileGlobal.fileJust1 {
background-color: #EBEBEB;

View file

@ -1,207 +1,77 @@
function idGen() {
var expire = Math.floor(Date.now() / 1000 + $('#expire').val() * 86400);
var random = Math.floor(Math.random() * Math.floor(99));
return expire + '-' + random;
}
$(function () {
function checkMimeTypes(mimeTypesTest) {
var mimeDetect=false;
Config_mimeTypes.forEach(function(item, index, array) {
var regex = item.replace(/\//g, "\\\/");
if (mimeTypesTest.match(regex) != undefined) {
mimeDetect=true;
}
});
if ((Config_mimeTypesConduct == 'allow' && mimeDetect)
|| (Config_mimeTypesConduct == 'deny' && !mimeDetect)) {
return true;
} else {
return false;
}
}
/**
* Function called to upload one file.
* @param file
* @param item
*/
function uploadFile(item, file, expire, random, resize, key, password, access) {
// Add progress bar
$('.progress').show();
$('.progress').append('<span class="file-' + item + '">' + file.name + '</span><br /><progress class="progress-' + item + '" value="0" max="100"></progress>');
// Create object XMLHttpRequest
var request = new XMLHttpRequest();
// Event progress to change value of progress bar
request.upload.addEventListener('progress', function (e) {
$('.progress-' + item).css('display', 'block');
var value = Math.round((e.loaded / e.total) * 100);
$('.progress-' + item).attr("value", value);
}, false);
// Create object FormData
var formData = new FormData();
// Add file to FormData
formData.append('random', random);
formData.append('item', item);
formData.append('file', file);
formData.append('expire', expire);
formData.append('resize', resize);
formData.append('key', key);
formData.append('password', password);
formData.append('access', access);
// File to call
request.open('post', 'upload.php');
// Function called when request ended
request.onload = function (e) {
$('#result').append(request.response);
};
// Send request
request.send(formData);
}
/**
* Function called to upload files.
*/
function upload() {
// Vide les messages si jamais il y en avait
$( "#preUpload" ).html( "" );
var upload = true;
// Get files
var files = $('#files')[0].files;
var expire = Math.floor(Date.now() / 1000 + $('#expire').val() * 86400);
var random = Math.floor(Math.random() * Math.floor(99));
var password = false
if ($('#passwordCheckbox').is(':checked')) {
password=$('#password').val();
}
var access = false
if ($('#accessCheckbox').is(':checked')) {
access=$('#access').val();
}
// Check size and mime
var fileAlreadyUploadSizeTotal = 0;
for (var i = 0; i < files.length; i++) {
// Size
fileAlreadyUploadSizeTotal = fileAlreadyUploadSizeTotal + document.getElementById("files").files[i].size;
if (document.getElementById("files").files[i].size > Config_maxUploadPerFile) {
$('#preUpload').append('<div class="highlight-1">' + document.getElementById("files").files[i].name + ' : ' + Msg_errorFileSize + '</div>');
upload = false;
}
// Mime
if (!checkMimeTypes(document.getElementById("files").files[i].type)) {
$('#preUpload').append('<div class="highlight-1">' + document.getElementById("files").files[i].name + ' : ' + Msg_errorFileType + '</div>');
upload = false;
}
}
if (fileAlreadyUploadSizeTotal > Config_maxUploadTotal) {
$('#preUpload').append('<div class="highlight-1">' + Msg_errorTotalSize + '</div>');
upload = false;
}
if (files.length > Config_maxUploadNb) {
$('#preUpload').append('<div class="highlight-1">' + Msg_errorUploadNb + '</div>');
upload = false;
}
if (files.length == 0) {
upload = false;
}
// Upload file by file
if (upload == true) {
// Session pour compter le nombre de fichier en cours de download
sessionStorage.setItem('uploadWait', files.length);
$( ".uploadArea" ).hide();
// On lance l'upload fichier par fichier:
for (var i = 0; i < files.length; i++) {
if (i == 0) {
// On mémorise l'upload dans le localStorage
if (localStorage.getItem('myFiles')) {
var data = JSON.parse(localStorage.getItem('myFiles'));
} else {
var data = {items: []};
}
var keyGen = Math.floor(Math.random() * (999999999999 - 100000000000) + 100000000000);
data.items.push(
{id: expire + '-' + random, key: keyGen}
);
localStorage.setItem('myFiles', JSON.stringify(data));
}
uploadFile(i, files[i], expire, random, $('#resize').val(), keyGen, password, access);
}
}
}
$(function () {
// Copy on clipart : https://stackoverflow.com/questions/44888884/copying-to-clipboard-textbox-value-using-jquery-javascript
function copyToClipboard(text) {
var textArea = document.createElement( "textarea" );
textArea.value = text;
document.body.appendChild( textArea );
textArea.select();
try {
var successful = document.execCommand( 'copy' );
var msg = successful ? 'successful' : 'unsuccessful';
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild( textArea );
}
$('.btn-upload').on('click', upload);
$( "#similarServices" ).click(function() {
$('.similarHref').hide();
$('.similarLink').show();
});
function copyToClipboard(text) {
var textArea = document.createElement( "textarea" );
textArea.value = text;
document.body.appendChild( textArea );
textArea.select();
try {
var successful = document.execCommand( 'copy' );
var msg = successful ? 'successful' : 'unsuccessful';
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild( textArea );
}
$(document).on('click', '.copy', function(){
copyToClipboard($(this).val());
$(this).select();
});
$( "#similarServices" ).click(function() {
$('.similarHref').hide();
$('.similarLink').show();
});
$("input[type=file]").on('change',function(){
$('#resizeForm').hide();
for (var i = 0; i < this.files.length; i++) {
var mime = this.files[i].type;
if (mime.match('^image\/(jpeg|gif)$')) {
$('#resizeForm').show();
}
}
if (this.files.length == 1) {
$('#uploadOptionAccess').show();
} else {
$('#uploadOptionAccess').hide();
$("#accessCheckbox"). prop("checked", false);
$("#accessForm"). hide();
}
});
$("#passwordCheckbox").on('change',function(){
if( $('#passwordCheckbox').is(':checked') ){
$('#passwordForm').show();
} else {
$('#passwordForm').hide();
}
});
$(document).on('click', '.copy', function(){
copyToClipboard($(this).val());
$(this).select();
});
$("#accessCheckbox").on('change',function(){
if( $('#accessCheckbox').is(':checked') ){
$('#accessForm').show();
} else {
$('#accessForm').hide();
}
});
$("#uploadOptionsLinkShow").on('click',function(){
$('#uploadOptions').show();
$('#uploadOptionsLinkShow').hide();
});
$("#uploadOptionsLinkHide").on('click',function(){
$('#uploadOptions').hide();
$('#uploadOptionsLinkShow').show();
});
$("#passwordCheckbox").on('change',function(){
if( $('#passwordCheckbox').is(':checked') ){
$('#passwordForm').show();
} else {
$('#passwordForm').hide();
}
});
$("#accessCheckbox").on('change',function(){
if( $('#accessCheckbox').is(':checked') ){
$('#accessForm').show();
} else {
$('#accessForm').hide();
}
});
$("#uploadOptionsLinkShow").on('click',function(){
$('#uploadOptions').show();
$('#uploadOptionsLinkShow').hide();
});
$("#uploadOptionsLinkHide").on('click',function(){
$('#uploadOptions').hide();
$('#uploadOptionsLinkShow').show();
});
$("#expire").on('change',function(){
$('#files_id').val(idGen());
});
$("#resize").on('change',function(){
$('#fileupload').fileupload('option', {
imageMaxWidth: $('#resize').val(),
imageMaxHeight: $('#resize').val(),
});
});
$('#ButtonStart').hide();
$('#ButtonReset').hide();
});

View file

@ -1,28 +1,53 @@
<?php
if (!isset($_POST['expire']) or !isset($_POST['item']) or !isset($_POST['key']) or !isset($_FILES) or !isset($_POST['random'])) {
if (!isset($_POST['expire']) or !isset($_POST['id']) or !isset($_POST['key'])) {
exit('No hack 1');
}
//~ echo $_POST['access'];
//~ if ($_POST['password'] != 'false') {
//~ echo "post password";
//~ exit($_POST['password']);
//~ }
//~ exit($_POST['access']);
$config = yaml_parse_file('./config.yaml');
include('./lib/functions.php');
// Vérification si le calcul d'expiration est conforme à la config
// Complexe, dépend trop du temps d'upload côté client
/*if ($_POST['expire'] <= time()+$config['expireDay'][count($config['expireDay'])-1]*86400+5) {
exit('No hack 2');
if (isset($_COOKIE['langue'])) {
$locale = lang2locale($_COOKIE['langue']);
$localeshort=locale2lang($locale);
} else {
$HTTP_ACCEPT_LANGUAGE=$_SERVER['HTTP_ACCEPT_LANGUAGE'];
//echo $HTTP_ACCEPT_LANGUAGE.'<br />';
$lang_from_http_accept = explode(',', $HTTP_ACCEPT_LANGUAGE);
//echo $lang_from_http_accept[0].'<br />';
$locale = lang2locale($lang_from_http_accept[0]);
if (substr($locale,0,2) != substr($lang_from_http_accept[0],0,2)) {
//echo "Non trouvé, 2ème tentative";
$lang_from_http_accept = explode('-', $lang_from_http_accept[0]);
//echo $lang_from_http_accept[0].'<br />';
$locale = lang2locale($lang_from_http_accept[0]);
}
//echo $locale.'<br />';
$localeshort=locale2lang($locale);
}
*/
// Définition de la langue :
$results=putenv("LC_ALL=$locale.utf8");
if (!$results) {
exit ('putenv failed');
}
$results=putenv("LC_LANG=$locale.utf8");
if (!$results) {
exit ('putenv failed');
}
$results=putenv("LC_LANGUAGE=$locale.utf8");
if (!$results) {
exit ('putenv failed');
}
$results=setlocale(LC_ALL, "$locale.utf8");
if (!$results) {
exit ('setlocale failed: locale function is not available on this platform, or the given local does not exist in this environment');
}
bindtextdomain("messages", "./lang");
textdomain("messages");
// Définition des variables
$uploadDir = $config['uploadDir'].'/'.$_POST['expire'].'-'.$_POST['random'];
$uploadFile = preg_replace("#[^a-zA-Z0-9.]#", "", basename($_FILES['file']['name']));
$id=$_POST['id'];
$uploadDir = $config['uploadDir'].'/'.$id;
// Création du répertoire
if (!is_dir($uploadDir)) {
mkdir($uploadDir);
@ -34,57 +59,23 @@ if (!is_dir($uploadDir)) {
}
}
}
if (!is_file($uploadDir.'/.key-'.$_POST['key'].'.cfg')) {
touch($uploadDir.'/.key-'.$_POST['key'].'.cfg');
}
if ($_POST['access'] != 'false' && preg_match('/^[0-9]+$/', $_POST['access'])) {
if (isset($_POST['accessCheckbox']) && isset($_POST['access']) && preg_match('/^[0-9]+$/', $_POST['access'])) {
if (!is_file($uploadDir.'/.access.cfg')) {
file_put_contents($uploadDir.'/.access.cfg', $_POST['access']);
file_put_contents($uploadDir.'/.access.cfg', $_POST['access']);
}
}
if ($_POST['password'] != 'false') {
if (isset($_POST['passwordCheckbox']) && isset($_POST['password'])) {
file_put_contents("/tmp/pwd", $_POST['password']);
if (!is_file($uploadDir.'/.password.cfg')) {
file_put_contents($uploadDir.'/.password.cfg', password_hash($config['passwordUniqKey'].$_POST['password'], PASSWORD_DEFAULT));
file_put_contents($uploadDir.'/.password.cfg', password_hash($config['passwordUniqKey'].$_POST['password'], PASSWORD_DEFAULT));
}
}
if (!checkMimeTypes($_FILES['file']['type'])) {
printf('<div class="highlight-1">'._('this type of file isn\'t allow').'</div>');
echo "<script>
$( '.progress-".$_POST['item']."').remove();
$('.file-".$_POST['item']."').append(' : <spam class=\"file-".$_POST['item']." uploadResult nok\">KO</spam>');
</script>";
} else if ($_FILES['file']['size'] > convertHumain2octect($config['maxUploadPerFile'])) {
printf('<div class="highlight-1">'.basename($_FILES['file']['name']).' : '._('this file exceeds the allowed size %s').'</div>', $config['maxUploadPerFile']);
echo "<script>
$( '.progress-".$_POST['item']."').remove();
$('.file-".$_POST['item']."').append(' : <spam class=\"file-".$_POST['item']." uploadResult nok\">KO</spam>');
</script>";
} else if ($fileAlreadyUploadSizeTotal > convertHumain2octect($config['maxUploadTotal'])) {
printf('<div class="highlight-1">'._('The total size of the files exceeds the allowed size %s').'</div>', $config['maxUploadTotal']);
echo "<script>
$( '.progress-".$_POST['item']."').remove();
$('.file-".$_POST['item']."').append(' : <spam class=\"file-".$_POST['item']." uploadResult nok\">KO</spam>');
</script>";
} else {
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadDir.'/'.$uploadFile)
&& $_FILES['file']['error'] == 0) {
if (isset($_POST['resize']) && $_POST['resize'] != 0 && preg_match('/^image\/(jpeg|gif)$/', $_FILES['file']['type'])) {
@resize_image($uploadDir.'/'.$uploadFile , $uploadDir.'/'.$uploadFile.'.resize' , $_POST['resize'] , $_POST['resize']);
@rename($uploadDir.'/'.$uploadFile.'.resize', $uploadDir.'/'.$uploadFile);
}
echo "<script>
sessionStorage.setItem('uploadWait', Number(sessionStorage.getItem('uploadWait'))-1);
$( '.progress-".$_POST['item']."').remove();
$('.file-".$_POST['item']."').append(' : <spam class=\"file-".$_POST['item']." uploadResult ok\">Ok</spam>');
if (sessionStorage.getItem('uploadWait') <= 0) {
sessionStorage.removeItem('uploadWait');
window.location.href = Config_baseUrl + '".$_POST['expire']."-".$_POST['random']."/';
}
</script>";
} else {
printf('<div class="highlight-1">'._('Unknown error').'</div>');
echo "<script>sessionStorage.setItem('uploadWait', sessionStorage.getItem('uploadWait')+1);</script>";
}
}
require('lib/UploadHandler.php');
$upload_handler = new UploadHandler();