@sendsafely/sendsafely 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FetchRequest.js +99 -0
- package/FileUtil.js +110 -0
- package/LICENSE +490 -0
- package/SendSafely.js +197 -316
- package/package.json +4 -3
package/SendSafely.js
CHANGED
|
@@ -4,17 +4,19 @@ const window = new Window();
|
|
|
4
4
|
const self = window;
|
|
5
5
|
const sjcl = require("sjcl");
|
|
6
6
|
const crypto = require("crypto");
|
|
7
|
-
const https = require('https');
|
|
8
7
|
const fs = require('fs');
|
|
9
8
|
const openpgp = require('openpgp');
|
|
10
9
|
const $ = require("jquery")(window);
|
|
11
10
|
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
|
|
12
11
|
const path = require("path");
|
|
13
12
|
const {AnonymousRequest} = require('./Dropzone');
|
|
13
|
+
const {FileUtil} = require('./FileUtil');
|
|
14
|
+
const {FetchRequest} = require('./FetchRequest');
|
|
14
15
|
|
|
15
16
|
eval(fs.readFileSync(__dirname + '/uploadWorker.js').toString());
|
|
16
17
|
eval(fs.readFileSync(__dirname + '/keyGeneratorWorker.js').toString());
|
|
17
18
|
var eventListenerTracker = {};
|
|
19
|
+
let ssLegacyUpload = false;
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* @description The only constructor for the library.
|
|
@@ -562,7 +564,7 @@ function SendSafely(url, apiKeyId, apiKeySecret, requestAPI){
|
|
|
562
564
|
* @param {String} packageId The packageId that you are adding the file to.
|
|
563
565
|
* @param {String} keyCode The key code associated with the package.
|
|
564
566
|
* @param {String} serverSecret The server secret associated with the package.
|
|
565
|
-
* @param {List<
|
|
567
|
+
* @param {List<absoluteFilePath>} An array of absolute file path to files that are being uploaded or an array of <File> (Deprecated) that are being uploaded.
|
|
566
568
|
* @param {String} uploadType Optional Leave blank (or specify 'NODE_API').
|
|
567
569
|
* @param {function} finished function (packageId, fileId, fileSize, fileName)
|
|
568
570
|
* @fires {sendsafely#progress}
|
|
@@ -600,7 +602,7 @@ function SendSafely(url, apiKeyId, apiKeySecret, requestAPI){
|
|
|
600
602
|
* @param {String} packageId The packageId that you are adding the file to.
|
|
601
603
|
* @param {String} keyCode The key code associated with the package.
|
|
602
604
|
* @param {String} serverSecret The server secret associated with the package.
|
|
603
|
-
* @param {List<
|
|
605
|
+
* @param {List<absoluteFilePath>} An array of absolute file path to files that are being uploaded or an array of <File> (Deprecated) that are being uploaded.
|
|
604
606
|
* @param {String} uploadType Optional Leave blank (or specify 'NODE_API').
|
|
605
607
|
* @param {String} directoryId The directoryId of the directory that you want to add the files to.
|
|
606
608
|
* @param {function} finished function (packageId, fileId, fileSize, fileName)
|
|
@@ -1009,101 +1011,6 @@ function SignedRequest(eventHandler, url, apiKey, apiKeySecret, requestAPI) {
|
|
|
1009
1011
|
retryCount: 2 //Need to Implement.
|
|
1010
1012
|
})
|
|
1011
1013
|
};
|
|
1012
|
-
|
|
1013
|
-
this.getHTTPSOptionForFileUpload = function (uri, method, messageData, boundary, isEC2Proxy) {
|
|
1014
|
-
var timestamp = myself.dateString();
|
|
1015
|
-
var header = myself.apiKey + myself.apiPrefix + uri + timestamp + messageData;
|
|
1016
|
-
var signature = myself.signMessage(header);
|
|
1017
|
-
var headers = {
|
|
1018
|
-
'Content-Type': 'multipart/form-data; boundary=' + boundary,
|
|
1019
|
-
'ss-api-key':myself.apiKey,
|
|
1020
|
-
'ss-request-timestamp': timestamp,
|
|
1021
|
-
'ss-request-signature': signature,
|
|
1022
|
-
'ss-request-api': myself.requestAPI
|
|
1023
|
-
};
|
|
1024
|
-
var url = new URL(myself.url + myself.apiPrefix + uri);
|
|
1025
|
-
|
|
1026
|
-
if(!isEC2Proxy) {
|
|
1027
|
-
headers = {};
|
|
1028
|
-
url = new URL(uri);
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
var options = {
|
|
1032
|
-
hostname: url.hostname,
|
|
1033
|
-
port: url.port,
|
|
1034
|
-
path: url.pathname + url.search,
|
|
1035
|
-
headers: headers,
|
|
1036
|
-
method: method,
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
return options;
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
this.getHTTPObjForFileUpload = function (uri, messageData, boundary, a_sync) {
|
|
1043
|
-
|
|
1044
|
-
var timestamp = myself.dateString();
|
|
1045
|
-
var header = myself.apiKey + myself.apiPrefix + uri + timestamp + messageData;
|
|
1046
|
-
|
|
1047
|
-
var signature = myself.signMessage(header);
|
|
1048
|
-
|
|
1049
|
-
var xhr = new XMLHttpRequest();
|
|
1050
|
-
var url = myself.url + myself.apiPrefix + uri;
|
|
1051
|
-
|
|
1052
|
-
xhr.open('POST', url, a_sync);
|
|
1053
|
-
|
|
1054
|
-
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
|
|
1055
|
-
xhr.setRequestHeader('ss-api-key', myself.apiKey);
|
|
1056
|
-
xhr.setRequestHeader('ss-request-timestamp', timestamp);
|
|
1057
|
-
xhr.setRequestHeader('ss-request-signature', signature);
|
|
1058
|
-
xhr.setRequestHeader('ss-request-api', myself.requestAPI);
|
|
1059
|
-
|
|
1060
|
-
return xhr;
|
|
1061
|
-
};
|
|
1062
|
-
|
|
1063
|
-
this.getHTTPObjForFileDownload = function (uri, messageData) {
|
|
1064
|
-
|
|
1065
|
-
var timestamp = myself.dateString();
|
|
1066
|
-
var header = myself.apiKey + myself.apiPrefix + uri + timestamp + messageData;
|
|
1067
|
-
|
|
1068
|
-
var signature = myself.signMessage(header);
|
|
1069
|
-
|
|
1070
|
-
var xhr = new XMLHttpRequest();
|
|
1071
|
-
var url = myself.url + myself.apiPrefix + uri;
|
|
1072
|
-
|
|
1073
|
-
xhr.open('POST', url, true);
|
|
1074
|
-
|
|
1075
|
-
xhr.responseType = 'arraybuffer';
|
|
1076
|
-
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
1077
|
-
xhr.setRequestHeader('ss-api-key', myself.apiKey);
|
|
1078
|
-
xhr.setRequestHeader('ss-request-timestamp', timestamp);
|
|
1079
|
-
xhr.setRequestHeader('ss-request-signature', signature);
|
|
1080
|
-
return xhr;
|
|
1081
|
-
};
|
|
1082
|
-
|
|
1083
|
-
this.getHTTPSOptionForFileDownload = function (uri, messageData) {
|
|
1084
|
-
var timestamp = myself.dateString();
|
|
1085
|
-
var header = myself.apiKey + myself.apiPrefix + uri + timestamp + messageData;
|
|
1086
|
-
|
|
1087
|
-
var signature = myself.signMessage(header);
|
|
1088
|
-
var method = 'GET';
|
|
1089
|
-
var headers = {
|
|
1090
|
-
'Content-Type': 'application/json',
|
|
1091
|
-
'Content-Length': messageData.length,
|
|
1092
|
-
'ss-api-key':myself.apiKey,
|
|
1093
|
-
'ss-request-timestamp': timestamp,
|
|
1094
|
-
'ss-request-signature': signature
|
|
1095
|
-
};
|
|
1096
|
-
|
|
1097
|
-
var url = new URL(uri);
|
|
1098
|
-
var options = {
|
|
1099
|
-
hostname: url.hostname,
|
|
1100
|
-
port: url.port,
|
|
1101
|
-
path: url.pathname + url.search,
|
|
1102
|
-
headers: headers,
|
|
1103
|
-
method: method,
|
|
1104
|
-
}
|
|
1105
|
-
return options;
|
|
1106
|
-
}
|
|
1107
1014
|
|
|
1108
1015
|
/**
|
|
1109
1016
|
* Generates a ISO Timestamp to the nearest second
|
|
@@ -1856,7 +1763,7 @@ function CreateFileId(eventHandler, request) {
|
|
|
1856
1763
|
|
|
1857
1764
|
var postData = {};
|
|
1858
1765
|
postData['filename'] = encodeURI(fileName);
|
|
1859
|
-
postData['uploadType'] =
|
|
1766
|
+
postData['uploadType'] = 'NODE_API';
|
|
1860
1767
|
postData['parts'] = parts;
|
|
1861
1768
|
postData['filesize'] = data.size;
|
|
1862
1769
|
|
|
@@ -2569,61 +2476,42 @@ function DownloadAndDecryptFile (eventHandler, request, serverWorkerURI) {
|
|
|
2569
2476
|
};
|
|
2570
2477
|
|
|
2571
2478
|
this.downloadFile = function (endpoint, requestBody, progressEvent, finishedEvent) {
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
requestData = null;
|
|
2479
|
+
let requestData = JSON.stringify(requestBody);
|
|
2480
|
+
let request = new FetchRequest({signedRequest:false});
|
|
2481
|
+
let res = undefined;
|
|
2482
|
+
|
|
2483
|
+
if (true || !myself.ec2Proxy) {
|
|
2484
|
+
requestData = null;
|
|
2485
|
+
request = request.sendRequest(endpoint, {method: 'GET'});
|
|
2580
2486
|
} else {
|
|
2581
|
-
|
|
2487
|
+
// download failover is not supported yet.
|
|
2488
|
+
request = new FetchRequest({url: myself.request.url, apiKey: myself.request.apiKey, apiKeySecret: myself.request.apiKeySecret});
|
|
2489
|
+
request = request.sendSignedRequest({url: endpoint, HTTPMethod: 'POST', mimetype: 'application/json'}, requestData);
|
|
2582
2490
|
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
for (var i = 0; i < downloadedData.length; ++i) {
|
|
2600
|
-
formattedResponse[i] = downloadedData[i];
|
|
2601
|
-
}
|
|
2602
|
-
myself.eventHandler.raise(finishedEvent, formattedResponse);
|
|
2603
|
-
} else {
|
|
2604
|
-
// parse error from server
|
|
2605
|
-
downloadedData = JSON.parse(downloadedData.toString());
|
|
2606
|
-
raiseDownloadError(res);
|
|
2607
|
-
}
|
|
2608
|
-
});
|
|
2609
|
-
|
|
2610
|
-
}).on('error', function(err) {
|
|
2611
|
-
req.end();
|
|
2612
|
-
raiseDownloadError(err);
|
|
2491
|
+
|
|
2492
|
+
request.then(function(response) {
|
|
2493
|
+
res = response;
|
|
2494
|
+
if(isValidResponse(response)) {
|
|
2495
|
+
myself.eventHandler.raise(progressEvent, response.size);
|
|
2496
|
+
return response.arrayBuffer();
|
|
2497
|
+
} else {
|
|
2498
|
+
return response.json();
|
|
2499
|
+
}
|
|
2500
|
+
}).then(function(data){
|
|
2501
|
+
if(isValidResponse(res)) {
|
|
2502
|
+
let formattedResponse = new Uint8Array(data);
|
|
2503
|
+
myself.eventHandler.raise(finishedEvent, formattedResponse);
|
|
2504
|
+
} else {
|
|
2505
|
+
raiseDownloadError(data);
|
|
2506
|
+
}
|
|
2613
2507
|
});
|
|
2614
|
-
|
|
2615
|
-
if(myself.ec2Proxy) {
|
|
2616
|
-
req.write(requestData);
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
|
-
req.end();
|
|
2620
2508
|
|
|
2621
2509
|
function isValidResponse(res) {
|
|
2622
|
-
return res.
|
|
2510
|
+
return res.status === 200 && (res.headers.has('content-type') && !res.headers.get['content-type']?.toLowerCase().includes('application/json'));
|
|
2623
2511
|
}
|
|
2624
2512
|
|
|
2625
2513
|
function raiseDownloadError(res) {
|
|
2626
|
-
|
|
2514
|
+
let debugStr = 'Response Code: ' + res.statusCode + ', Response Text: ' + res.statusMessage + ', Error: ' + (res.message);
|
|
2627
2515
|
console.log(debugStr);
|
|
2628
2516
|
myself.eventHandler.raiseError("FAIL", "Server returned an error: " + debugStr);
|
|
2629
2517
|
}
|
|
@@ -2950,9 +2838,10 @@ function EncryptAndUploadFile (eventHandler, request) {
|
|
|
2950
2838
|
myself.getFileIDs(packageId, directoryId, keyCode, serverSecret, files, uploadType, statusCb, finished);
|
|
2951
2839
|
};
|
|
2952
2840
|
|
|
2953
|
-
this.getFileIDs = function (packageId, directoryId, keyCode, serverSecret,
|
|
2954
|
-
|
|
2955
|
-
|
|
2841
|
+
this.getFileIDs = function (packageId, directoryId, keyCode, serverSecret, filesPath, uploadType, statusCb, finished) {
|
|
2842
|
+
let files = [];
|
|
2843
|
+
myself.addEncryptionKey(packageId, serverSecret, keyCode);
|
|
2844
|
+
function handleResponse(index, parts, files, fileUtil) {
|
|
2956
2845
|
var serverFilename = (files[index].name === undefined) ? myself.defaultFileName : files[index].name;
|
|
2957
2846
|
myself.responseParser.processAjaxDataRaw(myself.createFileID(packageId, directoryId, files[index], serverFilename, parts, uploadType, myself.async), function (resp) {
|
|
2958
2847
|
if(resp.response === "SUCCESS") {
|
|
@@ -2967,11 +2856,11 @@ function EncryptAndUploadFile (eventHandler, request) {
|
|
|
2967
2856
|
if( files[index].url === undefined ) {
|
|
2968
2857
|
//Add to encrypting Queue
|
|
2969
2858
|
var filename = (files[index].name === undefined) ? myself.defaultFileName : files[index].name;
|
|
2970
|
-
myself.encrypting.push({"packageId": packageId, "directoryId": directoryId, "file":files[index], "parts": parts, "part": 1, "name": filename, "fileStart": 0, "id": resp.message});
|
|
2859
|
+
myself.encrypting.push({"packageId": packageId, "directoryId": directoryId, "file":files[index], "parts": parts, "part": 1, "name": filename, "fileStart": 0, "id": resp.message, "fileUtil": fileUtil});
|
|
2971
2860
|
|
|
2972
2861
|
var type= (directoryId === undefined) ? undefined : "directory";
|
|
2973
2862
|
//TODO: REVIEW
|
|
2974
|
-
var event = {'fileId': files[index].id
|
|
2863
|
+
var event = {'fileId': files[index].id === undefined?resp.message:files[index].id, 'filePart':files[index].part, "parts":parts, 'name': filename, 'size': files[index].size, 'packageId': packageId, 'type': type};
|
|
2975
2864
|
myself.eventHandler.raise("sendsafely.files.attached", event);
|
|
2976
2865
|
/**
|
|
2977
2866
|
* @event sendsafely.files#attached
|
|
@@ -3006,16 +2895,35 @@ function EncryptAndUploadFile (eventHandler, request) {
|
|
|
3006
2895
|
});
|
|
3007
2896
|
}
|
|
3008
2897
|
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
2898
|
+
let _loop = function _loop(i, _p) {
|
|
2899
|
+
_p = _p.then(function (_) {
|
|
2900
|
+
return new Promise(function (resolve) {
|
|
2901
|
+
let f = filesPath[i];
|
|
2902
|
+
|
|
2903
|
+
if(typeof f === 'object' && f.hasOwnProperty('size')) {
|
|
2904
|
+
ssLegacyUpload = true;
|
|
2905
|
+
let parts = 1;
|
|
2906
|
+
if(f.size > (myself.SEGMENT_SIZE/4)) {
|
|
2907
|
+
parts = 1 + Math.ceil((f.size - (myself.SEGMENT_SIZE / 4)) / myself.SEGMENT_SIZE);
|
|
2908
|
+
}
|
|
2909
|
+
handleResponse(i, parts, filesPath, null);
|
|
2910
|
+
resolve();
|
|
2911
|
+
} else {
|
|
2912
|
+
let fileUtil = new FileUtil({filePath: f, callback: function(){}});
|
|
2913
|
+
fileUtil.init().then(function(file) {
|
|
2914
|
+
files.push(file);
|
|
2915
|
+
handleResponse(i, file.totalParts, files, fileUtil);
|
|
2916
|
+
resolve();
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2919
|
+
});
|
|
2920
|
+
});
|
|
2921
|
+
p = _p;
|
|
2922
|
+
};
|
|
3016
2923
|
|
|
3017
|
-
|
|
3018
|
-
|
|
2924
|
+
for (let i = 0, p = Promise.resolve(); i < filesPath.length; i++) {
|
|
2925
|
+
_loop(i, p);
|
|
2926
|
+
}
|
|
3019
2927
|
};
|
|
3020
2928
|
|
|
3021
2929
|
this.createFileID = function(packageId, directoryId, data, fileName, parts, uploadType, async) {
|
|
@@ -3036,48 +2944,59 @@ function EncryptAndUploadFile (eventHandler, request) {
|
|
|
3036
2944
|
this.uploadPart = function (statusCb, finished) {
|
|
3037
2945
|
if(myself.encrypting.length >= 1){
|
|
3038
2946
|
var currentFile = myself.encrypting[0];
|
|
3039
|
-
while(myself.segmentsCurrentlyEncrypting < myself.MAX_CONCURRENT_ENCRYPTIONS) {
|
|
3040
|
-
if(currentFile.part === 1){
|
|
3041
|
-
var fileObj = {};
|
|
3042
|
-
var fileSegment = _slice(currentFile.file.data, 0, Math.min((myself.SEGMENT_SIZE/4), currentFile.file.size));
|
|
3043
|
-
fileObj.fileSegment = fileSegment;
|
|
3044
|
-
fileObj.id = currentFile.id;
|
|
3045
|
-
fileObj.part = currentFile.part;
|
|
3046
|
-
fileObj.parts = currentFile.parts;
|
|
3047
|
-
fileObj.name = currentFile.name;
|
|
3048
|
-
fileObj.directoryId = currentFile.directoryId;
|
|
3049
|
-
|
|
3050
|
-
myself.encrypting[0].fileStart = Math.min(myself.SEGMENT_SIZE/4, myself.encrypting[0].file.size);
|
|
3051
|
-
}
|
|
3052
|
-
else if(currentFile.part <= currentFile.parts){
|
|
3053
|
-
var fileObj = {};
|
|
3054
|
-
var fileSegment = _slice(currentFile.file.data, currentFile.fileStart, Math.min(currentFile.fileStart+(myself.SEGMENT_SIZE), currentFile.file.size));
|
|
3055
|
-
fileObj.fileSegment = fileSegment;
|
|
3056
|
-
fileObj.id = currentFile.id;
|
|
3057
|
-
fileObj.part = currentFile.part;
|
|
3058
|
-
fileObj.parts = currentFile.parts;
|
|
3059
|
-
fileObj.name = currentFile.name;
|
|
3060
|
-
//TODO: Added during merge...confirm this
|
|
3061
|
-
fileObj.directoryId = currentFile.directoryId;
|
|
3062
|
-
|
|
3063
|
-
myself.encrypting[0].fileStart = Math.min(myself.encrypting[0].fileStart+(myself.SEGMENT_SIZE), myself.encrypting[0].file.size);
|
|
3064
|
-
}
|
|
3065
|
-
else{
|
|
3066
|
-
//Finished last
|
|
3067
|
-
myself.encrypting.shift();
|
|
3068
|
-
return myself.uploadPart(statusCb, finished);
|
|
3069
|
-
}
|
|
3070
2947
|
|
|
3071
|
-
|
|
2948
|
+
if(ssLegacyUpload) {
|
|
2949
|
+
while(myself.segmentsCurrentlyEncrypting < myself.MAX_CONCURRENT_ENCRYPTIONS) {
|
|
2950
|
+
let fileSegment;
|
|
2951
|
+
|
|
2952
|
+
if(currentFile.part === 1) {
|
|
2953
|
+
fileSegment = _slice(currentFile.file.data, 0, Math.min((myself.SEGMENT_SIZE/4), currentFile.file.size))
|
|
2954
|
+
myself.encrypting[0].fileStart = Math.min(myself.SEGMENT_SIZE/4, myself.encrypting[0].file.size);
|
|
2955
|
+
} else if(currentFile.part <= currentFile.parts) {
|
|
2956
|
+
fileSegment = _slice(currentFile.file.data, currentFile.fileStart, Math.min(currentFile.fileStart+(myself.SEGMENT_SIZE) , currentFile.file.size))
|
|
2957
|
+
myself.encrypting[0].fileStart = Math.min(myself.encrypting[0].fileStart+(myself.SEGMENT_SIZE), myself.encrypting[0].file.size);
|
|
2958
|
+
} else {
|
|
2959
|
+
myself.encrypting.shift();
|
|
2960
|
+
return myself.uploadPart(statusCb, finished);
|
|
2961
|
+
}
|
|
3072
2962
|
|
|
3073
|
-
|
|
2963
|
+
readFileSegmentAndUpload(fileSegment);
|
|
2964
|
+
}
|
|
3074
2965
|
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
2966
|
+
} else {
|
|
2967
|
+
if(!currentFile.fileUtil.eof) {
|
|
2968
|
+
currentFile.fileUtil.callback = readFileSegmentAndUpload;
|
|
2969
|
+
currentFile.fileUtil.read();
|
|
2970
|
+
}
|
|
3080
2971
|
}
|
|
2972
|
+
|
|
2973
|
+
function readFileSegmentAndUpload(fileSegment) {
|
|
2974
|
+
var fileObj = {};
|
|
2975
|
+
fileObj.fileSegment = ssLegacyUpload? fileSegment : fileSegment.data;
|
|
2976
|
+
fileObj.id = currentFile.id;
|
|
2977
|
+
fileObj.part = currentFile.part;
|
|
2978
|
+
fileObj.parts = currentFile.parts;
|
|
2979
|
+
fileObj.name = currentFile.name;
|
|
2980
|
+
fileObj.directoryId = currentFile.directoryId;
|
|
2981
|
+
|
|
2982
|
+
myself.encrypting[0].part++;
|
|
2983
|
+
myself.segmentsCurrentlyEncrypting++;
|
|
2984
|
+
|
|
2985
|
+
var packageId = currentFile.packageId;
|
|
2986
|
+
var directoryId = currentFile.directoryId;
|
|
2987
|
+
myself.sendFileToWorker(fileObj, packageId, directoryId, currentFile.file.size, statusCb, finished, function(){
|
|
2988
|
+
if(ssLegacyUpload) {
|
|
2989
|
+
myself.uploadPart(statusCb, finished);
|
|
2990
|
+
} else {
|
|
2991
|
+
if(myself.segmentsCurrentlyEncrypting < myself.MAX_CONCURRENT_ENCRYPTIONS && !fileSegment.complete) {
|
|
2992
|
+
currentFile.fileUtil.read();
|
|
2993
|
+
} else if(fileSegment.complete) {
|
|
2994
|
+
myself.encrypting.shift();
|
|
2995
|
+
return myself.uploadPart(statusCb, finished);
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
});
|
|
2999
|
+
}
|
|
3081
3000
|
}
|
|
3082
3001
|
};
|
|
3083
3002
|
|
|
@@ -3151,133 +3070,95 @@ function EncryptAndUploadFile (eventHandler, request) {
|
|
|
3151
3070
|
};
|
|
3152
3071
|
|
|
3153
3072
|
this.SendPartToServer = function(requestType, messageData, boundary, filesize, encryptedFile, filename, uploadCb, a_sync, packageId, done_callback, progress_callback, retryIterator) {
|
|
3073
|
+
let fileId = messageData.fileId;
|
|
3074
|
+
let filePart = messageData.filePart;
|
|
3075
|
+
let multipart = {fileId: fileId, uploadType: 'NODE_API', filePart: filePart};
|
|
3076
|
+
let multiPartForm = createMultiPartForm(boundary, JSON.stringify(multipart), encryptedFile.file);
|
|
3077
|
+
let url = requestType.url;
|
|
3078
|
+
let method = 'POST';
|
|
3079
|
+
let contentLength = Buffer.from(multiPartForm.buffer).length;
|
|
3080
|
+
let request = new FetchRequest({url: myself.request.url, apiKey: myself.request.apiKey, apiKeySecret: myself.request.apiKeySecret});
|
|
3081
|
+
let res = undefined;
|
|
3154
3082
|
|
|
3155
|
-
var fileId = messageData.fileId;
|
|
3156
|
-
var filePart = messageData.filePart;
|
|
3157
|
-
|
|
3158
|
-
var multipart = {};
|
|
3159
|
-
multipart["fileId"] = fileId;
|
|
3160
|
-
multipart["uploadType"] = "NODE_API";
|
|
3161
|
-
multipart["filePart"] = filePart;
|
|
3162
|
-
var multiPartForm = createMultiPartForm(boundary, JSON.stringify(multipart), encryptedFile.file);
|
|
3163
|
-
var url = requestType.url;
|
|
3164
|
-
var method = "POST"
|
|
3165
|
-
var contentLength = Buffer.from(multiPartForm.buffer).length;
|
|
3166
|
-
|
|
3167
3083
|
if (!myself.ec2Proxy) {
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3084
|
+
url = myself.uploadUrls[fileId][filePart];
|
|
3085
|
+
method = "PUT";
|
|
3086
|
+
contentLength = Buffer.from(encryptedFile.file).length;
|
|
3087
|
+
request = new FetchRequest({signedRequest: false});
|
|
3088
|
+
request = request.sendRequest(url, {method: method, headers: {'Content-Length': contentLength}, body: Buffer.from(encryptedFile.file), timeout: 25000});
|
|
3089
|
+
} else {
|
|
3090
|
+
request = request.sendSignedRequest({url: url, HTTPMethod: method, mimetype: 'multipart/form-data; boundary=' + boundary, messageData: messageData}, multiPartForm.buffer);
|
|
3171
3091
|
}
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
if(
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
myself.eventHandler.raise(myself.UPLOAD_ERROR_EVENT, {error: 'AUTHENTICATION_FAILED', message: response.message});
|
|
3202
|
-
}
|
|
3203
|
-
else if( (myself.ec2Proxy && response.response == "SUCCESS") || (! myself.ec2Proxy && res.statusCode == 200) ) {
|
|
3204
|
-
//response.fileId = response.message;
|
|
3205
|
-
var discard = myself.uploading.shift();
|
|
3206
|
-
discard = null;
|
|
3207
|
-
|
|
3208
|
-
myself.eventHandler.unbind(myself.UPLOAD_ABORT_EVENT, eventId);
|
|
3209
|
-
if(encryptedFile.part == encryptedFile.parts)
|
|
3210
|
-
{
|
|
3211
|
-
if (! myself.ec2Proxy)
|
|
3212
|
-
{
|
|
3213
|
-
var counter = 0;
|
|
3214
|
-
myself.markFileComplete(packageId, fileId, a_sync, function() { done_callback(packageId, fileId, filesize, filename); }, function() { myself.eventHandler.raise(myself.SERVER_ERROR_EVENT, {error: "FILE_INCOMPLETE", message: "Your file did not upload completely. Please refresh and try again."});}, counter);
|
|
3215
|
-
}
|
|
3216
|
-
else
|
|
3217
|
-
{
|
|
3218
|
-
done_callback(packageId, fileId, filesize, filename);
|
|
3092
|
+
|
|
3093
|
+
request.then(function(response) {
|
|
3094
|
+
res = response;
|
|
3095
|
+
if(response.status !== 200) {
|
|
3096
|
+
throw new Error('retry');
|
|
3097
|
+
} else if (response.status === 200 && response.headers.has('content-type') && response.headers.get('content-type')?.toLowerCase().includes('application/json')) {
|
|
3098
|
+
return response.json();
|
|
3099
|
+
}
|
|
3100
|
+
}).then(function(responseData) {
|
|
3101
|
+
uploadCb({loaded: contentLength});
|
|
3102
|
+
let response = {response:"SERVER_ERROR", message: "A server error has occurred, please try again."};
|
|
3103
|
+
if(myself.ec2Proxy && responseData !== undefined){
|
|
3104
|
+
response = responseData;
|
|
3105
|
+
}
|
|
3106
|
+
if(myself.ec2Proxy && response.response === "LIMIT_EXCEEDED") {
|
|
3107
|
+
myself.eventHandler.raise(myself.LIMIT_EXCEEDED_EVENT, {error: response.message});
|
|
3108
|
+
} else if(myself.ec2Proxy && response.response === "AUTHENTICATION_FAILED") {
|
|
3109
|
+
myself.removeFileFromQueue(messageData.fileId);
|
|
3110
|
+
myself.eventHandler.raise(myself.UPLOAD_ERROR_EVENT, {error: 'AUTHENTICATION_FAILED', message: response.message});
|
|
3111
|
+
} else if( (myself.ec2Proxy && response.response === "SUCCESS") || (! myself.ec2Proxy && res.status === 200) ) {
|
|
3112
|
+
let discard = myself.uploading.shift();
|
|
3113
|
+
discard = null;
|
|
3114
|
+
|
|
3115
|
+
if(encryptedFile.part === encryptedFile.parts) {
|
|
3116
|
+
if (! myself.ec2Proxy) {
|
|
3117
|
+
let counter = 0;
|
|
3118
|
+
myself.markFileComplete(packageId, fileId, a_sync, function() { done_callback(packageId, fileId, filesize, filename); }, function() { myself.eventHandler.raise(myself.SERVER_ERROR_EVENT, {error: "FILE_INCOMPLETE", message: "Your file did not upload completely. Please refresh and try again."});}, counter);
|
|
3119
|
+
} else {
|
|
3120
|
+
done_callback(packageId, fileId, filesize, filename);
|
|
3219
3121
|
}
|
|
3220
|
-
}
|
|
3221
|
-
if(myself.uploading.length != 0){
|
|
3222
|
-
myself.nextUploadFile(done_callback, progress_callback);
|
|
3223
|
-
}
|
|
3224
3122
|
}
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3123
|
+
if(myself.uploading.length !== 0){
|
|
3124
|
+
myself.nextUploadFile(done_callback, progress_callback);
|
|
3125
|
+
}
|
|
3126
|
+
} else {
|
|
3127
|
+
if(myself.markedAsDeleted[messageData.fileId] === undefined) {
|
|
3128
|
+
if(retryIterator === undefined) {retryIterator = 1;}
|
|
3229
3129
|
if(retryIterator < 5) {
|
|
3230
|
-
|
|
3130
|
+
myself.SendPart(requestType, messageData, boundary, filesize, encryptedFile, filename, uploadCb, a_sync, packageId, done_callback, progress_callback, retryIterator+1)
|
|
3231
3131
|
} else {
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3132
|
+
myself.removeFileFromQueue(messageData.fileId, messageData.fileId);
|
|
3133
|
+
let error = res.status;
|
|
3134
|
+
let message = res.statusText;
|
|
3135
|
+
if(myself.ec2Proxy) {
|
|
3136
|
+
error = response.response;
|
|
3137
|
+
message = response.message;
|
|
3138
|
+
}
|
|
3139
|
+
myself.eventHandler.raise(myself.UPLOAD_ERROR_EVENT, {error: error, message: message});
|
|
3240
3140
|
}
|
|
3241
|
-
}
|
|
3242
3141
|
}
|
|
3243
|
-
}
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
myself.removeFileFromQueue(messageData.fileId, messageData.fileId);
|
|
3264
|
-
myself.eventHandler.raise(myself.UPLOAD_ERROR_EVENT, {error: err.statusMessage, message: "A server error occurred - Please try again."});
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
});
|
|
3268
|
-
|
|
3269
|
-
if (myself.ec2Proxy) {
|
|
3270
|
-
req.write(Buffer.from(multiPartForm.buffer));
|
|
3271
|
-
} else {
|
|
3272
|
-
req.write(Buffer.from(encryptedFile.file));
|
|
3273
|
-
}
|
|
3274
|
-
req.end();
|
|
3275
|
-
|
|
3276
|
-
// Add event listener so we can abort the upload if we have to.
|
|
3277
|
-
var eventId = myself.eventHandler.bind(myself.UPLOAD_ABORT_EVENT, function(data) {
|
|
3278
|
-
if(data.fileId == messageData.fileId) {
|
|
3279
|
-
req.end();
|
|
3280
|
-
}
|
|
3142
|
+
}
|
|
3143
|
+
}).catch(function(err) {
|
|
3144
|
+
if(retryIterator === undefined) {retryIterator = 1;}
|
|
3145
|
+
if(retryIterator < 5) {
|
|
3146
|
+
setTimeout(function() {
|
|
3147
|
+
myself.SendPart(requestType, messageData, boundary, filesize, encryptedFile, filename, uploadCb, a_sync, packageId, done_callback, progress_callback, retryIterator+1);
|
|
3148
|
+
}, retryIterator*1000);
|
|
3149
|
+
} else {
|
|
3150
|
+
//If we fail 5 times and are not using the proxy, flip the proxy switch and try again
|
|
3151
|
+
if (! myself.ec2Proxy ) {
|
|
3152
|
+
myself.ec2Proxy = true;
|
|
3153
|
+
retryIterator = 0;
|
|
3154
|
+
setTimeout(function() {
|
|
3155
|
+
myself.SendPart(requestType, messageData, boundary, filesize, encryptedFile, filename, uploadCb, a_sync, packageId, done_callback, progress_callback, retryIterator+1);
|
|
3156
|
+
}, retryIterator*1000);
|
|
3157
|
+
} else {
|
|
3158
|
+
myself.removeFileFromQueue(messageData.fileId, messageData.fileId);
|
|
3159
|
+
myself.eventHandler.raise(myself.UPLOAD_ERROR_EVENT, {error: err.code, message: "A server error occurred - Please try again."});
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3281
3162
|
});
|
|
3282
3163
|
}
|
|
3283
3164
|
|
package/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendsafely/sendsafely",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"main": "SendSafely.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
7
|
},
|
|
8
8
|
"author": "SendSafely",
|
|
9
|
-
"license": "",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
10
|
"description": "The SendSafely JavaScript SDK for Node.js lets you integrate SendSafely secure data transfer capabilities directly into your Node.js application.",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"jquery": "^3.4.1",
|
|
13
|
+
"make-fetch-happen": "^10.2.1",
|
|
13
14
|
"openpgp": "^4.5.5",
|
|
14
15
|
"sjcl": "^1.0.8",
|
|
15
|
-
"window": "^4.2.
|
|
16
|
+
"window": "^4.2.7",
|
|
16
17
|
"xmlhttprequest": "^1.8.0"
|
|
17
18
|
},
|
|
18
19
|
"repository": {
|