1 package com.joshuawise.dumload;
3 import java.io.InputStream;
4 import java.io.OutputStream;
6 import com.jcraft.jsch.*;
7 import java.lang.Boolean;
9 import android.app.Activity;
10 import android.app.Service;
11 import android.content.Intent;
12 import android.app.PendingIntent;
13 import android.content.Context;
14 import android.net.Uri;
15 import android.os.Bundle;
16 import android.os.IBinder;
17 import android.widget.TextView;
18 import android.widget.Toast;
19 import android.util.Log;
20 import android.app.NotificationManager;
21 import android.app.Notification;
22 import android.os.Handler;
23 import android.os.Messenger;
24 import android.os.Looper;
25 import android.os.Message;
26 import android.os.SystemClock;
27 import android.widget.RemoteViews;
29 public class Uploader extends Service implements Runnable, UserInfo, UIKeyboardInteractive {
31 private String homedir;
33 private static final int HELPME_ID = 1;
34 private RemoteViews remote;
35 private int thenotifid;
36 private Notification thenotif;
37 private String headline;
39 private InputStream is;
41 public Object _theObject;
43 private void sayNullNotification(final String scroller, final String headline, final String description)
45 int bogon = (int)SystemClock.elapsedRealtime();
46 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
47 Notification notification = new Notification(R.drawable.icon, scroller, System.currentTimeMillis());
49 Intent intent = new Intent(this, NotifSlave.class);
51 intent.setAction("com.joshuawise.dumload.NotifSlave");
52 /* no extras to make the notifslave die */
53 intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
55 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
56 notification.defaults |= Notification.DEFAULT_VIBRATE;
57 notification.flags |= Notification.FLAG_AUTO_CANCEL;
58 notification.setLatestEventInfo(getApplicationContext(), headline, description, contentIntent);
60 mNotificationManager.notify(bogon, notification);
63 private Object /* pick one type, and fixate on it */ dance(final String type, final String text) /* for inside the thread */
65 final Uploader thisupl = this;
66 final Message msg = Message.obtain();
69 Thread t = new Thread() {
72 int bogon = (int)SystemClock.elapsedRealtime();
74 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
75 Notification notification = new Notification(R.drawable.icon, "Dumload prompt", System.currentTimeMillis());
77 Handler h = new Handler() {
78 public void handleMessage(Message M) {
80 Looper.myLooper().quit();
83 Messenger m = new Messenger(h);
85 Intent intent = new Intent(thisupl, NotifSlave.class);
87 intent.setAction("com.joshuawise.dumload.NotifSlave");
88 intent.putExtra("com.joshuawise.dumload.returnmessenger", m);
89 intent.putExtra("com.joshuawise.dumload.reqtype", type);
90 intent.putExtra("com.joshuawise.dumload.prompt", text);
91 intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
93 PendingIntent contentIntent = PendingIntent.getActivity(thisupl, 0, intent, 0);
94 notification.defaults |= Notification.DEFAULT_VIBRATE;
95 notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
96 notification.setLatestEventInfo(getApplicationContext(), "I've been had!", "Dumload needs your input.", contentIntent);
98 Log.e("Dumload.Uploader[thread]", "Notifying...");
100 mNotificationManager.notify(bogon, notification);
102 Log.e("Dumload.Uploader[thread]", "About to go to 'sleep'...");
104 Log.e("Dumload.Uploader[thread]", "And we're alive!");
106 Log.e("Dumload.Uploader[thread]", "result was: "+(Integer.toString(msg.arg1)));
108 mNotificationManager.cancel(bogon);
115 } catch (Exception e) {
119 if (type.equals("yesno"))
120 return new Boolean(msg.arg1 == 1);
121 else if (type.equals("message"))
123 else if (type.equals("password")) {
126 Bundle b = msg.getData();
127 return b.getString("response");
133 String _password = null;
134 public String getPassword()
138 public boolean promptPassword(String message)
140 _password = (String)dance("password", message);
141 return (_password != null);
144 String _passphrase = null;
145 public String getPassphrase()
149 public boolean promptPassphrase(String message)
151 _passphrase = (String)dance("password", message);
152 return (_passphrase != null);
155 public boolean promptYesNo(String str)
157 return ((Boolean)dance("yesno", str)).booleanValue();
160 public void showMessage(String str)
162 dance("message", str);
165 public String[] promptKeyboardInteractive(String dest, String name, String instr, String[] prompt, boolean[] echo)
168 String [] responses = new String[prompt.length];
170 Log.e("Dumload.Uploader", "dest: "+dest);
171 Log.e("Dumload.Uploader", "name: "+name);
172 Log.e("Dumload.Uploader", "instr: "+instr);
173 for (i = 0; i < prompt.length; i++)
175 responses[i] = (String) dance("password", "[" + dest + "]\n" + prompt[i]);
176 if (responses[i] == null)
182 private void expect_ack(InputStream in) throws Exception, java.io.IOException
188 throw new Exception("unexpected EOF from remote end");
191 if (b == 1 /* error */ || b == 2 /* fatal error */)
193 StringBuffer sb = new StringBuffer();
196 while ((c = in.read()) != '\n')
199 throw new Exception("error from remote end: " + sb.toString());
203 private void set_up_notif(final String _headline)
205 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
206 thenotif = new Notification(R.drawable.icon, headline, System.currentTimeMillis());
207 thenotifid = (int)SystemClock.elapsedRealtime();
209 Intent intent = new Intent(this, NotifSlave.class);
211 headline = _headline;
213 intent.setAction("com.joshuawise.dumload.NotifSlave");
214 /* no extras to make the notifslave die */
215 intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
217 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
218 thenotif.defaults |= 0;
219 thenotif.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
221 remote = new RemoteViews(getPackageName(), R.layout.textnotif);
222 remote.setImageViewResource(R.id.image, R.drawable.icon);
223 remote.setTextViewText(R.id.headline, headline);
224 remote.setTextViewText(R.id.status, "Beginning upload...");
225 thenotif.contentView = remote;
226 thenotif.contentIntent = contentIntent;
228 mNotificationManager.notify(thenotifid, thenotif);
231 private void destroy_notif()
233 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
234 mNotificationManager.cancel(thenotifid);
237 private void update_notif(String text)
239 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
241 remote = new RemoteViews(getPackageName(), R.layout.textnotif);
242 remote.setImageViewResource(R.id.image, R.drawable.icon);
243 remote.setTextViewText(R.id.headline, headline);
244 remote.setTextViewText(R.id.status, text);
245 thenotif.contentView = remote;
247 mNotificationManager.notify(thenotifid, thenotif);
250 private void update_notif(int n, int total)
252 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
254 remote = new RemoteViews(getPackageName(), R.layout.progressnotif);
255 remote.setImageViewResource(R.id.image, R.drawable.icon);
256 remote.setTextViewText(R.id.headline, headline);
257 remote.setProgressBar(R.id.status, total, n, false);
258 thenotif.contentView = remote;
260 mNotificationManager.notify(thenotifid, thenotif);
268 Log.e("Dumload.Uploader[thread]", "This brought to you from the new thread.");
270 set_up_notif("Dumload upload in progress");
273 say("Uploading "+(Integer.toString(is.available()))+" bytes");
275 update_notif("Connecting...");
277 JSch jsch = new JSch();
278 jsch.setKnownHosts(homedir + "/known_hosts");
279 Session s = jsch.getSession("joshua", "nyus.joshuawise.com", 22);
283 Channel channel = s.openChannel("exec");
284 ((ChannelExec)channel).setCommand("scp -t /tmp/lol.jpg");
287 OutputStream scp_out = channel.getOutputStream();
288 InputStream scp_in = channel.getInputStream();
290 update_notif("Starting send...");
292 /* Okay, BS out of the way. Now go send the file. */
295 scp_out.write(("C0644 " + (Integer.toString(is.available())) + " lol.jpg\n").getBytes());
301 total = is.available();
304 byte[] buf = new byte[4096];
305 while ((len = is.read(buf, 0, buf.length)) > 0)
307 scp_out.write(buf, 0, len);
309 update_notif(nbytes, total);
314 update_notif("Finishing file transfer...");
316 scp_out.write("\0".getBytes());
321 channel.disconnect();
323 update_notif("Preparing to resize image...");
325 channel = s.openChannel("exec");
326 ((ChannelExec)channel).setCommand("pscale /tmp/lol.jpg");
329 scp_in = channel.getInputStream();
331 update_notif("Resizing image...");
332 while ((len = scp_in.read(buf, 0, buf.length)) > 0)
335 channel.disconnect();
336 update_notif("Upload complete.");
338 sayNullNotification("Dumload upload complete", "Upload complete", "Dumload has finished uploading your file.");
341 } catch (Exception e) {
342 Log.e("Dumload.uploader[thread]", "JSchException: "+(e.toString()));
343 sayNullNotification("Dumload upload failed", "Upload failed", e.toString());
348 Log.e("Dumload.uploader[thread]", "And now I'm back to life!");
351 private void say(String s) {
352 Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
356 public void onStart(Intent i, int startId)
359 homedir = getApplicationContext().getFilesDir().getAbsolutePath();
362 super.onStart(i, startId);
364 Log.e("Dumload.Uploader", "Started.");
365 Log.e("Dumload.Uploader", "My path is "+homedir);
368 is = getContentResolver().openInputStream(uri);
369 } catch (Exception e) {
370 say("Failed to open input file.");
375 me = new Thread(this, "Uploader thread");
380 public IBinder onBind(Intent i) {
381 Log.e("Dumload.Uploader", "bound");