]> Joshua Wise's Git repositories - dumload.git/blame_incremental - src/com/joshuawise/dumload/Uploader.java
Fix stray DOS line endings
[dumload.git] / src / com / joshuawise / dumload / Uploader.java
... / ...
CommitLineData
1package com.joshuawise.dumload;
2
3import java.io.InputStream;
4import java.io.OutputStream;
5
6import android.app.Notification;
7import android.app.NotificationManager;
8import android.app.PendingIntent;
9import android.app.Service;
10import android.content.Context;
11import android.content.Intent;
12import android.content.SharedPreferences;
13import android.net.Uri;
14import android.os.Bundle;
15import android.os.Handler;
16import android.os.IBinder;
17import android.os.Looper;
18import android.os.Message;
19import android.os.Messenger;
20import android.os.SystemClock;
21import android.preference.PreferenceManager;
22import android.util.Log;
23import android.widget.RemoteViews;
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;
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;
38 private RemoteViews remote;
39 private int thenotifid;
40 private Notification thenotif;
41 private String headline;
42 private String dest;
43
44 private InputStream is;
45
46 public Object _theObject;
47
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
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;
100 notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
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]);
181 if (responses[i] == null)
182 return null;
183 }
184 return responses;
185 }
186
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
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
268 public void run()
269 {
270 Looper.prepare();
271
272 Log.e("Dumload.Uploader[thread]", "This brought to you from the new thread.");
273
274 set_up_notif("Dumload upload: " + dest);
275
276 try {
277 say("Uploading "+(Integer.toString(is.available()))+" bytes");
278
279 update_notif("Connecting...");
280
281 JSch jsch = new JSch();
282 jsch.setKnownHosts(homedir + "/known_hosts");
283 try {
284 jsch.addIdentity(homedir + "/id_dsa");
285 } catch (java.lang.Exception e) {
286 }
287 try {
288 jsch.addIdentity(homedir + "/id_dsa_generated");
289 } catch (java.lang.Exception e) {
290 }
291 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
292 String server = prefs.getString("server", "").trim();
293 String userName = prefs.getString("userName", "").trim();
294 Integer port = Integer.valueOf(prefs.getString("port", "22"));
295 Log.d("dbg", userName + "@" + server + ":" + port);
296 Session s = jsch.getSession(userName, server, port);
297 s.setUserInfo(this);
298 s.connect();
299
300 Channel channel = s.openChannel("exec");
301 ((ChannelExec)channel).setCommand("scp -t "+dest);
302 channel.connect();
303
304 OutputStream scp_out = channel.getOutputStream();
305 InputStream scp_in = channel.getInputStream();
306
307 update_notif("Starting send...");
308
309 /* Okay, BS out of the way. Now go send the file. */
310 expect_ack(scp_in);
311
312 String stfu;
313 if (dest.lastIndexOf("/") > 0)
314 stfu = dest.substring(dest.lastIndexOf("/") + 1);
315 else
316 stfu = dest;
317
318 scp_out.write(("C0644 " + (Integer.toString(is.available())) + " "+stfu+"\n").getBytes());
319 scp_out.flush();
320
321 expect_ack(scp_in);
322
323 int total, nbytes;
324 total = is.available();
325 nbytes = 0;
326 int len;
327 byte[] buf = new byte[4096];
328 while ((len = is.read(buf, 0, buf.length)) > 0)
329 {
330 scp_out.write(buf, 0, len);
331 nbytes += len;
332 update_notif(nbytes, total);
333 }
334
335 is.close();
336
337 update_notif("Finishing file transfer...");
338
339 scp_out.write("\0".getBytes());
340 scp_out.flush();
341
342 expect_ack(scp_in);
343
344 channel.disconnect();
345
346 update_notif("Preparing to resize image...");
347
348 channel = s.openChannel("exec");
349 ((ChannelExec)channel).setCommand("pscale "+dest);
350 channel.connect();
351
352 scp_in = channel.getInputStream();
353
354 update_notif("Resizing image...");
355 while ((len = scp_in.read(buf, 0, buf.length)) > 0)
356 ;
357
358 channel.disconnect();
359 update_notif("Upload complete.");
360
361 sayNullNotification("Dumload upload complete: " + dest, "Upload complete", "Uploaded: " + dest);
362
363 s.disconnect();
364 } catch (Exception e) {
365 Log.e("Dumload.uploader[thread]", "JSchException: "+(e.toString()));
366 sayNullNotification("Dumload upload failed", "Upload failed", e.toString());
367 }
368
369 destroy_notif();
370
371 Log.e("Dumload.uploader[thread]", "And now I'm back to life!");
372 }
373
374 private void say(String s) {
375 Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
376 }
377
378 @Override
379 public void onStart(Intent i, int startId)
380 {
381 uri = i.getData();
382 dest = i.getStringExtra("com.joshuawise.dumload.dest");
383 homedir = getApplicationContext().getFilesDir().getAbsolutePath();
384 int shits = 0;
385 int giggles = 1;
386
387 super.onStart(i, startId);
388
389 Log.e("Dumload.Uploader", "Started.");
390 Log.e("Dumload.Uploader", "My path is "+homedir);
391
392 try {
393 is = getContentResolver().openInputStream(uri);
394 } catch (Exception e) {
395 say("Failed to open input file.");
396 return;
397 }
398
399
400 me = new Thread(this, "Uploader thread");
401 me.start();
402 }
403
404 @Override
405 public IBinder onBind(Intent i) {
406 Log.e("Dumload.Uploader", "bound");
407
408 return null;
409 }
410}
This page took 0.032012 seconds and 4 git commands to generate.