From 740a6fa59649fc6edced392dbbdcd74363f489c5 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 28 Jul 2013 13:52:17 +0300 Subject: [PATCH] Add partially-functioning getfile command --- AndroidManifest.xml | 1 + res/values/strings.xml | 7 ++ src/ro/ieval/fonbot/Heavy.java | 215 +++++++++++++++++++++++++-------- src/ro/ieval/fonbot/Utils.java | 18 ++- 4 files changed, 191 insertions(+), 50 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index cc92df3..4ae622d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -34,6 +34,7 @@ + diff --git a/res/values/strings.xml b/res/values/strings.xml index 2924533..8b4dd01 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -466,4 +466,11 @@ The help command can be used to get a list of commands and help for them. Exampl Toggling torch state… Your device has been turned on Cannot parse camera number + + Usage: getfile filename url\n + Downloads the given url to the file described by the given filename\n + Example: getfile /storage/sdcard1 http://ieval.ro/ + + Error opening file %1$s (%2$s) + File received diff --git a/src/ro/ieval/fonbot/Heavy.java b/src/ro/ieval/fonbot/Heavy.java index 85aff17..cac04f7 100644 --- a/src/ro/ieval/fonbot/Heavy.java +++ b/src/ro/ieval/fonbot/Heavy.java @@ -5,13 +5,18 @@ import static ro.ieval.fonbot.Utils.toNonNull; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.FileNotFoundException; +import java.io.InputStream; import java.io.IOException; +import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; +import java.net.URL; +import java.net.URLConnection; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; import java.util.ArrayList; @@ -287,6 +292,153 @@ final class Heavy { } } + /** + * ExecutableRunnable that uploads a file to a given host and port, netcat-style + * + * @author Marius Gavrilescu + */ + private static final class NcfileExecutableRunnable extends ExecutableRunnable { + private final Context context; + private final Address replyTo; + private final String filename; + private final String hostname; + private final int port; + + /** + * Construct a NcfileExecutableRunnable + * + * @param context Context instance + * @param replyTo reply Address + * @param filename filename to upload + * @param hostname hostname to upload to + * @param port port to upload to + */ + NcfileExecutableRunnable(final Context context, final Address replyTo, final String filename, final String hostname, final int port){ + this.context=context; + this.replyTo=replyTo; + this.filename=filename; + this.hostname=hostname; + this.port=port; + } + + @Override public void run(){ + final FileChannel in; + final SocketChannel sock; + try{ + in=new FileInputStream(filename).getChannel(); + } catch (final FileNotFoundException e){ + Utils.sendMessage(context, replyTo, file_not_found, filename); + return; + } + + try{ + sock = SocketChannel.open(new InetSocketAddress(hostname, port)); + } catch (final IOException e){ + Utils.sendMessage(context, replyTo, toNonNull(context.getString(cannot_connect_to_host_on_port, hostname, Integer.valueOf(port)))); + try { + in.close(); + } catch (IOException ex) { + //ignored + } + return; + } + + try{ + in.transferTo(0, in.size(), sock); + } catch (final IOException e){ + Utils.sendMessage(context, replyTo, toNonNull(context.getString(io_error, e.getMessage()))); + } finally { + try{ + in.close(); + } catch (IOException e){ + //ignored + } + try{ + sock.close(); + } catch(IOException e){ + //ignored + } + } + Utils.sendMessage(context, replyTo, file_sent); + } + } + + /** + * ExecutableRunnable that downloads a file from a given host and port, netcat-style + * + * @author Marius Gavrilescu + */ + private static final class GetfileExecutableRunnable extends ExecutableRunnable { + private final Context context; + private final Address replyTo; + private final String filename; + private final String hostname; + private final int port; + + /** + * Construct a GetfileExecutableRunnable + * + * @param context Context instance + * @param replyTo reply Address + * @param filename filename to save to + * @param hostname hostname to download from + * @param port port to download from + */ + GetfileExecutableRunnable(final Context context, final Address replyTo, final String filename, final String hostname, final int port){ + this.context=context; + this.replyTo=replyTo; + this.filename=filename; + this.hostname=hostname; + this.port=port; + } + + @Override public void run(){ + final InputStream in; + final FileOutputStream out; + final Socket sock; + try{ + out=new FileOutputStream(filename); + } catch (final IOException e){ + Utils.sendMessage(context, replyTo, error_opening_file, filename, e.getMessage()); + return; + } + + try{ + sock = new Socket(hostname, port); + in = sock.getInputStream(); + } catch (final IOException e){ + Utils.sendMessage(context, replyTo, toNonNull(context.getString(cannot_connect_to_host_on_port, hostname, Integer.valueOf(port)))); + try { + out.close(); + } catch (IOException ex) { + //ignored + } + return; + } + + try{ + byte[] buffer=new byte[1024*1024*2]; + int nread; + while((nread = in.read(buffer)) > 0) + out.write(buffer, 0, nread); + } catch (final IOException e){ + Utils.sendMessage(context, replyTo, toNonNull(context.getString(io_error, e.getMessage()))); + } finally { + try{ + out.close(); + } catch (IOException e){ + //ignored + } + try{ + sock.close(); + } catch(IOException e){ + //ignored + } + } + Utils.sendMessage(context, replyTo, file_received); + } + } + /** * PictureCallback that sends the picture to a server. * @@ -1037,55 +1189,7 @@ final class Heavy { * @param port server port */ public static void ncfile(final Context context, final Address replyTo, final String filename,final String hostname,final int port){ - new AsyncTask() { - @Override - protected @Nullable Void doInBackground(@Nullable final Void... params) { - final FileChannel in; - try{ - in=new FileInputStream(filename).getChannel(); - } catch (final FileNotFoundException e){ - Utils.sendMessage(context, replyTo, file_not_found, filename); - return null; - } - final SocketChannel sock; - try{ - sock = SocketChannel.open(new InetSocketAddress(hostname, port)); - } catch (final IOException e){ - Utils.sendMessage(context, replyTo, toNonNull(context.getString( - cannot_connect_to_host_on_port, hostname, Integer.valueOf(port)))); - try { - in.close(); - } catch (IOException ex) { - //ignored - } - return null; - } - - try{ - in.transferTo(0, in.size(), sock); - } catch (final IOException e){ - Utils.sendMessage(context, replyTo, toNonNull(context.getString( - io_error, e.getMessage()))); - } finally { - try{ - in.close(); - } catch (IOException e){ - //ignored - } - try{ - sock.close(); - } catch(IOException e){ - //ignored - } - } - return null; - } - - @Override - protected void onPostExecute(@Nullable final Void result) { - Utils.sendMessage(context, replyTo, file_sent); - } - }.execute(); + new NcfileExecutableRunnable(context, replyTo, filename, hostname, port).execute(); } /** @@ -1790,4 +1894,17 @@ final class Heavy { context.sendBroadcast(new Intent("net.cactii.flash2.TOGGLE_FLASHLIGHT")); Utils.sendMessage(context, replyTo, toggling_torch_state); } + + /** + * Download a file from a given URL to a given filename + * + * @param context Context instance + * @param replyTo reply Address + * @param filename filename to save to + * @param hostname hostname to download from + * @param port port to download from + */ + public static void getfile(final Context context, final Address replyTo, final String filename, final String hostname, final int port){ + new GetfileExecutableRunnable(context, replyTo, filename, hostname, port).execute(); + } } diff --git a/src/ro/ieval/fonbot/Utils.java b/src/ro/ieval/fonbot/Utils.java index c425420..f37773a 100644 --- a/src/ro/ieval/fonbot/Utils.java +++ b/src/ro/ieval/fonbot/Utils.java @@ -65,7 +65,7 @@ public final class Utils { LS, RM, CONTACTS, DISABLE, ENABLE, POLL, HANGUP, ANSWER, LAUNCH, DATA, GPS, GLOCATION, REBOOT, NOTIFY, SCREENCAP, - TORCH + TORCH, GETFILE } /** @@ -986,6 +986,22 @@ public final class Utils { case TORCH: Heavy.torch(context, replyTo); break; + + case GETFILE: + if(args.length != 3){ + Heavy.help(context, replyTo, toNonNull(Command.GETFILE)); + return; + } + + final int getfilePort; + try{ + getfilePort=Integer.parseInt(args[2]); + } catch (NumberFormatException e){ + sendMessage(context, replyTo, cannot_parse_port); + break; + } + Heavy.getfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), getfilePort); + break; } } -- 2.39.2