Add SH and ROOTSH commands
[fonbot.git] / src / ro / ieval / fonbot / Utils.java
1 package ro.ieval.fonbot;
2
3 import static ro.ieval.fonbot.R.string.*;
4
5 import java.net.MalformedURLException;
6 import java.net.URL;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Locale;
10
11 import org.eclipse.jdt.annotation.NonNull;
12 import org.eclipse.jdt.annotation.Nullable;
13
14 import ro.ieval.fonbot.Address.Protocol;
15 import android.content.Context;
16 import android.content.Intent;
17 import android.content.SharedPreferences;
18 import android.database.Cursor;
19 import android.location.LocationManager;
20 import android.media.AudioManager;
21 import android.net.Uri;
22 import android.os.Handler;
23 import android.os.Looper;
24 import android.preference.PreferenceManager;
25 import android.provider.ContactsContract.PhoneLookup;
26 import android.telephony.SmsManager;
27 import android.util.Log;
28 import android.widget.Toast;
29
30 /*
31 * Copyright © 2013 Marius Gavrilescu
32 *
33 * This file is part of FonBot.
34 *
35 * FonBot is free software: you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation, either version 3 of the License, or
38 * (at your option) any later version.
39 *
40 * FonBot is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
44 *
45 * You should have received a copy of the GNU General Public License
46 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
47 */
48
49 /**
50 * Utility functions and enums used in various places.
51 *
52 * @author Marius Gavrilescu <marius@ieval.ro>
53 */
54 public final class Utils {
55 /**
56 * Enum of all FonBot commands.
57 *
58 * @author Marius Gavrilescu <marius@ieval.ro>
59 */
60 @SuppressWarnings("javadoc")
61 public static enum Command{
62 TOAST, ECHO, SMS, FLASH, WIFI,
63 BLUETOOTH, DIAL, RING, SPEAK, VIBRATE,
64 DIALOG, LOCATION, NOLOCATION, RINGER, NCFILE,
65 PHOTO, SETNOTIFICATION, DELNOTIFICATION, SETPASSWORD, HELP,
66 WIPE, LOCK, VIEW, PLAY, PAUSE,
67 NEXT, PREV, BATT, CALLLOG, SMSLOG,
68 LS, RM, CONTACTS, DISABLE, ENABLE,
69 POLL, HANGUP, ANSWER, LAUNCH, DATA,
70 GPS, GLOCATION, REBOOT, NOTIFY, SCREENCAP,
71 TORCH, GETFILE, SH, ROOTSH
72 }
73
74 /**
75 * Enum of all message types. Each message type is a kind of notification which can be enabled/disabled by the user and directed to a certain address.
76 *
77 * @author Marius Gavrilescu <marius@ieval.ro>
78 *
79 */
80 public static enum MessageType{
81 /** SMS notifications */
82 SMS,
83 /** Phone state (idle, offhook or ringing) notifications */
84 PHONE_STATE,
85 /** Lockscreen failed password notifications */
86 WATCH_LOGIN,
87 /** Device admin enable/disable notifications */
88 ADMIN,
89 /** Coarse battery status (low battery, ok battery) notifications */
90 BATTERY,
91 /** Fine battery status notifications */
92 BATTERY_CHANGED,
93 /** Headset plug/unplug notifications */
94 HEADSET,
95 /** Phone booted notifications */
96 BOOT,
97 }
98
99 /**
100 * Enum of wipe types. The two defined types are the data wipe (which does not include the SD card) and the full wipe (which includes the SD card).
101 *
102 * @author Marius Gavrilescu <marius@ieval.ro>
103 */
104 public static enum WipeType{
105 /** Factory reset the phone, without touching the SD card */
106 DATA,
107 /** Factory reset the phone and wipe the SD card too */
108 FULL
109 }
110
111 /**
112 * Enum of ringer modes.
113 *
114 * @author Marius Gavrilescu <marius@ieval.ro>
115 */
116 public static enum RingerMode{
117 /** Sound is on */
118 NORMAL,
119 /** Sound is off, vibrate is on */
120 VIBRATE,
121 /** Sound is off, vibrate is off */
122 SILENT
123 }
124
125 /**
126 * Enum of location providers
127 *
128 * @author Marius Gavrilescu <marius@ieval.ro>
129 */
130 public static enum LocationProvider{
131 /** The network location provider */
132 NETWORK,
133 /** The GPS location provider */
134 GPS
135 }
136
137 /**
138 * Enum of toast lengths.
139 *
140 * @author Marius Gavrilescu <marius@ieval.ro>
141 */
142 private static enum ToastLength{
143 /** Long toast */
144 LONG,
145 /** Short toast */
146 SHORT
147 }
148
149 /**
150 * Enum of the values on and off. Used for boolean arguments.
151 *
152 * @author Marius Gavrilescu <marius@ieval.ro>
153 */
154 @SuppressWarnings("javadoc")
155 private static enum OnOff{
156 ON, OFF
157 }
158
159 /**
160 * Enum of ongoing event types
161 *
162 * @author Marius Gavrilescu <marius@ieval.ro>
163 */
164 public static enum OngoingEvent{
165 /** Location tracking is active. Registered by {@link Command#LOCATION}, unregistered by {@link Command#NOLOCATION} */
166 LOCATION(location_tracking_is_active),
167 /** The phone is ringing. Registered/unregistered by {@link Command#RING} */
168 RING(ringing);
169
170 /** String resource: the event description */
171 public final int resource;
172
173 /**
174 * Constructs an OngoingEvent from its event description.
175 *
176 * @param resource the event description
177 */
178 private OngoingEvent(final int resource) {
179 this.resource=resource;
180 }
181 }
182
183 /** Confirmation string for the {@link Command#WIPE WIPE} command. */
184 public static final String WIPE_CONFIRM_STRING="I am aware this cannot be undone";
185
186 /**
187 * Converts a Nullable object into a NonNull one.
188 *
189 * @param object the Nullable object to convert
190 * @return a NonNull object equivalent to the Nullable parameter
191 * @throws AssertionError if the given object is null
192 */
193 public static <T> T toNonNull(@Nullable T object) throws AssertionError{
194 if(object==null)
195 throw new NullPointerException();
196 return object;
197 }
198
199 /**
200 * Join an array of Objects with elements separated by a separator into a single string.
201 *
202 * @param separator the separator
203 * @param offset the offset into the array
204 * @param args the array of Objects to join
205 * @return the joined string
206 */
207 public static String join(final String separator,final int offset,final Object[] args){
208 final StringBuilder sb=new StringBuilder(240);
209 sb.append(args[offset]);
210 for (int i = offset+1; i < args.length; i++) {
211 sb.append(separator);
212 sb.append(args[i]);
213 }
214 return toNonNull(sb.toString());
215 }
216
217 /**
218 * Join an array of Objects with elements separated by a separator into a single string.
219 *
220 * @param separator the separator
221 * @param args the array of objects to join
222 * @return the joined string
223 */
224 public static String join(final String separator, final Object[] args){
225 return join(separator,0,args);
226 }
227
228 /**
229 * Send a notification to the user.
230 *
231 * @param context Context instance
232 * @param type notification type
233 * @param resource String resource for the message text
234 */
235 public static void sendMessage(final Context context, final MessageType type, final int resource){
236 sendMessage(context, type, toNonNull(context.getString(resource)));
237 }
238
239 /**
240 * Send a notification to the user.
241 *
242 * @param context Context instance
243 * @param type notification type
244 * @param resource String resource for the message text
245 * @param args format parameters for the resource
246 */
247 public static void sendMessage(final Context context, final MessageType type, final int resource, final Object... args){
248 sendMessage(context, type, toNonNull(context.getString(resource, args)));
249 }
250
251 /**
252 * Send a message to a certain Address.
253 *
254 * @param context Context instance
255 * @param address destination Address
256 * @param resource String resource for the message text
257 */
258 public static void sendMessage(final Context context, final Address address, final int resource){
259 sendMessage(context, address, toNonNull(context.getString(resource)));
260 }
261
262 /**
263 * Send a message to a certain Address.
264 *
265 * @param context Context instance
266 * @param address destination Address
267 * @param resource String resource for the message text
268 * @param args format parameters for the resource
269 */
270 public static void sendMessage(final Context context, final Address address, final int resource, final Object... args){
271 sendMessage(context, address, toNonNull(context.getString(resource, args)));
272 }
273
274 /**
275 * Send a notification to the user.
276 *
277 * @param context Context instance
278 * @param type notification type
279 * @param msg the notification text
280 */
281 public static void sendMessage(final Context context, final MessageType type,final String msg){
282 final SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(context);
283 final String address=sp.getString(type.toString(),null);
284 if(address==null)
285 return;
286 sendMessage(context, new Address(address), msg);
287 }
288
289 /**
290 * Send a message to a certain Address.
291 *
292 * @param context Context instance
293 * @param address destination Address
294 * @param message the message text
295 */
296 public static void sendMessage(final Context context, final Address address, final String message){
297 switch(address.protocol){
298 case HTTP:
299 new HttpCallExecutableRunnable("/send", toNonNull(Arrays.asList(new Header("X-Destination", toNonNull(address.data)))), context, null, true, address.requestId == null ? message : address.requestId + " " + message).execute();
300 break;
301
302 case SMS:
303 new Handler(Looper.getMainLooper()).post(new Runnable(){
304 @Override
305 public void run(){
306 final ArrayList<String> parts = SmsManager.getDefault().divideMessage(message);
307 SmsManager.getDefault().sendMultipartTextMessage(address.data, null, parts, null, null);
308 }
309 });
310 break;
311
312 case LOCAL:
313 final Intent intent = new Intent(FonBotLocalActivity.RESPONSE_RECEIVED_ACTION);
314 intent.putExtra(FonBotLocalActivity.EXTRA_RESPONSE, message);
315 context.sendBroadcast(intent);
316 break;
317
318 case NULL:
319 break;//blackhole
320 }
321 }
322
323 /**
324 * Splits a string into words.
325 *
326 * @param string the string
327 * @return an array of words
328 */
329 public static String[] shellwords(final String string){
330 return toNonNull(string.split("[ ]+(?=([^\"]*\"[^\"]*\")*[^\"]*$)"));//TODO: Make this handle backslash escapes
331 }
332
333 /**
334 * Returns the name associated with a phone number.
335 *
336 * @param context Context instance
337 * @param number phone number to search for
338 * @return the name associated with this number, or null if the number was not found in the contacts.
339 */
340 public static @Nullable String callerId(final Context context, final String number){
341 final Cursor cursor=context.getContentResolver().query(
342 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)),
343 new String[]{PhoneLookup.DISPLAY_NAME},
344 null,
345 null,
346 null);
347
348 if(cursor.moveToFirst()){
349 final String name=cursor.getString(0);
350 cursor.close();
351 return name;
352 }
353 cursor.close();
354 return null;
355 }
356
357 /**
358 * Registers an ongoing event.
359 *
360 * @param context Context instance
361 * @param event event to register
362 */
363 public static void registerOngoing(final Context context, final OngoingEvent event){
364 final Intent intent=new Intent(context, FonBotMainService.class);
365 intent.setAction(FonBotMainService.ACTION_PUT_ONGOING);
366 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
367 context.startService(intent);
368 }
369
370 /**
371 * Unregisters an ongoing event
372 *
373 * @param context Context instance
374 * @param event event to unregister
375 */
376 public static void unregisterOngoing(final Context context, final OngoingEvent event){
377 final Intent intent=new Intent(context, FonBotMainService.class);
378 intent.setAction(FonBotMainService.ACTION_DELETE_ONGOING);
379 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
380 context.startService(intent);
381 }
382
383 /**
384 * Gets the server URL according to the user preferences.
385 *
386 * @param context Context instance
387 * @param path URL path
388 * @return the server URL
389 * @throws MalformedURLException if the user preferences create an invalid URL
390 */
391 public static URL getServerURL(final Context context, final String path) throws MalformedURLException{
392 final String protocol=PreferenceManager.getDefaultSharedPreferences(context).getString("protocol", "https");
393 final String hostname=PreferenceManager.getDefaultSharedPreferences(context).getString("hostname", "fonbot.ieval.ro");
394 final int port=Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString("port", "443"));
395 final URL url=new URL(protocol, hostname, port, path);
396 return url;
397 }
398
399 /**
400 * Executes a given command
401 *
402 * @param context Context instance
403 * @param cmd Command to execute
404 * @param args arguments for the command
405 * @param replyTo Address to send replies to
406 */
407 private static void processCommand(final Context context, final Command cmd,final String[] args,final Address replyTo){
408 if(Heavy.isCommandDisabled(context, cmd)){
409 sendMessage(context, replyTo, command_disabled, cmd.toString());
410 return;
411 }
412
413 switch(cmd){
414 case TOAST:
415 if(args.length < 1 || args.length > 2){
416 Heavy.help(context, replyTo, toNonNull(Command.TOAST));
417 break;
418 }
419
420 if(args.length==1)
421 Heavy.toast(context, replyTo, toNonNull(args[0]));
422 else {
423 try {
424 switch(ToastLength.valueOf(args[1].toUpperCase(Locale.ENGLISH))){
425 case LONG:
426 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_LONG);
427 break;
428 case SHORT:
429 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_SHORT);
430 }
431 } catch(IllegalArgumentException e){
432 sendMessage(context, replyTo, invalid_length_allowed_values_are, join(", ",toNonNull(ToastLength.values())));
433 }
434 }
435 break;
436
437 case ECHO:
438 if(args.length==0){
439 Heavy.help(context, replyTo, toNonNull(Command.ECHO));
440 break;
441 }
442 sendMessage(context, replyTo, join(" ",args));
443 break;
444
445 case SMS:
446 if(args.length < 2){
447 Heavy.help(context, replyTo, toNonNull(Command.SMS));
448 break;
449 }
450 Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args));
451 break;
452
453 case FLASH:
454 if(args.length != 1){
455 Heavy.help(context, replyTo, toNonNull(Command.FLASH));
456 break;
457 }
458
459 try {
460 Heavy.flash(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
461 } catch(IllegalArgumentException e) {
462 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
463 }
464 break;
465
466 case WIFI:
467 if(args.length>1){
468 Heavy.help(context, replyTo, toNonNull(Command.WIFI));
469 break;
470 }
471 if(args.length==0)
472 Heavy.wifi(context, replyTo);
473 else {
474 try {
475 Heavy.wifi(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
476 } catch(IllegalArgumentException e) {
477 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
478 }
479 }
480 break;
481
482 case BLUETOOTH:
483 if(args.length>1){
484 Heavy.help(context, replyTo, toNonNull(Command.BLUETOOTH));
485 break;
486 }
487 if(args.length==0)
488 Heavy.bluetooth(context, replyTo);
489 else {
490 try {
491 Heavy.bluetooth(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
492 } catch(IllegalArgumentException e) {
493 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
494 }
495 }
496 break;
497
498 case DIAL:
499 if(args.length!=1){
500 Heavy.help(context, replyTo, toNonNull(Command.DIAL));
501 break;
502 }
503 Heavy.dial(context, replyTo, toNonNull(args[0]));
504 break;
505
506 case RING:
507 if(args.length>1){
508 Heavy.help(context, replyTo, toNonNull(Command.RING));
509 break;
510 }
511 if(args.length==0)
512 Heavy.ring(context, replyTo);
513 else {
514 try {
515 Heavy.ring(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
516 } catch(IllegalArgumentException e){
517 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
518 }
519 }
520 break;
521
522 case SPEAK:
523 if(args.length==0){
524 Heavy.help(context, replyTo, toNonNull(Command.SPEAK));
525 break;
526 }
527 Heavy.speak(context, replyTo, join(" ",args));
528 break;
529
530 case VIBRATE:
531 if(args.length!=1){
532 Heavy.help(context, replyTo, toNonNull(Command.VIBRATE));
533 break;
534 }
535 final long ms;
536 try{
537 ms=Long.parseLong(args[0]);
538 } catch(NumberFormatException e){
539 sendMessage(context, replyTo, could_not_parse_ms);
540 break;
541 }
542 Heavy.vibrate(context, replyTo, ms);
543 break;
544
545 case DIALOG://TODO: Should add an edittext
546 if(args.length<1){
547 Heavy.help(context, replyTo, toNonNull(Command.DIALOG));
548 break;
549 }
550 final String[] buttons=new String[args.length-1];
551 System.arraycopy(args,1,buttons,0,buttons.length);
552 Heavy.dialog(context, replyTo, toNonNull(args[0]), buttons);
553 break;
554
555 case LOCATION:
556 if(args.length>3||args.length<1){
557 Heavy.help(context, replyTo, toNonNull(Command.LOCATION));
558 break;
559 }
560
561 final @NonNull String provider;
562 try{
563 switch(LocationProvider.valueOf(args[0].toUpperCase(Locale.ENGLISH))){
564 case GPS:
565 provider=toNonNull(LocationManager.GPS_PROVIDER);
566 break;
567 case NETWORK:
568 default:
569 provider=toNonNull(LocationManager.NETWORK_PROVIDER);
570 break;
571 }
572 } catch(IllegalArgumentException e){
573 sendMessage(context, replyTo, cannot_parse_provider_allowed_values_are, join(", ",toNonNull(LocationProvider.values())));
574 break;
575 }
576
577 final long minTime;
578 final float minDistance;
579
580 if(args.length>1)
581 try{
582 minTime=Long.parseLong(args[1]);
583 } catch (NumberFormatException e){
584 sendMessage(context, replyTo, cannot_parse_min_time);
585 break;
586 }
587 else
588 minTime=500;
589
590 if(args.length>2)
591 try{
592 minDistance=Float.parseFloat(args[2]);
593 } catch (NumberFormatException e){
594 sendMessage(context, replyTo, cannot_parse_min_distance);
595 break;
596 }
597 else
598 minDistance=0;
599 Heavy.location(context, replyTo, provider, minTime, minDistance);
600 break;
601
602 case NOLOCATION:
603 Heavy.nolocation(context, replyTo);
604 break;
605
606 case RINGER:
607 if(args.length>1){
608 Heavy.help(context, replyTo, toNonNull(Command.RINGER));
609 break;
610 }
611 if(args.length==0)
612 Heavy.ringer(context, replyTo);
613 else{
614 try{
615 final RingerMode rm=RingerMode.valueOf(args[0].toUpperCase(Locale.ENGLISH));
616 switch(rm){
617 case NORMAL:
618 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_NORMAL);
619 break;
620 case VIBRATE:
621 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_VIBRATE);
622 break;
623 case SILENT:
624 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_SILENT);
625 break;
626 }
627 } catch (IllegalArgumentException e){
628 Utils.sendMessage(context, replyTo, invalid_ringer_mode_valid_values_are, join(", ",toNonNull(RingerMode.values())));
629 }
630 }
631 break;
632
633 case NCFILE:
634 if(args.length!=3){
635 Heavy.help(context, replyTo, toNonNull(Command.NCFILE));
636 break;
637 }
638
639 final int ncfilePort;
640 try{
641 ncfilePort=Integer.parseInt(args[2]);
642 } catch (NumberFormatException e){
643 sendMessage(context, replyTo, cannot_parse_port);
644 break;
645 }
646 Heavy.ncfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), ncfilePort);
647 break;
648
649 case PHOTO:
650 if(args.length!=3){
651 Heavy.help(context, replyTo, toNonNull(Command.PHOTO));
652 break;
653 }
654
655 final int cameraNumber;
656 try{
657 cameraNumber=Integer.parseInt(args[0]);
658 } catch (NumberFormatException e){
659 sendMessage(context, replyTo, cannot_parse_camera_number);
660 break;
661 }
662
663 final int photoPort;
664 try{
665 photoPort=Integer.parseInt(args[2]);
666 } catch (NumberFormatException e){
667 sendMessage(context, replyTo, cannot_parse_port);
668 break;
669 }
670 Heavy.photo(context, replyTo, cameraNumber, toNonNull(args[1]), photoPort);
671 break;
672
673 case SETNOTIFICATION:
674 if(args.length!=1){
675 Heavy.help(context, replyTo, toNonNull(Command.SETNOTIFICATION));
676 break;
677 }
678
679 try{
680 PreferenceManager.getDefaultSharedPreferences(context).edit()
681 .putString(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString(), replyTo.toString())
682 .commit();
683 sendMessage(context, replyTo, notification_enabled);
684 } catch (IllegalArgumentException e){
685 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
686 break;
687 }
688
689 break;
690
691 case DELNOTIFICATION:
692 if(args.length!=1){
693 Heavy.help(context, replyTo, toNonNull(Command.DELNOTIFICATION));
694 break;
695 }
696
697 try{
698 PreferenceManager.getDefaultSharedPreferences(context).edit()
699 .remove(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString())
700 .commit();
701 sendMessage(context, replyTo, notification_disabled);
702 } catch (IllegalArgumentException e){
703 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
704 break;
705 }
706
707
708 break;
709 case SETPASSWORD:
710 if(args.length > 1){
711 Heavy.help(context, replyTo, toNonNull(Command.SETPASSWORD));
712 break;
713 }
714
715 try{
716 if(args.length==0)
717 Heavy.setPassword(context, replyTo);
718 else
719 Heavy.setPassword(context, replyTo, toNonNull(args[0]));
720 } catch (SecurityException e){
721 sendMessage(context, replyTo, security_exception+e.getMessage());
722 }
723 break;
724
725 case WIPE:
726 if(args.length!=2){
727 Heavy.help(context, replyTo, toNonNull(Command.WIPE));
728 break;
729 }
730
731 if(!args[1].equalsIgnoreCase(WIPE_CONFIRM_STRING)){
732 sendMessage(context, replyTo, the_second_argument_to_wipe_must_be, WIPE_CONFIRM_STRING);
733 break;
734 }
735
736 try{
737 Heavy.wipe(context, toNonNull(WipeType.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
738 } catch (IllegalArgumentException e){
739 sendMessage(context, replyTo, wipetype_should_be_one_of, join (", ",toNonNull(WipeType.values())));
740 } catch (SecurityException e){
741 sendMessage(context, replyTo, security_exception, e.getMessage());
742 }
743 break;
744
745 case LOCK:
746 try{
747 Heavy.lock(context, replyTo);
748 } catch (SecurityException e){
749 sendMessage(context, replyTo, security_exception, e.getMessage());
750 }
751 break;
752
753 case VIEW:
754 if(args.length!=1){
755 Heavy.help(context, replyTo, toNonNull(Command.VIEW));
756 break;
757 }
758
759 Heavy.view(context, replyTo, toNonNull(Uri.parse(args[0])));
760 break;
761
762 case PLAY:
763 Heavy.musicPlayerCommand(context, replyTo, "play");
764 break;
765
766 case PAUSE:
767 Heavy.musicPlayerCommand(context, replyTo, "pause");
768 break;
769
770 case NEXT:
771 Heavy.musicPlayerCommand(context, replyTo, "next");
772 break;
773
774 case PREV:
775 Heavy.musicPlayerCommand(context, replyTo, "previous");
776 break;
777
778 case BATT:
779 Heavy.batt(context, replyTo);
780 break;
781
782 case CALLLOG:
783 if (args.length > 1) {
784 Heavy.help(context, replyTo, toNonNull(Command.CALLLOG));
785 break;
786 }
787
788 if (args.length == 0)
789 Heavy.calllog(context, replyTo, 5);
790 else {
791 try {
792 Heavy.calllog(context, replyTo, Integer.parseInt(args[0]));
793 } catch (IllegalArgumentException e){
794 sendMessage(context, replyTo, cannot_parse_count);
795 }
796 }
797 break;
798
799 case SMSLOG:
800 if (args.length > 1) {
801 Heavy.help(context, replyTo, toNonNull(Command.SMSLOG));
802 break;
803 }
804
805 if (args.length == 0)
806 Heavy.smslog(context, replyTo, 5);
807 else {
808 try {
809 Heavy.smslog(context, replyTo, Integer.parseInt(args[0]));
810 } catch (IllegalArgumentException e) {
811 sendMessage(context, replyTo, cannot_parse_count);
812 }
813 }
814 break;
815
816 case HELP:
817 if(args.length != 1){
818 Heavy.help(context, replyTo, toNonNull(Command.HELP));
819 break;
820 }
821
822 try {
823 Heavy.help(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
824 } catch (IllegalArgumentException e) {
825 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
826 }
827 break;
828
829 case LS:
830 if(args.length != 1){
831 Heavy.help(context, replyTo, toNonNull(Command.LS));
832 break;
833 }
834
835 Heavy.ls(context, replyTo, toNonNull(args[0]));
836 break;
837
838 case RM:
839 if(args.length != 1){
840 Heavy.help(context, replyTo, toNonNull(Command.RM));
841 break;
842 }
843
844 Heavy.rm(context, replyTo, toNonNull(args[0]));
845 break;
846
847 case CONTACTS:
848 if(args.length != 1){
849 Heavy.help(context, replyTo, toNonNull(Command.CONTACTS));
850 break;
851 }
852
853 Heavy.contacts(context, replyTo, toNonNull(args[0]));
854 break;
855
856 case DISABLE:
857 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
858 Heavy.help(context, replyTo, toNonNull(Command.DISABLE));
859 break;
860 }
861
862 try{
863 Heavy.disable(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
864 } catch (IllegalArgumentException e){
865 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
866 }
867 break;
868
869 case ENABLE:
870 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
871 Heavy.help(context, replyTo, toNonNull(Command.ENABLE));
872 break;
873 }
874
875 try{
876 Heavy.enable(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
877 } catch (IllegalArgumentException e){
878 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
879 }
880 break;
881
882 case POLL:
883 Heavy.poll(context, replyTo);
884 break;
885
886 case HANGUP:
887 Heavy.hangup(context, replyTo);
888 break;
889
890 case ANSWER:
891 Heavy.answer(context, replyTo);
892 break;
893
894 case LAUNCH:
895 if(args.length!=1){
896 Heavy.help(context, replyTo, toNonNull(Command.LAUNCH));
897 break;
898 }
899 Heavy.launch(context, replyTo, toNonNull(args[0]));
900 break;
901
902 case DATA:
903 if(args.length>1){
904 Heavy.help(context, replyTo, toNonNull(Command.DATA));
905 break;
906 }
907
908 if(args.length==0){
909 Heavy.data(context, replyTo);
910 break;
911 }
912 try {
913 Heavy.data(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
914 } catch(IllegalArgumentException e) {
915 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
916 }
917 break;
918
919 case GPS:
920 if(args.length>1){
921 Heavy.help(context, replyTo, toNonNull(Command.GPS));
922 break;
923 }
924
925 if(args.length==0){
926 Heavy.gps(context, replyTo);
927 break;
928 }
929
930 try {
931 Heavy.gps(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
932 } catch(IllegalArgumentException e) {
933 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
934 }
935 break;
936
937 case GLOCATION:
938 if(args.length>1){
939 Heavy.help(context, replyTo, toNonNull(Command.GLOCATION));
940 break;
941 }
942
943 if(args.length==0){
944 Heavy.glocation(context, replyTo);
945 break;
946 }
947
948 try {
949 Heavy.glocation(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
950 } catch(IllegalArgumentException e) {
951 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
952 }
953 break;
954
955 case REBOOT:
956 if(args.length>1){
957 Heavy.help(context, replyTo, toNonNull(Command.REBOOT));
958 break;
959 }
960
961 Heavy.reboot(context, replyTo, args.length==0?null:args[0]);
962 break;
963
964 case NOTIFY:
965 if(args.length!=1 && args.length!=3){
966 Heavy.help(context, replyTo, toNonNull(Command.NOTIFY));
967 return;
968 }
969
970 final int id;
971 try{
972 id=Integer.parseInt(args[0]);
973 } catch (NumberFormatException e){
974 sendMessage(context, replyTo, R.string.could_not_parse_id);
975 break;
976 }
977
978 if(args.length==1)
979 Heavy.notify(context, replyTo, id);
980 else
981 Heavy.notify(context, replyTo, id, toNonNull(args[1]), toNonNull(args[2]));
982 break;
983
984 case SCREENCAP:
985 if(args.length != 1){
986 Heavy.help(context, replyTo, toNonNull(Command.SCREENCAP));
987 return;
988 }
989
990 Heavy.screencap(context, replyTo, args[0]);
991 break;
992
993 case TORCH:
994 Heavy.torch(context, replyTo);
995 break;
996
997 case GETFILE:
998 if(args.length != 3){
999 Heavy.help(context, replyTo, toNonNull(Command.GETFILE));
1000 return;
1001 }
1002
1003 final int getfilePort;
1004 try{
1005 getfilePort=Integer.parseInt(args[2]);
1006 } catch (NumberFormatException e){
1007 sendMessage(context, replyTo, cannot_parse_port);
1008 break;
1009 }
1010 Heavy.getfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), getfilePort);
1011 break;
1012
1013 case SH:
1014 if(args.length == 0){
1015 Heavy.help(context, replyTo, toNonNull(Command.SH));
1016 return;
1017 }
1018
1019 Heavy.execute(context, replyTo, "sh", join(" ", args));
1020 break;
1021
1022 case ROOTSH:
1023 if(args.length == 0){
1024 Heavy.help(context, replyTo, toNonNull(Command.ROOTSH));
1025 return;
1026 }
1027
1028 Heavy.execute(context, replyTo, "su", join(" ", args));
1029 break;
1030 }
1031
1032 }
1033
1034 /**
1035 * Executes a given command
1036 *
1037 * @param context Context instance
1038 * @param cmd Command to execute
1039 * @param args arguments for the command
1040 * @param replyTo Address to send replies to
1041 */
1042 public static void processCommand(final Context context, final String cmd,final String[] args,final Address replyTo){
1043 final @NonNull Command command;
1044 try{
1045 command=toNonNull(Command.valueOf(cmd.toUpperCase(Locale.ENGLISH)));
1046 } catch (IllegalArgumentException e){
1047 sendMessage(context, replyTo, unknown_command, cmd.toUpperCase(Locale.ENGLISH), e.getMessage());
1048 return;
1049 }
1050
1051 try{
1052 processCommand(context, command,args,replyTo);
1053 } catch(Exception e){
1054 sendMessage(context, replyTo, error_while_processing_command, e.getClass().getName(), e.getMessage());
1055 Log.w(Utils.class.getName(), "Error while processing command", e);
1056 }
1057 }
1058 }
This page took 0.055368 seconds and 4 git commands to generate.