]> Joshua Wise's Git repositories - dumload.git/blame - src/com/joshuawise/dumload/Uploader.java
Fix stray DOS line endings
[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 }
7d9c8975 287 try {
288 jsch.addIdentity(homedir + "/id_dsa_generated");
289 } catch (java.lang.Exception e) {
290 }
42aa7dfd 291 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
292 String server = prefs.getString("server", "").trim();
293 String userName = prefs.getString("userName", "").trim();
7d9c8975 294 Integer port = Integer.valueOf(prefs.getString("port", "22"));
42aa7dfd 295 Log.d("dbg", userName + "@" + server + ":" + port);
296 Session s = jsch.getSession(userName, server, port);
0763e16d
JW
297 s.setUserInfo(this);
298 s.connect();
299
300 Channel channel = s.openChannel("exec");
bb6544e9 301 ((ChannelExec)channel).setCommand("scp -t "+dest);
0763e16d
JW
302 channel.connect();
303
035767ac
JW
304 OutputStream scp_out = channel.getOutputStream();
305 InputStream scp_in = channel.getInputStream();
306
ae61bba6
JW
307 update_notif("Starting send...");
308
035767ac
JW
309 /* Okay, BS out of the way. Now go send the file. */
310 expect_ack(scp_in);
311
bb6544e9
JW
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());
035767ac
JW
319 scp_out.flush();
320
321 expect_ack(scp_in);
322
ae61bba6
JW
323 int total, nbytes;
324 total = is.available();
325 nbytes = 0;
035767ac
JW
326 int len;
327 byte[] buf = new byte[4096];
328 while ((len = is.read(buf, 0, buf.length)) > 0)
ae61bba6 329 {
035767ac 330 scp_out.write(buf, 0, len);
ae61bba6
JW
331 nbytes += len;
332 update_notif(nbytes, total);
333 }
035767ac
JW
334
335 is.close();
336
e1916520 337 update_notif("Finishing file transfer...");
ae61bba6 338
035767ac
JW
339 scp_out.write("\0".getBytes());
340 scp_out.flush();
341
342 expect_ack(scp_in);
343
e1916520
JW
344 channel.disconnect();
345
346 update_notif("Preparing to resize image...");
347
348 channel = s.openChannel("exec");
bb6544e9 349 ((ChannelExec)channel).setCommand("pscale "+dest);
e1916520
JW
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
bb6544e9 361 sayNullNotification("Dumload upload complete: " + dest, "Upload complete", "Uploaded: " + dest);
0763e16d 362
0763e16d 363 s.disconnect();
035767ac 364 } catch (Exception e) {
0763e16d 365 Log.e("Dumload.uploader[thread]", "JSchException: "+(e.toString()));
ae61bba6 366 sayNullNotification("Dumload upload failed", "Upload failed", e.toString());
0763e16d
JW
367 }
368
ae61bba6
JW
369 destroy_notif();
370
0763e16d
JW
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();
bb6544e9 382 dest = i.getStringExtra("com.joshuawise.dumload.dest");
0763e16d
JW
383 homedir = getApplicationContext().getFilesDir().getAbsolutePath();
384 int shits = 0;
42aa7dfd 385 int giggles = 1;
0763e16d
JW
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 {
035767ac 393 is = getContentResolver().openInputStream(uri);
0763e16d 394 } catch (Exception e) {
035767ac
JW
395 say("Failed to open input file.");
396 return;
0763e16d
JW
397 }
398
0763e16d
JW
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.066517 seconds and 4 git commands to generate.