]> Joshua Wise's Git repositories - dumload.git/blob - src/com/joshuawise/dumload/Uploader.java
Fix port usage and always try to add the generated key
[dumload.git] / src / com / joshuawise / dumload / Uploader.java
1 package com.joshuawise.dumload;
2
3 import java.io.InputStream;
4 import java.io.OutputStream;
5
6 import android.app.Notification;
7 import android.app.NotificationManager;
8 import android.app.PendingIntent;
9 import android.app.Service;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.SharedPreferences;
13 import android.net.Uri;
14 import android.os.Bundle;
15 import android.os.Handler;
16 import android.os.IBinder;
17 import android.os.Looper;
18 import android.os.Message;
19 import android.os.Messenger;
20 import android.os.SystemClock;
21 import android.preference.PreferenceManager;
22 import android.util.Log;
23 import android.widget.RemoteViews;
24 import android.widget.Toast;
25
26 import com.jcraft.jsch.Channel;
27 import com.jcraft.jsch.ChannelExec;
28 import com.jcraft.jsch.JSch;
29 import com.jcraft.jsch.Session;
30 import com.jcraft.jsch.UIKeyboardInteractive;
31 import com.jcraft.jsch.UserInfo;
32
33 public 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.040942 seconds and 4 git commands to generate.