added filename special character check, and moved replace regex to front end
This commit is contained in:
parent
49f1fb8745
commit
e99e8291bd
5 changed files with 126 additions and 163 deletions
|
@ -24,14 +24,11 @@ module.exports = {
|
||||||
default:
|
default:
|
||||||
throw new Error('The ' + file.Type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');
|
throw new Error('The ' + file.Type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');
|
||||||
}
|
}
|
||||||
|
// validate claim name
|
||||||
// validate name
|
const invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
||||||
const invalidCharacters = /[^A-Za-z0-9,- ]/.exec(name);
|
|
||||||
if (invalidCharacters) {
|
if (invalidCharacters) {
|
||||||
throw new Error('The name you provided is not allowed. Please use A-Z, a-z, 0-9, and "-" only.');
|
throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"');
|
||||||
}
|
}
|
||||||
name = str.replace(/\s+/g, '-'); //replace space with dash/hyphen
|
|
||||||
|
|
||||||
// validate license
|
// validate license
|
||||||
if ((license.indexOf('Public Domain') === -1) && (license.indexOf('Creative Commons') === -1)) {
|
if ((license.indexOf('Public Domain') === -1) && (license.indexOf('Creative Commons') === -1)) {
|
||||||
throw new Error('Only posts with a license of "Public Domain" or "Creative Commons" are eligible for publishing through spee.ch');
|
throw new Error('Only posts with a license of "Public Domain" or "Creative Commons" are eligible for publishing through spee.ch');
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
// define variables
|
|
||||||
var socket = io();
|
|
||||||
var uploader = new SocketIOFileUpload(socket);
|
|
||||||
var stagedFiles = null;
|
|
||||||
|
|
||||||
/* configure the submit button */
|
|
||||||
function publishSelectedImage(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
// validate inputs
|
|
||||||
var name = document.getElementById('publish-name').value;
|
|
||||||
try {
|
|
||||||
validateSubmission(stagedFiles, name);
|
|
||||||
} catch (error) {
|
|
||||||
if (error.name === 'FileError'){
|
|
||||||
showError('input-error-file-selection', error.message);
|
|
||||||
} else if (error.name === 'NameError') {
|
|
||||||
showError('input-error-claim-name', error.message);
|
|
||||||
} else {
|
|
||||||
showError('input-error-publish-submit', error.message);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// make sure the name is available then start the upload
|
|
||||||
validateClaimName(name)
|
|
||||||
.then(function() {
|
|
||||||
uploader.submitFiles(stagedFiles); //note: must pass the file as part of an array.
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
showError('input-error-claim-name', error);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
/* socketio-file-upload listeners */
|
|
||||||
uploader.addEventListener('start', function(event){
|
|
||||||
var name = document.getElementById('publish-name').value;
|
|
||||||
var license = document.getElementById('publish-license').value;
|
|
||||||
var nsfw = document.getElementById('publish-nsfw').checked;
|
|
||||||
event.file.meta.name = name;
|
|
||||||
event.file.meta.license = license;
|
|
||||||
event.file.meta.nsfw = nsfw;
|
|
||||||
event.file.meta.type = stagedFiles[0].type;
|
|
||||||
// re-set the html in the publish area
|
|
||||||
document.getElementById('publish-active-area').innerHTML = '<div id="publish-status"></div><div id="progress-bar"></div>';
|
|
||||||
// start a progress animation
|
|
||||||
createProgressBar(document.getElementById('progress-bar'), 12);
|
|
||||||
// google analytics
|
|
||||||
ga('send', {
|
|
||||||
hitType: 'event',
|
|
||||||
eventCategory: 'publish',
|
|
||||||
eventAction: name
|
|
||||||
});
|
|
||||||
});
|
|
||||||
uploader.addEventListener('progress', function(event){
|
|
||||||
var percent = event.bytesLoaded / event.file.size * 100;
|
|
||||||
updatePublishStatus('File is ' + percent.toFixed(2) + '% loaded to the server');
|
|
||||||
});
|
|
||||||
|
|
||||||
/* socket.io message listeners */
|
|
||||||
socket.on('publish-status', function(msg){
|
|
||||||
updatePublishStatus(msg);
|
|
||||||
});
|
|
||||||
socket.on('publish-failure', function(msg){
|
|
||||||
document.getElementById('publish-active-area').innerHTML = '<p> --(✖╭╮✖)→ </p><p>' + JSON.stringify(msg) + '</p><strong>For help, post the above error text in the #speech channel on the <a href="https://lbry.slack.com/" target="_blank">lbry slack</a></strong>';
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('publish-complete', function(msg){
|
|
||||||
var publishResults;
|
|
||||||
var showUrl = '/show/' + msg.name + '/' + msg.result.claim_id;
|
|
||||||
// build new publish area
|
|
||||||
publishResults = '<p>Your publish is complete! You are being redirected to it now.</p>';
|
|
||||||
publishResults += '<p><a target="_blank" href="' + showUrl + '">If you do not get redirected, click here.</a></p>';
|
|
||||||
// update publish area
|
|
||||||
document.getElementById('publish-active-area').innerHTML = publishResults;
|
|
||||||
window.location.href = showUrl;
|
|
||||||
});
|
|
|
@ -2,7 +2,7 @@
|
||||||
function updatePublishStatus(msg){
|
function updatePublishStatus(msg){
|
||||||
document.getElementById('publish-status').innerHTML = msg;
|
document.getElementById('publish-status').innerHTML = msg;
|
||||||
}
|
}
|
||||||
|
// validation function which checks the proposed file's type and size
|
||||||
function validateFile(file) {
|
function validateFile(file) {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw new Error('no file provided');
|
throw new Error('no file provided');
|
||||||
|
@ -22,28 +22,28 @@ function validateFile(file) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error('The ' + file.Type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.')
|
throw new Error(file.type + ' is not supported a supported file type. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.')
|
||||||
}
|
}
|
||||||
|
// validate the file name (note: different from the lbry claim name)
|
||||||
|
var invalidCharacter = /[^\w.-\s()]/g.exec(file.name);
|
||||||
|
if (invalidCharacter) {
|
||||||
|
throw new Error('Special characters, such as "' + invalidCharacter + '", are not allowed in the file name.');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
// validation function that checks to make sure the claim name is not already claimed
|
||||||
function validateSubmission(stagedFiles, name){
|
|
||||||
// make sure only 1 file was selected
|
|
||||||
if (!stagedFiles) {
|
|
||||||
throw new FileError("Please select a file");
|
|
||||||
} else if (stagedFiles.length > 1) {
|
|
||||||
throw new FileError("Only one file is allowed at a time");
|
|
||||||
}
|
|
||||||
// validate 'name' field
|
|
||||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
|
||||||
if (invalidCharacters) {
|
|
||||||
throw new NameError(invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, and "-" only.');
|
|
||||||
} else if (name.length < 1) {
|
|
||||||
throw new NameError("You must enter a name for your claim");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function validateClaimName (name) {
|
function validateClaimName (name) {
|
||||||
var deferred = new Promise(function(resolve, reject) {
|
var deferred = new Promise(function(resolve, reject) {
|
||||||
|
// validate the characters in the 'name' field
|
||||||
|
if (name.length < 1) {
|
||||||
|
reject(new NameError("You must enter a name for your claim"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var invalidCharacters = /[^A-Za-z0-9,-]/g.exec(name);
|
||||||
|
if (invalidCharacters) {
|
||||||
|
reject(new NameError('"' + invalidCharacters + '" is not allowed. Use only the following characters: A-Z, a-z, 0-9, and "-"'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// make sure the claim name is still available
|
||||||
var xhttp;
|
var xhttp;
|
||||||
xhttp = new XMLHttpRequest();
|
xhttp = new XMLHttpRequest();
|
||||||
xhttp.open('GET', '/api/isClaimAvailable/' + name, true);
|
xhttp.open('GET', '/api/isClaimAvailable/' + name, true);
|
||||||
|
@ -54,7 +54,7 @@ function validateClaimName (name) {
|
||||||
if (this.response == true) {
|
if (this.response == true) {
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
reject("That name has already been claimed by spee.ch. Please choose a different name.");
|
reject( new NameError("That name has already been claimed by spee.ch. Please choose a different name."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reject("request to check claim name failed with status:" + this.status);
|
reject("request to check claim name failed with status:" + this.status);
|
||||||
|
@ -65,41 +65,88 @@ function validateClaimName (name) {
|
||||||
});
|
});
|
||||||
return deferred;
|
return deferred;
|
||||||
}
|
}
|
||||||
|
// validation function which checks all aspects of the publish submission
|
||||||
|
function validateSubmission(stagedFiles, name){
|
||||||
|
var deferred = new Promise(function (resolve, reject) {
|
||||||
|
// make sure only 1 file was selected
|
||||||
|
if (!stagedFiles) {
|
||||||
|
reject(new FileError("Please select a file"));
|
||||||
|
} else if (stagedFiles.length > 1) {
|
||||||
|
reject(new FileError("Only one file is allowed at a time"));
|
||||||
|
}
|
||||||
|
// validate the file's name, type, and size
|
||||||
|
try {
|
||||||
|
validateFile(stagedFiles[0]);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
// make sure the claim name has not already been used
|
||||||
|
validateClaimName(name)
|
||||||
|
.then(function() {
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
reject(error);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
/* regular publish helper functions */
|
/* publish helper functions */
|
||||||
|
|
||||||
|
// When a file is selected for publish, validate that file and
|
||||||
|
// stage it so it will be ready when the publish button is clicked.
|
||||||
function previewAndStageFile(selectedFile){
|
function previewAndStageFile(selectedFile){
|
||||||
var previewHolder = document.getElementById('asset-preview-holder');
|
var previewHolder = document.getElementById('asset-preview-holder');
|
||||||
var dropzone = document.getElementById('drop-zone');
|
var dropzone = document.getElementById('drop-zone');
|
||||||
var previewReader = new FileReader();
|
var previewReader = new FileReader();
|
||||||
var nameInput = document.getElementById('publish-name');
|
var nameInput = document.getElementById('publish-name');
|
||||||
// validate the file
|
// validate the file's name, type, and size
|
||||||
try {
|
try {
|
||||||
validateFile(selectedFile);
|
validateFile(selectedFile);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showError('input-error-file-selection', error.message);
|
showError('input-error-file-selection', error.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// set the preview
|
// set the image preview, if a preview was provided
|
||||||
if (selectedFile.type === 'video/mp4') {
|
if (selectedFile.type !== 'video/mp4') {
|
||||||
|
|
||||||
} else {
|
|
||||||
previewReader.readAsDataURL(selectedFile);
|
previewReader.readAsDataURL(selectedFile);
|
||||||
previewReader.onloadend = function () {
|
previewReader.onloadend = function () {
|
||||||
dropzone.style.display = 'none';
|
dropzone.style.display = 'none';
|
||||||
previewHolder.style.display = 'block';
|
previewHolder.style.display = 'block';
|
||||||
previewHolder.innerHTML = '<img width="100%" src="' + previewReader.result + '" alt="image preview"/>';
|
previewHolder.innerHTML = '<img width="100%" src="' + previewReader.result + '" alt="image preview"/>';
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// set the name input value to the image name if none is set yet
|
// set the name input value to the image name if none is set yet
|
||||||
if (nameInput.value === "") {
|
if (nameInput.value === "") {
|
||||||
nameInput.value = selectedFile.name.substring(0, selectedFile.name.indexOf('.'));
|
var filename = selectedFile.name.substring(0, selectedFile.name.indexOf('.'))
|
||||||
|
filename = filename.replace(/\s+/g, '-');
|
||||||
|
nameInput.value = filename;
|
||||||
}
|
}
|
||||||
// store the selected file for upload
|
// store the selected file for upload
|
||||||
stagedFiles = [selectedFile];
|
stagedFiles = [selectedFile];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate the publish submission and then trigger publishing.
|
||||||
|
function publishSelectedImage(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var name = document.getElementById('publish-name').value;
|
||||||
|
validateSubmission(stagedFiles, name)
|
||||||
|
.then(function() {
|
||||||
|
uploader.submitFiles(stagedFiles);
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
if (error.name === 'FileError'){
|
||||||
|
showError('input-error-file-selection', error.message);
|
||||||
|
} else if (error.name === 'NameError') {
|
||||||
|
showError('input-error-claim-name', error.message);
|
||||||
|
} else {
|
||||||
|
showError('input-error-publish-submit', error.message);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
/* drop zone functions */
|
/* drop zone functions */
|
||||||
|
|
||||||
function drop_handler(ev) {
|
function drop_handler(ev) {
|
||||||
|
@ -128,51 +175,3 @@ function dragend_handler(ev) {
|
||||||
ev.dataTransfer.clearData();
|
ev.dataTransfer.clearData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* meme publish functions */
|
|
||||||
|
|
||||||
function startPublish() {
|
|
||||||
//download the image
|
|
||||||
var dataUrl = canvas.toDataURL('image/jpeg'); // canvas defined in memeDraw.js
|
|
||||||
var blob = dataURItoBlob(dataUrl)
|
|
||||||
var fileName = nameInput.value + ".jpeg"; //note: need to dynamically grab type
|
|
||||||
var file = new File([blob], fileName, {type: 'image/jpeg', lastModified: Date.now()});
|
|
||||||
stageAndPublish(file);
|
|
||||||
};
|
|
||||||
|
|
||||||
function stageAndPublish(file) {
|
|
||||||
var name = nameInput.value;
|
|
||||||
var invalidCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
|
||||||
// validate 'name'
|
|
||||||
if (invalidCharacters) {
|
|
||||||
showError('input-error-claim-name', invalidCharacters + ' is not allowed. A-Z, a-z, 0-9, "_" and "-" only.');
|
|
||||||
return;
|
|
||||||
} else if (name.length < 1) {
|
|
||||||
showError('input-error-claim-name', 'You must enter a name for your claim');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// stage files
|
|
||||||
stagedFiles = [file]; // stores the selected file for
|
|
||||||
// make sure a file was selected
|
|
||||||
if (stagedFiles) {
|
|
||||||
// make sure only 1 file was selected
|
|
||||||
if (stagedFiles.length < 1) {
|
|
||||||
showError('input-error-file-selection', 'A file is needed');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// make sure the content type is acceptable
|
|
||||||
switch (stagedFiles[0].type) {
|
|
||||||
case "image/png":
|
|
||||||
case "image/jpeg":
|
|
||||||
case "image/gif":
|
|
||||||
case "video/mp4":
|
|
||||||
uploader.submitFiles(stagedFiles);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
showError('input-error-publish-submit', 'Only .png, .jpeg, .gif, and .mp4 files are currently supported');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showError('input-error-file-selection', 'Please select a file');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,52 @@
|
||||||
|
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
<script src="/siofu/client.js"></script>
|
<script src="/siofu/client.js"></script>
|
||||||
|
|
||||||
<script src="/assets/js/generalFunctions.js"></script>
|
<script src="/assets/js/generalFunctions.js"></script>
|
||||||
<script src="/assets/js/publishFunctions.js"></script>
|
<script src="/assets/js/publishFunctions.js"></script>
|
||||||
<script src="/assets/js/index.js"></script>
|
<script typ="text/javascript">
|
||||||
|
// define variables
|
||||||
|
var socket = io();
|
||||||
|
var uploader = new SocketIOFileUpload(socket);
|
||||||
|
var stagedFiles = null;
|
||||||
|
/* socketio-file-upload listeners */
|
||||||
|
uploader.addEventListener('start', function(event){
|
||||||
|
var name = document.getElementById('publish-name').value;
|
||||||
|
var license = document.getElementById('publish-license').value;
|
||||||
|
var nsfw = document.getElementById('publish-nsfw').checked;
|
||||||
|
event.file.meta.name = name;
|
||||||
|
event.file.meta.license = license;
|
||||||
|
event.file.meta.nsfw = nsfw;
|
||||||
|
event.file.meta.type = stagedFiles[0].type;
|
||||||
|
// re-set the html in the publish area
|
||||||
|
document.getElementById('publish-active-area').innerHTML = '<div id="publish-status"></div><div id="progress-bar"></div>';
|
||||||
|
// start a progress animation
|
||||||
|
createProgressBar(document.getElementById('progress-bar'), 12);
|
||||||
|
// google analytics
|
||||||
|
ga('send', {
|
||||||
|
hitType: 'event',
|
||||||
|
eventCategory: 'publish',
|
||||||
|
eventAction: name
|
||||||
|
});
|
||||||
|
});
|
||||||
|
uploader.addEventListener('progress', function(event){
|
||||||
|
var percent = event.bytesLoaded / event.file.size * 100;
|
||||||
|
updatePublishStatus('File is ' + percent.toFixed(2) + '% loaded to the server');
|
||||||
|
});
|
||||||
|
/* socket.io message listeners */
|
||||||
|
socket.on('publish-status', function(msg){
|
||||||
|
updatePublishStatus(msg);
|
||||||
|
});
|
||||||
|
socket.on('publish-failure', function(msg){
|
||||||
|
document.getElementById('publish-active-area').innerHTML = '<p> --(✖╭╮✖)→ </p><p>' + JSON.stringify(msg) + '</p><strong>For help, post the above error text in the #speech channel on the <a href="https://lbry.slack.com/" target="_blank">lbry slack</a></strong>';
|
||||||
|
});
|
||||||
|
socket.on('publish-complete', function(msg){
|
||||||
|
var publishResults;
|
||||||
|
var showUrl = '/show/' + msg.name + '/' + msg.result.claim_id;
|
||||||
|
// build new publish area
|
||||||
|
publishResults = '<p>Your publish is complete! You are being redirected to it now.</p>';
|
||||||
|
publishResults += '<p><a target="_blank" href="' + showUrl + '">If you do not get redirected, click here.</a></p>';
|
||||||
|
// update publish area
|
||||||
|
document.getElementById('publish-active-area').innerHTML = publishResults;
|
||||||
|
window.location.href = showUrl;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
<script>
|
<script>
|
||||||
var elem = document.querySelector('.grid');
|
var elem = document.querySelector('.grid');
|
||||||
var trendingImages = document.querySelectorAll('.trending-image');
|
var trendingImages = document.querySelectorAll('.trending-image');
|
||||||
console.log(trendingImages)
|
|
||||||
var trendingVideos = document.querySelectorAll('.trending-video');
|
var trendingVideos = document.querySelectorAll('.trending-video');
|
||||||
var msnry = new Masonry( elem, {
|
var msnry = new Masonry( elem, {
|
||||||
itemSelector: '.grid-item'
|
itemSelector: '.grid-item'
|
||||||
|
@ -34,14 +33,12 @@
|
||||||
// after images are loaded, reset layout
|
// after images are loaded, reset layout
|
||||||
for (var i = 0; i < trendingVideos.length; i++) {
|
for (var i = 0; i < trendingVideos.length; i++) {
|
||||||
trendingImages[i].addEventListener('load', function(){
|
trendingImages[i].addEventListener('load', function(){
|
||||||
console.log('image loaded');
|
|
||||||
msnry.layout();
|
msnry.layout();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// after videos are loaded, reset layout
|
// after videos are loaded, reset layout
|
||||||
for (var i = 0; i < trendingVideos.length; i++) {
|
for (var i = 0; i < trendingVideos.length; i++) {
|
||||||
trendingVideos[i].addEventListener('loadeddata', function(){
|
trendingVideos[i].addEventListener('loadeddata', function(){
|
||||||
console.log('video loaded');
|
|
||||||
msnry.layout();
|
msnry.layout();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue