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