diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e51bc30 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +.gradle/* diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..93413ef --- /dev/null +++ b/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'groovy' +} + +repositories { + maven { + url 'http://127.0.0.1:8081/repository/maven-all-uci/' + } +} + +dependencies { + testCompile 'org.codehaus.groovy:groovy-all:2.4.8' + testCompile "org.spockframework:spock-core:1.1-groovy-2.4-rc-2" + compile 'org.codehaus.groovy:groovy-all:2.4.8' + compile 'javax.mail:mail:1.4.1' + compile 'org.apache.httpcomponents:httpclient:4.5.5' + compile 'org.apache.httpcomponents:httpmime:4.3.1' + compile 'commons-validator:commons-validator:1.4.0' +} + +task fatjar(type: Jar) { + manifest { + attributes 'Main-Class': 'org.iroko.transfer.Main' + } + from { + configurations + .runtime + .collect { it.isDirectory() ? it : zipTree(it) } + } + with jar +} diff --git a/src/main/groovy/org/iroko/transfer/ArgsParser.groovy b/src/main/groovy/org/iroko/transfer/ArgsParser.groovy new file mode 100644 index 0000000..589ad90 --- /dev/null +++ b/src/main/groovy/org/iroko/transfer/ArgsParser.groovy @@ -0,0 +1,42 @@ +package org.iroko.transfer + +import java.io.File +import org.apache.commons.validator.EmailValidator + +class ArgsParser { + + String FILE_STATE = '-F' + String EMAIL_STATE = '-E' + def files = [] + def emails = [] + def errors = [] + + ArgsParser(def args) { + def state + for (arg in args) { + if (arg == FILE_STATE || arg == EMAIL_STATE) { + state = arg + } else if (state && state == FILE_STATE) { + if (arg[0] == '~') { + arg = arg.replace('~', System.getProperty('user.home')) + } + File argFile = new File(arg); + if (!argFile.exists()) { + errors.add("File ${argFile.getName()} not exists !!!") + } else { + files.add(argFile) + } + } else if (state && state == EMAIL_STATE) { + if (!EmailValidator.getInstance().isValid(arg)) { + errors.add("E-mail ${arg} is wrong !!!") + } else { + emails.add(arg) + } + } + } + } + + def hasErrors() { + errors.size > 0 + } +} diff --git a/src/main/groovy/org/iroko/transfer/ConfigReader.groovy b/src/main/groovy/org/iroko/transfer/ConfigReader.groovy new file mode 100644 index 0000000..fdb3ccd --- /dev/null +++ b/src/main/groovy/org/iroko/transfer/ConfigReader.groovy @@ -0,0 +1,21 @@ +package org.iroko.transfer + +import java.io.File +import java.io.FileReader +import java.util.Properties + +class ConfigReader { + + Properties props + + ConfigReader() throws FileNotFoundException { + File configFile = new File("${System.getProperty('user.home')}/.config/transfer-cli/transfer.properties") + FileReader fr = new FileReader(configFile) + props = new Properties() + props.load(fr) + } + + def getProps() { + props + } +} diff --git a/src/main/groovy/org/iroko/transfer/EmailShare.groovy b/src/main/groovy/org/iroko/transfer/EmailShare.groovy new file mode 100644 index 0000000..5c8e597 --- /dev/null +++ b/src/main/groovy/org/iroko/transfer/EmailShare.groovy @@ -0,0 +1,46 @@ +package org.iroko.transfer + +import java.util.Properties +import javax.mail.Message +import javax.mail.MessagingException +import javax.mail.PasswordAuthentication +import javax.mail.Session +import javax.mail.Transport +import javax.mail.internet.InternetAddress +import javax.mail.internet.MimeMessage + + +class EmailShare { + + Session session + List emails + Properties properties + + EmailShare(Properties properties, List emails) { + session = Session.getInstance(properties, + new javax.mail.Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(properties.get('username'), properties.get('password')) + } + }) + this.emails = emails + this.properties = properties + } + + def share(shareUrl) { + try { + Message message = new MimeMessage(session) + message.setFrom(new InternetAddress(properties.get('email'))) + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(emails.join(','))) + message.setSubject("Transfer download link") + message.setText("${shareUrl}\n\nThe link is alive for 14 days") + + Transport.send(message) + + System.out.println("Done: Emails delivered") + + } catch (MessagingException e) { + throw new MessagingException(e) + } + } +} diff --git a/src/main/groovy/org/iroko/transfer/Main.groovy b/src/main/groovy/org/iroko/transfer/Main.groovy new file mode 100644 index 0000000..70fea96 --- /dev/null +++ b/src/main/groovy/org/iroko/transfer/Main.groovy @@ -0,0 +1,38 @@ +package org.iroko.transfer + +import java.util.Properties + +class Main { + + static main(args) { + + try{ + ConfigReader config = new ConfigReader() + + def props = config.props + + ArgsParser argsParser = new ArgsParser(args) + + def shareUrl + + if (argsParser.hasErrors()) { + argsParser.errors.each {println it} + } else { + if (argsParser.files.size > 0) { + Transfer transfer = new Transfer(argsParser.files) + shareUrl = transfer.sendFiles() + } + + if (argsParser.emails.size > 0 && shareUrl) { + EmailShare emailShare = new EmailShare(props, argsParser.emails) + emailShare.share(shareUrl) + } + + println shareUrl + } + }catch (FileNotFoundException e) { + println "Config file not found !!" + } + } + +} diff --git a/src/main/groovy/org/iroko/transfer/Transfer.groovy b/src/main/groovy/org/iroko/transfer/Transfer.groovy new file mode 100644 index 0000000..d30997c --- /dev/null +++ b/src/main/groovy/org/iroko/transfer/Transfer.groovy @@ -0,0 +1,60 @@ +package org.iroko.transfer + +import org.apache.http.HttpEntity +import org.apache.http.HttpResponse +import org.apache.http.HttpVersion +import org.apache.http.client.HttpClient +import org.apache.http.client.methods.HttpPost +import org.apache.http.entity.mime.MultipartEntity +import org.apache.http.entity.mime.content.ContentBody +import org.apache.http.entity.mime.content.FileBody +import org.apache.http.impl.client.DefaultHttpClient +import org.apache.http.params.CoreProtocolPNames +import org.apache.http.util.EntityUtils + +class Transfer { + + HttpClient httpclient + MultipartEntity mpEntity + HttpPost httppost + String URL = "https://transfer.sh" + List files + + Transfer(List files) { + httpclient = new DefaultHttpClient() + httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1) + httppost = new HttpPost(URL) + this.files = files + } + + def sendFiles() { + def transferKey + + MultipartEntity mpEntity = new MultipartEntity() + + files.each {mpEntity.addPart("file", new FileBody(it))} + + httppost.setEntity(mpEntity); + System.out.println("executing request " + httppost.getRequestLine()) + HttpResponse response = httpclient.execute(httppost) + HttpEntity resEntity = response.getEntity() + + println "${response.getStatusLine()}: Files uploaded" + if (resEntity != null) { + def responseStr = EntityUtils.toString(resEntity) + transferKey = responseStr.split('/')[3] + } + if (resEntity != null) { + resEntity.consumeContent() + } + + httpclient.getConnectionManager().shutdown() + + buildDownloadLink(transferKey, files) + } + + def buildDownloadLink(String key, List files) { + def filesPathGroup = files.collect {"${key}/${it.getName()}"} + "${URL}/(${filesPathGroup.join(',')}).zip" + } +} diff --git a/src/test/groovy/org/iroko/transfer/ArgsParser.groovy b/src/test/groovy/org/iroko/transfer/ArgsParser.groovy new file mode 100644 index 0000000..06e5888 --- /dev/null +++ b/src/test/groovy/org/iroko/transfer/ArgsParser.groovy @@ -0,0 +1,25 @@ +import spock.lang.* +import org.iroko.transfer.ArgsParser + + +class ArgsParserSpec extends Specification { + def "testing Args parser with invalid e-mails"() { + when: + def args = ['-F', '~/test.file', '-E', 'bademail@'] + ArgsParser parser = new ArgsParser(args) + println parser.errors + then: + parser.hasErrors() == true + parser.errors.size == 1 + } + + def "Testing Args parser with invalid files"() { + when: + def args = ['-F', '~/test1.file', '-E', 'goodemail@gmail.com'] + ArgsParser parser = new ArgsParser(args) + println parser.errors + then: + parser.hasErrors() == true + parser.errors.size == 1 + } +} diff --git a/src/test/groovy/org/iroko/transfer/Main.groovy b/src/test/groovy/org/iroko/transfer/Main.groovy new file mode 100644 index 0000000..9b01da9 --- /dev/null +++ b/src/test/groovy/org/iroko/transfer/Main.groovy @@ -0,0 +1,9 @@ +import spock.lang.* + + +class MainSpec extends Specification { + def "testing main"() { + expect: + 1 == 1 + } +}