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