diff --git a/eeprom.js b/eeprom.js new file mode 100644 index 0000000..aa6bd41 --- /dev/null +++ b/eeprom.js @@ -0,0 +1,185 @@ +var EEPROM = function(srcId, endpoint, authorization) { + this.srcId = parseInt(srcId); + this.setEndpoint(endpoint); + this.setAuthorization(authorization); +}; +EEPROM.prototype.setEndpoint = function(endpoint) { + this.endpoint = endpoint.toString(); +}; +EEPROM.prototype.setAuthorization = function(authorization) { + this.authorization = authorization.toString(); +}; +EEPROM.prototype.deleteUpload = function(fileInfo) { + return new EEPROM.EEPROMDeleteTask( + this.authorization, + fileInfo + ); +}; +EEPROM.prototype.createUpload = function(file) { + return new EEPROM.EEPROMUploadTask( + this.srcId, + this.endpoint, + this.authorization, + file + ); +}; +EEPROM.ERR_GENERIC = 'generic'; // Generic error, no further details +EEPROM.ERR_INVALID = 'invalid'; // Request is invalid +EEPROM.ERR_AUTH = 'auth'; // Auth token expired +EEPROM.ERR_ACCESS = 'access'; // Barred from uploading +EEPROM.ERR_DMCA = 'dmca'; // DMCA takedown +EEPROM.ERR_GONE = 'gone'; // Invalid endpoint +EEPROM.ERR_SERVER = 'server'; // Server error +EEPROM.ERR_SIZE = 'size'; // Too large + +EEPROM.EEPROMFile = function(fileInfo) { + // A merge operation woulda been neat. + this.id = (fileInfo.id || '').toString(); + this.url = (fileInfo.url || '').toString(); + this.urlf = (fileInfo.urlf || '').toString(); + this.thumb = (fileInfo.thumb || '').toString(); + this.name = (fileInfo.name || '').toString(); + this.type = (fileInfo.type || '').toString(); + this.size = parseInt(fileInfo.size || 0); + this.user = parseInt(fileInfo.user || 0); + this.hash = (fileInfo.hash || '').toString(); + this.created = (fileInfo.created || null); + this.accessed = (fileInfo.accessed || null); + this.expires = (fileInfo.expires || null); + this.deleted = (fileInfo.deleted || null); + this.dmca = (fileInfo.dmca || null); +}; +EEPROM.EEPROMFile.prototype.isImage = function() { return this.type.indexOf('image/') === 0; }; +EEPROM.EEPROMFile.prototype.isAudio = function() { return this.type.indexOf('audio/') === 0; }; +EEPROM.EEPROMFile.prototype.isVideo = function() { return this.type.indexOf('video/') === 0; }; + +EEPROM.EEPROMDeleteTask = function(authorization, fileInfo) { + var _self = this; + this.authorization = authorization; + this.fileInfo = fileInfo; + this.xhr = new XMLHttpRequest; + this.xhr.addEventListener('readystatechange', function() { + if(this.readyState !== 4) + return; + + if(this.status !== 204) { + _self.errorCode = EEPROM.ERR_GENERIC; + + switch(this.status) { + case 401: + _self.errorCode = EEPROM.ERR_AUTH; + break; + case 403: + _self.errorCode = EEPROM.ERR_ACCESS; + break; + case 404: + case 410: + _self.errorCode = EEPROM.ERR_GONE; + break; + case 500: + case 503: + _self.errorCode = EEPROM.ERR_SERVER; + break; + } + + if(_self.onFailure) + _self.onFailure(_self.errorCode); + return; + } + + if(_self.onSuccess) + _self.onSuccess(); + }); +}; +EEPROM.EEPROMDeleteTask.prototype.onSuccess = undefined; +EEPROM.EEPROMDeleteTask.prototype.onFailure = undefined; +EEPROM.EEPROMDeleteTask.prototype.start = function() { + this.xhr.open('DELETE', this.fileInfo.urlf); + this.xhr.setRequestHeader('Authorization', this.authorization); + this.xhr.send(); +}; + +EEPROM.EEPROMUploadTask = function(srcId, endpoint, authorization, file) { + var _self = this; + + this.aborted = false; + this.endpoint = endpoint; + this.authorization = authorization; + this.xhr = new XMLHttpRequest; + this.formData = new FormData; + this.formData.append('src', srcId); + this.formData.append('file', file); + + var reportUploadProgress = function(ev) { + if(_self.onProgress) + _self.onProgress(new EEPROM.EEPROMUploadTask.EEPROMUploadTaskProgress(ev.loaded, ev.total)); + }; + + this.xhr.upload.addEventListener('loadstart', reportUploadProgress); + this.xhr.upload.addEventListener('progress', reportUploadProgress); + this.xhr.upload.addEventListener('load', reportUploadProgress); + + this.xhr.addEventListener('readystatechange', function() { + if(this.readyState !== 4) + return; + + if(this.status !== 201) { + _self.failureResponse = { + userAborted: _self.aborted, + error: EEPROM.ERR_GENERIC, + }; + + switch(this.status) { + case 400: + case 405: + _self.failureResponse.error = EEPROM.ERR_INVALID; + break; + case 401: + _self.failureResponse.error = EEPROM.ERR_AUTH; + break; + case 403: + _self.failureResponse.error = EEPROM.ERR_ACCESS; + break; + case 404: + case 410: + _self.failureResponse.error = EEPROM.ERR_GONE; + break; + case 451: + _self.failureResponse.error = EEPROM.ERR_DMCA; + break; + case 413: + _self.failureResponse.error = EEPROM.ERR_SIZE; + _self.failureResponse.maxSize = parseInt(this.getResponseHeader('X-EEPROM-Max-Size')); + break; + case 500: + case 503: + _self.failureResponse.error = EEPROM.ERR_SERVER; + break; + } + + if(_self.onFailure) + _self.onFailure(_self.failureResponse); + return; + } + + _self.fileInfo = new EEPROM.EEPROMFile(JSON.parse(this.responseText)); + + if(_self.onComplete) + _self.onComplete(_self.fileInfo); + }); +}; +EEPROM.EEPROMUploadTask.EEPROMUploadTaskProgress = function(loaded, total) { + this.progress = Math.ceil(((this.loaded = loaded) / (this.total = total)) * 100); +}; +EEPROM.EEPROMUploadTask.prototype.onComplete = undefined; +EEPROM.EEPROMUploadTask.prototype.onFailure = undefined; +EEPROM.EEPROMUploadTask.prototype.onProgress = undefined; +EEPROM.EEPROMUploadTask.prototype.abort = function() { + this.aborted = true; + this.xhr.abort(); +}; +EEPROM.EEPROMUploadTask.prototype.start = function() { + this.xhr.open('POST', this.endpoint); + this.xhr.setRequestHeader('Authorization', this.authorization); + this.xhr.send(this.formData); +}; diff --git a/public/index.php b/public/index.php index 44fed4e..60b2d99 100644 --- a/public/index.php +++ b/public/index.php @@ -280,6 +280,12 @@ if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})\.json/?$#', $reqPath, $matches)) { return; } +if($reqPath === '/eeprom.js' && is_file(PRM_ROOT . '/eeprom.js')) { + header('Content-Type: application/javascript; charset=utf-8'); + echo file_get_contents(PRM_ROOT . '/eeprom.js'); + return; +} + header('Content-Type: text/plain; charset=us-ascii'); if($reqPath === '/' || $reqPath === '/stats' || $reqPath === '/html') {