]> Joshua Wise's Git repositories - dumload.git/blame - src/com/joshuawise/dumload/Uploader.java
Add location prompt and pubkey support
[dumload.git] / src / com / joshuawise / dumload / Uploader.java
CommitLineData
0763e16d
JW
1package com.joshuawise.dumload;
2
3import java.io.InputStream;
035767ac 4import java.io.OutputStream;
0763e16d
JW
5
6import com.jcraft.jsch.*;
7import java.lang.Boolean;
8
9import android.app.Activity;
10import android.app.Service;
11import android.content.Intent;
12import android.app.PendingIntent;
13import android.content.Context;
14import android.net.Uri;
15import android.os.Bundle;
16import android.os.IBinder;
17import android.widget.TextView;
18import android.widget.Toast;
19import android.util.Log;
20import android.app.NotificationManager;
21import android.app.Notification;
22import android.os.Handler;
23import android.os.Messenger;
24import android.os.Looper;
25import android.os.Message;
26import android.os.SystemClock;
ae61bba6 27import android.widget.RemoteViews;
0763e16d
JW
28
29public class Uploader extends Service implements Runnable, UserInfo, UIKeyboardInteractive {
30 private Uri uri;
31 private String homedir;
32 private Thread me;
33 private static final int HELPME_ID = 1;
ae61bba6
JW
34 private RemoteViews remote;
35 private int thenotifid;
36 private Notification thenotif;
37 private String headline;
bb6544e9 38 private String dest;
0763e16d 39
035767ac
JW
40 private InputStream is;
41
0763e16d
JW
42 public Object _theObject;
43
ae61bba6
JW
44 private void sayNullNotification(final String scroller, final String headline, final String description)
45 {
46 int bogon = (int)SystemClock.elapsedRealtime();
47 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
48 Notification notification = new Notification(R.drawable.icon, scroller, System.currentTimeMillis());
49
50 Intent intent = new Intent(this, NotifSlave.class);
51
52 intent.setAction("com.joshuawise.dumload.NotifSlave");
53 /* no extras to make the notifslave die */
54 intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
55
56 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
57 notification.defaults |= Notification.DEFAULT_VIBRATE;
58 notification.flags |= Notification.FLAG_AUTO_CANCEL;
59 notification.setLatestEventInfo(getApplicationContext(), headline, description, contentIntent);
60
61 mNotificationManager.notify(bogon, notification);
62 }
63
0763e16d
JW
64 private Object /* pick one type, and fixate on it */ dance(final String type, final String text) /* for inside the thread */
65 {
66 final Uploader thisupl = this;
67 final Message msg = Message.obtain();
68
69 /* t(*A*t) */
70 Thread t = new Thread() {
71 public void run() {
72 Looper.prepare();
73 int bogon = (int)SystemClock.elapsedRealtime();
74
75 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
76 Notification notification = new Notification(R.drawable.icon, "Dumload prompt", System.currentTimeMillis());
77
78 Handler h = new Handler() {
79 public void handleMessage(Message M) {
80 msg.copyFrom(M);
81 Looper.myLooper().quit();
82 }
83 };
84 Messenger m = new Messenger(h);
85
86 Intent intent = new Intent(thisupl, NotifSlave.class);
87
88 intent.setAction("com.joshuawise.dumload.NotifSlave");
89 intent.putExtra("com.joshuawise.dumload.returnmessenger", m);
90 intent.putExtra("com.joshuawise.dumload.reqtype", type);
91 intent.putExtra("com.joshuawise.dumload.prompt", text);
92 intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
93
94 PendingIntent contentIntent = PendingIntent.getActivity(thisupl, 0, intent, 0);
95 notification.defaults |= Notification.DEFAULT_VIBRATE;
ae61bba6 96 notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
0763e16d
JW
97 notification.setLatestEventInfo(getApplicationContext(), "I've been had!", "Dumload needs your input.", contentIntent);
98
99 Log.e("Dumload.Uploader[thread]", "Notifying...");
100
101 mNotificationManager.notify(bogon, notification);
102
103 Log.e("Dumload.Uploader[thread]", "About to go to 'sleep'...");
104 Looper.loop();
105 Log.e("Dumload.Uploader[thread]", "And we're alive!");
106
107 Log.e("Dumload.Uploader[thread]", "result was: "+(Integer.toString(msg.arg1)));
108
109 mNotificationManager.cancel(bogon);
110 }
111 };
112
113 t.start();
114 try {
115 t.join();
116 } catch (Exception e) {
117 return null;
118 }
119
120 if (type.equals("yesno"))
121 return new Boolean(msg.arg1 == 1);
122 else if (type.equals("message"))
123 return null;
124 else if (type.equals("password")) {
125 if (msg.arg1 == 0)
126 return null;
127 Bundle b = msg.getData();
128 return b.getString("response");
129 } else
130 return null;
131 }
132
133 /* UserInfo bits */
134 String _password = null;
135 public String getPassword()
136 {
137 return _password;
138 }
139 public boolean promptPassword(String message)
140 {
141 _password = (String)dance("password", message);
142 return (_password != null);
143 }
144
145 String _passphrase = null;
146 public String getPassphrase()
147 {
148 return _passphrase;
149 }
150 public boolean promptPassphrase(String message)
151 {
152 _passphrase = (String)dance("password", message);
153 return (_passphrase != null);
154 }
155
156 public boolean promptYesNo(String str)
157 {
158 return ((Boolean)dance("yesno", str)).booleanValue();
159 }
160
161 public void showMessage(String str)
162 {
163 dance("message", str);
164 }
165
166 public String[] promptKeyboardInteractive(String dest, String name, String instr, String[] prompt, boolean[] echo)
167 {
168 int i;
169 String [] responses = new String[prompt.length];
170
171 Log.e("Dumload.Uploader", "dest: "+dest);
172 Log.e("Dumload.Uploader", "name: "+name);
173 Log.e("Dumload.Uploader", "instr: "+instr);
174 for (i = 0; i < prompt.length; i++)
175 {
176 responses[i] = (String) dance("password", "[" + dest + "]\n" + prompt[i]);
ae61bba6
JW
177 if (responses[i] == null)
178 return null;
0763e16d
JW
179 }
180 return responses;
181 }
182
035767ac
JW
183 private void expect_ack(InputStream in) throws Exception, java.io.IOException
184 {
185 int b = in.read();
186
187 if (b == -1)
188 {
189 throw new Exception("unexpected EOF from remote end");
190 }
191
192 if (b == 1 /* error */ || b == 2 /* fatal error */)
193 {
194 StringBuffer sb = new StringBuffer();
195 int c = 0;
196
197 while ((c = in.read()) != '\n')
198 sb.append((char)c);
199
200 throw new Exception("error from remote end: " + sb.toString());
201 }
202 }
203
ae61bba6
JW
204 private void set_up_notif(final String _headline)
205 {
206 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
207 thenotif = new Notification(R.drawable.icon, headline, System.currentTimeMillis());
208 thenotifid = (int)SystemClock.elapsedRealtime();
209
210 Intent intent = new Intent(this, NotifSlave.class);
211
212 headline = _headline;
213
214 intent.setAction("com.joshuawise.dumload.NotifSlave");
215 /* no extras to make the notifslave die */
216 intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
217
218 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
219 thenotif.defaults |= 0;
220 thenotif.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
221
222 remote = new RemoteViews(getPackageName(), R.layout.textnotif);
223 remote.setImageViewResource(R.id.image, R.drawable.icon);
224 remote.setTextViewText(R.id.headline, headline);
225 remote.setTextViewText(R.id.status, "Beginning upload...");
226 thenotif.contentView = remote;
227 thenotif.contentIntent = contentIntent;
228
229 mNotificationManager.notify(thenotifid, thenotif);
230 }
231
232 private void destroy_notif()
233 {
234 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
235 mNotificationManager.cancel(thenotifid);
236 }
237
238 private void update_notif(String text)
239 {
240 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
241
242 remote = new RemoteViews(getPackageName(), R.layout.textnotif);
243 remote.setImageViewResource(R.id.image, R.drawable.icon);
244 remote.setTextViewText(R.id.headline, headline);
245 remote.setTextViewText(R.id.status, text);
246 thenotif.contentView = remote;
247
248 mNotificationManager.notify(thenotifid, thenotif);
249 }
250
251 private void update_notif(int n, int total)
252 {
253 NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
254
255 remote = new RemoteViews(getPackageName(), R.layout.progressnotif);
256 remote.setImageViewResource(R.id.image, R.drawable.icon);
257 remote.setTextViewText(R.id.headline, headline);
258 remote.setProgressBar(R.id.status, total, n, false);
259 thenotif.contentView = remote;
260
261 mNotificationManager.notify(thenotifid, thenotif);
262 }
263
0763e16d
JW
264 @Override
265 public void run()
266 {
267 Looper.prepare();
268
269 Log.e("Dumload.Uploader[thread]", "This brought to you from the new thread.");
270
bb6544e9 271 set_up_notif("Dumload upload: " + dest);
ae61bba6 272
0763e16d 273 try {
035767ac
JW
274 say("Uploading "+(Integer.toString(is.available()))+" bytes");
275
ae61bba6
JW
276 update_notif("Connecting...");
277
0763e16d
JW
278 JSch jsch = new JSch();
279 jsch.setKnownHosts(homedir + "/known_hosts");
bb6544e9
JW
280 try {
281 jsch.addIdentity(homedir + "/id_dsa");
282 } catch (java.lang.Exception e) {
283 }
0763e16d
JW
284 Session s = jsch.getSession("joshua", "nyus.joshuawise.com", 22);
285 s.setUserInfo(this);
286 s.connect();
287
288 Channel channel = s.openChannel("exec");
bb6544e9 289 ((ChannelExec)channel).setCommand("scp -t "+dest);
0763e16d
JW
290 channel.connect();
291
035767ac
JW
292 OutputStream scp_out = channel.getOutputStream();
293 InputStream scp_in = channel.getInputStream();
294
ae61bba6
JW
295 update_notif("Starting send...");
296
035767ac
JW
297 /* Okay, BS out of the way. Now go send the file. */
298 expect_ack(scp_in);
299
bb6544e9
JW
300 String stfu;
301 if (dest.lastIndexOf("/") > 0)
302 stfu = dest.substring(dest.lastIndexOf("/") + 1);
303 else
304 stfu = dest;
305
306 scp_out.write(("C0644 " + (Integer.toString(is.available())) + " "+stfu+"\n").getBytes());
035767ac
JW
307 scp_out.flush();
308
309 expect_ack(scp_in);
310
ae61bba6
JW
311 int total, nbytes;
312 total = is.available();
313 nbytes = 0;
035767ac
JW
314 int len;
315 byte[] buf = new byte[4096];
316 while ((len = is.read(buf, 0, buf.length)) > 0)
ae61bba6 317 {
035767ac 318 scp_out.write(buf, 0, len);
ae61bba6
JW
319 nbytes += len;
320 update_notif(nbytes, total);
321 }
035767ac
JW
322
323 is.close();
324
e1916520 325 update_notif("Finishing file transfer...");
ae61bba6 326
035767ac
JW
327 scp_out.write("\0".getBytes());
328 scp_out.flush();
329
330 expect_ack(scp_in);
331
e1916520
JW
332 channel.disconnect();
333
334 update_notif("Preparing to resize image...");
335
336 channel = s.openChannel("exec");
bb6544e9 337 ((ChannelExec)channel).setCommand("pscale "+dest);
e1916520
JW
338 channel.connect();
339
340 scp_in = channel.getInputStream();
341
342 update_notif("Resizing image...");
343 while ((len = scp_in.read(buf, 0, buf.length)) > 0)
344 ;
345
346 channel.disconnect();
347 update_notif("Upload complete.");
348
bb6544e9 349 sayNullNotification("Dumload upload complete: " + dest, "Upload complete", "Uploaded: " + dest);
0763e16d 350
0763e16d 351 s.disconnect();
035767ac 352 } catch (Exception e) {
0763e16d 353 Log.e("Dumload.uploader[thread]", "JSchException: "+(e.toString()));
ae61bba6 354 sayNullNotification("Dumload upload failed", "Upload failed", e.toString());
0763e16d
JW
355 }
356
ae61bba6
JW
357 destroy_notif();
358
0763e16d
JW
359 Log.e("Dumload.uploader[thread]", "And now I'm back to life!");
360 }
361
362 private void say(String s) {
363 Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
364 }
365
366 @Override
367 public void onStart(Intent i, int startId)
368 {
369 uri = i.getData();
bb6544e9 370 dest = i.getStringExtra("com.joshuawise.dumload.dest");
0763e16d
JW
371 homedir = getApplicationContext().getFilesDir().getAbsolutePath();
372 int shits = 0;
373
374 super.onStart(i, startId);
375
376 Log.e("Dumload.Uploader", "Started.");
377 Log.e("Dumload.Uploader", "My path is "+homedir);
378
379 try {
035767ac 380 is = getContentResolver().openInputStream(uri);
0763e16d 381 } catch (Exception e) {
035767ac
JW
382 say("Failed to open input file.");
383 return;
0763e16d
JW
384 }
385
0763e16d
JW
386
387 me = new Thread(this, "Uploader thread");
388 me.start();
389 }
390
391 @Override
392 public IBinder onBind(Intent i) {
393 Log.e("Dumload.Uploader", "bound");
394
395 return null;
396 }
397}
This page took 0.06011 seconds and 4 git commands to generate.