#! /usr/bin/env runjs requireJAR('aliyun-sdk-oss-2.4.1-SNAPSHOT.jar'); requireJAR('commons-beanutils-1.8.0.jar'); requireJAR('commons-codec-1.9.jar'); requireJAR('commons-collections-3.2.1.jar'); requireJAR('commons-lang-2.5.jar'); requireJAR('commons-logging-1.2.jar'); requireJAR('ezmorph-1.0.6.jar'); requireJAR('hamcrest-core-1.1.jar'); requireJAR('httpclient-4.4.1.jar'); requireJAR('httpcore-4.4.1.jar'); requireJAR('jdom-1.1.jar'); requireJAR('json-lib-2.4-jdk15.jar'); requireJAR('maven:external.jose4j:jose4j:0.5.5'); requireJAR('maven:org.slf4j:slf4j-api:1.7.21'); var oss = require('component-oss.js'); var args = require('component-args.js'); var bytes = require('component-bytes.js'); var counter = require('component-counter.js'); var gpg = require('component-gpg-ex.js'); var File = java.io.File; var System = java.lang.System; var FileInputStream = java.io.FileInputStream; var FileOutputStream = java.io.FileOutputStream; var JsonWebKey = Packages.org.jose4j.jwk.JsonWebKey; var JsonWebEncryption = Packages.org.jose4j.jwe.JsonWebEncryption; var KeyManagementAlgorithmIdentifiers = Packages.org.jose4j.jwe.KeyManagementAlgorithmIdentifiers; var ContentEncryptionAlgorithmIdentifiers = Packages.org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers; var CounterInputStream = Packages.me.hatter.tools.commons.io.CounterInputStream; var RFile = Packages.me.hatter.tools.commons.io.RFile; var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil; var KeyValue = Packages.me.hatter.tools.commons.network.HttpRequest.KeyValue; var ListObjectsRequest = Packages.com.aliyun.oss.model.ListObjectsRequest; var AESCryptTool = Packages.me.hatter.tools.commons.security.crypt.AESCryptTool; var DefaultRollCounter = Packages.me.hatter.tools.commons.io.DefaultRollCounter; var main = () => { var start = $$.date().millis(); var parsedArgs = args.parseARGS(['noenc', 'removesourcefile']); if ((parsedArgs.args.length != 1) && (parsedArgs.args.length != 3)) { println('osssendfile.js -- upload file to playsecurity.org'); println(); println('osssendfile.js [--config config.json] list'); println('osssendfile.js [--config config.json] clear'); println('osssendfile.js [--config config.json] [--noenc] [--removesourcefile] [--jwk \'x\'] file.ext title keywords'); println('osssendfile.js [--config config.json] [--noenc] [--removesourcefile] [--jwk \'{JWK}\'] file.ext title keywords'); return; } var configJSON = null; try { var config = RFile.from(parsedArgs.values['config'] || '~/.jssp/config/osssendfile.json').string(); configJSON = JSON.parse(config); } catch (e) { println('Parse config error: ' + e); } var hasNoAccessKey = !configJSON.accessKey || !configJSON.secretKey; var hasNoOidc = !configJSON.oidc; if (!configJSON || !configJSON.bucket || !configJSON.endpoint || !configJSON.token || (hasNoAccessKey && hasNoOidc)) { println('----- Config format -----'); println('{'); println(' \"endpoint\": \"\",'); println(' \"accessKey\": \"\",'); println(' \"secretKey\": \"\",'); println(' \"bucket\": \"\",'); println(' \"token\": \"\",'); println(' \"deleteSourceFile\": false'); println('}'); println('----- OR -----'); println('{'); println(' \"endpoint\": \"\",'); println(' \"bucket\": \"\",'); println(' \"token\": \"\",'); println(' \"oidc\": {'); println(' \"sub\": \"\",'); println(' \"client_id\": \"\",'); println(' \"client_secret\": \"\"'); println(' },'); println(' \"deleteSourceFile\": false'); println('}'); return; } var stsCredential = null; if (configJSON.oidc) { var params = $$.list(); params.add(new KeyValue('client_id', configJSON.oidc.clientId)); params.add(new KeyValue('client_secret', configJSON.oidc.clientSecret)); params.add(new KeyValue('sub', configJSON.oidc.sub)); var createStsUrl = 'https://hatter.ink/oidc/create_sts.json'; var sts = $$.httpRequest().readTimeout(5 * 60 * 1000).url(createStsUrl).post(params); var stsJSON = JSON.parse(sts.toString()); if (stsJSON.status != 200) { println('Get STS failed: ' + stsJSON.message); return; } stsCredential= stsJSON.data; } var OSSClient = Packages.com.aliyun.oss.OSSClient; var client; if (stsCredential) { client = new OSSClient(configJSON.endpoint, stsCredential.accessKeyId, stsCredential.accessKeySecret, stsCredential.securityToken); } else { client = new OSSClient(configJSON.endpoint, configJSON.accessKey, configJSON.secretKey); } try { if (parsedArgs.args.length == 1) { var getSums = () => { var objectListing = client.listObjects( new ListObjectsRequest(configJSON.bucket) .withMaxKeys(100) .withPrefix('tempfiles/temp_transfer_') ); return $ARRAY(objectListing.getObjectSummaries()); }; var commandMap = { 'list': () => { var sums = getSums(); println('Find ' + sums.length + ' object(s).') sums.forEach((s) => { println("Object: " + $$.asList(s.getKey(), s.getSize(), s.getLastModified())); }); println('DONE @' + new Date()); }, 'clear': () => { var sums = getSums(); println('Find ' + sums.length + ' object(s).') sums.forEach((s) => { println("Delete object: " + $$.asList(s.getKey(), s.getSize(), s.getLastModified())); client.deleteObject(configJSON.bucket, s.getKey()); }); println('DONE @' + new Date()); }, 'null': (cmd) => { println('[ERROR] Unknown command: ' + cmd); } }; (commandMap[parsedArgs.args[0]] || commandMap['null'])(parsedArgs.args[0]); return; } var file = parsedArgs.args[0]; var title = parsedArgs.args[1]; var keywords = parsedArgs.args[2]; var ext = (file.lastIndexOf('.') > 0) ? file.substring(file.lastIndexOf('.') + 1) : null; var sendFile = $$.file(file); if (!(sendFile.exists())) { println("File not exists: " + sendFile); return; } if (!client.doesBucketExist(configJSON.bucket)) { println("Bucket NOT exists: " + configJSON.bucket); return; } var isSecure = false; var tempKey = $$.random().nextIoBytes(16); var pJwk = parsedArgs.values['jwk']; if (pJwk) { var pJwkContent = pJwk[0]; if ((pJwk[0].length == 0) || ($STR(pJwk[0]) == 'x')) { pJwkContent = gpg.decrypt('~/jwk.json.asc'); } var jwk = JsonWebKey.Factory.newJwk(pJwkContent); var senderJwe = new JsonWebEncryption(); senderJwe.setPlaintext(title); senderJwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT); senderJwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); senderJwe.setKey(jwk.getKey()); var encTitle = 'JWE:' + senderJwe.getCompactSerialization(); println('Encrypt JWE title: ' + title + ' --> ' + encTitle); title = encTitle; isSecure = true; tempKey = __.bytes.from(jwk.getKey().getEncoded()); } var isDoDefaultEnc = !parsedArgs.flags['noenc']; var sendFileTemp = sendFile; if (isDoDefaultEnc) { sendFileTemp = $$.file(file + '.tmp'); println('Encryption local file: ' + sendFile + ' --> ' + sendFileTemp + (isSecure ? ' [secure]': ' [normal]')); AESCryptTool.gcmEncrypt(tempKey.bytes()).counter(new DefaultRollCounter(sendFile.length()).prefix('Encrypting: ')).from(sendFile).to(sendFileTemp); } var newFile = 'tempfiles/temp_transfer_' + $$.date().millis() + (ext ? ('.' + ext) : ''); println('Uploading object: ' + sendFileTemp + ' --> ' + newFile + ', file size: ' + bytes.showBytes(sendFileTemp.length())); var databaseDbGpg = new FileInputStream(sendFileTemp); var counterIS = new CounterInputStream(databaseDbGpg, counter.getCounterBar(sendFileTemp.length())); client.putObject(configJSON.bucket, newFile, counterIS); println(); // var ossURL = oss.generateSignedURL(configJSON.endpoint, configJSON.accessKey, configJSON.secretKey, configJSON.bucket, newFile, 600 * 1000); var ossURL = client.generatePresignedUrl(configJSON.bucket, newFile, new java.util.Date(new java.util.Date().getTime() + 600 * 1000)).toString(); println('Object URL: ' + ossURL); println('Sending document ....'); var params = $$.list(); params.add(new KeyValue('jsonp', '1')); params.add(new KeyValue('token', configJSON.token)); params.add(new KeyValue('url', ossURL)); params.add(new KeyValue('title', title)); params.add(new KeyValue('keywords', keywords)); if (isDoDefaultEnc) { if (isSecure) { params.add(new KeyValue('jwe_secure', "true")); params.add(new KeyValue('real_length', sendFile.length())); params.add(new KeyValue('real_sha256', __.rfile.from(sendFile).digest(__.digests.sha256()).asHex())); } else { params.add(new KeyValue('encryption', tempKey.asBase64())); } } var res = $$.httpRequest().readTimeout(5 * 60 * 1000).url('https://playsecurity.org/doc/addDoc.jsonp').post(params); println('Add doc result: ' + res); var resJSON = JSON.parse(res.toString()); if (resJSON.status == 200) { println("Deleteing object: " + newFile); client.deleteObject(configJSON.bucket, newFile); } else { println("Object is not deleted: " + newFile); } if (isDoDefaultEnc) { sendFileTemp.delete(); } var deleteSourceFile = configJSON.deleteSourceFile || parsedArgs.flags['removesourcefile'] || false; if (deleteSourceFile) { println('Delete file: ' + sendFile); sendFile.delete(); } println('DONE @' + new Date()); } catch (e) { println('OSS Error: ' + e); } finally { client.shutdown(); } }; main();