Let users disable command confirmations over SMS
[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, SMSQ, 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 confirmation message to a certain Address. A confirm message is a message that:
276 * 1) Confers no information (except for confirming that the command was executed).
277 * 2) May be dropped if the user asked so.
278 *
279 * @param context Context instance
280 * @param address destination Address
281 * @param resource String resource for the message text
282 * @param args format parameters for the resource
283 */
284 public static void sendConfirmMessage(final Context context, final Address address, final int resource, final Object... args){
285 final SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(context);
286 if(address.protocol != Protocol.SMS || !sp.getBoolean("expensive_sms", false))
287 sendMessage(context, address, resource, args);
288 }
289
290 /**
291 * Send a notification to the user.
292 *
293 * @param context Context instance
294 * @param type notification type
295 * @param msg the notification text
296 */
297 public static void sendMessage(final Context context, final MessageType type,final String msg){
298 final SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(context);
299 final String address=sp.getString(type.toString(),null);
300 if(address==null)
301 return;
302 sendMessage(context, new Address(address), msg);
303 }
304
305 /**
306 * Send a message to a certain Address.
307 *
308 * @param context Context instance
309 * @param address destination Address
310 * @param message the message text
311 */
312 public static void sendMessage(final Context context, final Address address, final String message){
313 switch(address.protocol){
314 case HTTP:
315 new HttpCallExecutableRunnable("/send", toNonNull(Arrays.asList(new Header("X-Destination", toNonNull(address.data)))), context, null, true, address.requestId == null ? message : address.requestId + " " + message).execute();
316 break;
317
318 case SMS:
319 new Handler(Looper.getMainLooper()).post(new Runnable(){
320 @Override
321 public void run(){
322 final ArrayList<String> parts = SmsManager.getDefault().divideMessage(message);
323 SmsManager.getDefault().sendMultipartTextMessage(address.data, null, parts, null, null);
324 }
325 });
326 break;
327
328 case LOCAL:
329 final Intent intent = new Intent(FonBotLocalActivity.RESPONSE_RECEIVED_ACTION);
330 intent.putExtra(FonBotLocalActivity.EXTRA_RESPONSE, message);
331 context.sendBroadcast(intent);
332 break;
333
334 case NULL:
335 break;//blackhole
336 }
337 }
338
339 /**
340 * Splits a string into words.
341 *
342 * @param string the string
343 * @return an array of words
344 */
345 public static String[] shellwords(final String string){
346 return toNonNull(string.split("[ ]+(?=([^\"]*\"[^\"]*\")*[^\"]*$)"));//TODO: Make this handle backslash escapes
347 }
348
349 /**
350 * Returns the name associated with a phone number.
351 *
352 * @param context Context instance
353 * @param number phone number to search for
354 * @return the name associated with this number, or null if the number was not found in the contacts.
355 */
356 public static @Nullable String callerId(final Context context, final String number){
357 final Cursor cursor=context.getContentResolver().query(
358 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)),
359 new String[]{PhoneLookup.DISPLAY_NAME},
360 null,
361 null,
362 null);
363
364 if(cursor.moveToFirst()){
365 final String name=cursor.getString(0);
366 cursor.close();
367 return name;
368 }
369 cursor.close();
370 return null;
371 }
372
373 /**
374 * Registers an ongoing event.
375 *
376 * @param context Context instance
377 * @param event event to register
378 */
379 public static void registerOngoing(final Context context, final OngoingEvent event){
380 final Intent intent=new Intent(context, FonBotMainService.class);
381 intent.setAction(FonBotMainService.ACTION_PUT_ONGOING);
382 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
383 context.startService(intent);
384 }
385
386 /**
387 * Unregisters an ongoing event
388 *
389 * @param context Context instance
390 * @param event event to unregister
391 */
392 public static void unregisterOngoing(final Context context, final OngoingEvent event){
393 final Intent intent=new Intent(context, FonBotMainService.class);
394 intent.setAction(FonBotMainService.ACTION_DELETE_ONGOING);
395 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
396 context.startService(intent);
397 }
398
399 /**
400 * Gets the server URL according to the user preferences.
401 *
402 * @param context Context instance
403 * @param path URL path
404 * @return the server URL
405 * @throws MalformedURLException if the user preferences create an invalid URL
406 */
407 public static URL getServerURL(final Context context, final String path) throws MalformedURLException{
408 final String protocol=PreferenceManager.getDefaultSharedPreferences(context).getString("protocol", "https");
409 final String hostname=PreferenceManager.getDefaultSharedPreferences(context).getString("hostname", "fonbot.ieval.ro");
410 final int port=Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString("port", "443"));
411 final URL url=new URL(protocol, hostname, port, path);
412 return url;
413 }
414
415 /**
416 * Executes a given command
417 *
418 * @param context Context instance
419 * @param cmd Command to execute
420 * @param args arguments for the command
421 * @param replyTo Address to send replies to
422 */
423 private static void processCommand(final Context context, final Command cmd,final String[] args,final Address replyTo){
424 if(Heavy.isCommandDisabled(context, cmd)){
425 sendMessage(context, replyTo, command_disabled, cmd.toString());
426 return;
427 }
428
429 switch(cmd){
430 case TOAST:
431 if(args.length < 1 || args.length > 2){
432 Heavy.help(context, replyTo, toNonNull(Command.TOAST));
433 break;
434 }
435
436 if(args.length==1)
437 Heavy.toast(context, replyTo, toNonNull(args[0]));
438 else {
439 try {
440 switch(ToastLength.valueOf(args[1].toUpperCase(Locale.ENGLISH))){
441 case LONG:
442 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_LONG);
443 break;
444 case SHORT:
445 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_SHORT);
446 }
447 } catch(IllegalArgumentException e){
448 sendMessage(context, replyTo, invalid_length_allowed_values_are, join(", ",toNonNull(ToastLength.values())));
449 }
450 }
451 break;
452
453 case ECHO:
454 if(args.length==0){
455 Heavy.help(context, replyTo, toNonNull(Command.ECHO));
456 break;
457 }
458 sendMessage(context, replyTo, join(" ",args));
459 break;
460
461 case SMS:
462 if(args.length < 2){
463 Heavy.help(context, replyTo, toNonNull(Command.SMS));
464 break;
465 }
466 Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args), false);
467 break;
468
469 case SMSQ:
470 if(args.length < 2){
471 Heavy.help(context, replyTo, toNonNull(Command.SMSQ));
472 break;
473 }
474 Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args), true);
475 break;
476
477 case FLASH:
478 if(args.length != 1){
479 Heavy.help(context, replyTo, toNonNull(Command.FLASH));
480 break;
481 }
482
483 try {
484 Heavy.flash(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
485 } catch(IllegalArgumentException e) {
486 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
487 }
488 break;
489
490 case WIFI:
491 if(args.length>1){
492 Heavy.help(context, replyTo, toNonNull(Command.WIFI));
493 break;
494 }
495 if(args.length==0)
496 Heavy.wifi(context, replyTo);
497 else {
498 try {
499 Heavy.wifi(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
500 } catch(IllegalArgumentException e) {
501 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
502 }
503 }
504 break;
505
506 case BLUETOOTH:
507 if(args.length>1){
508 Heavy.help(context, replyTo, toNonNull(Command.BLUETOOTH));
509 break;
510 }
511 if(args.length==0)
512 Heavy.bluetooth(context, replyTo);
513 else {
514 try {
515 Heavy.bluetooth(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 DIAL:
523 if(args.length!=1){
524 Heavy.help(context, replyTo, toNonNull(Command.DIAL));
525 break;
526 }
527 Heavy.dial(context, replyTo, toNonNull(args[0]));
528 break;
529
530 case RING:
531 if(args.length>1){
532 Heavy.help(context, replyTo, toNonNull(Command.RING));
533 break;
534 }
535 if(args.length==0)
536 Heavy.ring(context, replyTo);
537 else {
538 try {
539 Heavy.ring(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
540 } catch(IllegalArgumentException e){
541 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
542 }
543 }
544 break;
545
546 case SPEAK:
547 if(args.length==0){
548 Heavy.help(context, replyTo, toNonNull(Command.SPEAK));
549 break;
550 }
551 Heavy.speak(context, replyTo, join(" ",args));
552 break;
553
554 case VIBRATE:
555 if(args.length!=1){
556 Heavy.help(context, replyTo, toNonNull(Command.VIBRATE));
557 break;
558 }
559 final long ms;
560 try{
561 ms=Long.parseLong(args[0]);
562 } catch(NumberFormatException e){
563 sendMessage(context, replyTo, could_not_parse_ms);
564 break;
565 }
566 Heavy.vibrate(context, replyTo, ms);
567 break;
568
569 case DIALOG://TODO: Should add an edittext
570 if(args.length<1){
571 Heavy.help(context, replyTo, toNonNull(Command.DIALOG));
572 break;
573 }
574 final String[] buttons=new String[args.length-1];
575 System.arraycopy(args,1,buttons,0,buttons.length);
576 Heavy.dialog(context, replyTo, toNonNull(args[0]), buttons);
577 break;
578
579 case LOCATION:
580 if(args.length>3||args.length<1){
581 Heavy.help(context, replyTo, toNonNull(Command.LOCATION));
582 break;
583 }
584
585 final @NonNull String provider;
586 try{
587 switch(LocationProvider.valueOf(args[0].toUpperCase(Locale.ENGLISH))){
588 case GPS:
589 provider=toNonNull(LocationManager.GPS_PROVIDER);
590 break;
591 case NETWORK:
592 default:
593 provider=toNonNull(LocationManager.NETWORK_PROVIDER);
594 break;
595 }
596 } catch(IllegalArgumentException e){
597 sendMessage(context, replyTo, cannot_parse_provider_allowed_values_are, join(", ",toNonNull(LocationProvider.values())));
598 break;
599 }
600
601 final long minTime;
602 final float minDistance;
603
604 if(args.length>1)
605 try{
606 minTime=Long.parseLong(args[1]);
607 } catch (NumberFormatException e){
608 sendMessage(context, replyTo, cannot_parse_min_time);
609 break;
610 }
611 else
612 minTime=500;
613
614 if(args.length>2)
615 try{
616 minDistance=Float.parseFloat(args[2]);
617 } catch (NumberFormatException e){
618 sendMessage(context, replyTo, cannot_parse_min_distance);
619 break;
620 }
621 else
622 minDistance=0;
623 Heavy.location(context, replyTo, provider, minTime, minDistance);
624 break;
625
626 case NOLOCATION:
627 Heavy.nolocation(context, replyTo);
628 break;
629
630 case RINGER:
631 if(args.length>1){
632 Heavy.help(context, replyTo, toNonNull(Command.RINGER));
633 break;
634 }
635 if(args.length==0)
636 Heavy.ringer(context, replyTo);
637 else{
638 try{
639 final RingerMode rm=RingerMode.valueOf(args[0].toUpperCase(Locale.ENGLISH));
640 switch(rm){
641 case NORMAL:
642 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_NORMAL);
643 break;
644 case VIBRATE:
645 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_VIBRATE);
646 break;
647 case SILENT:
648 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_SILENT);
649 break;
650 }
651 } catch (IllegalArgumentException e){
652 Utils.sendMessage(context, replyTo, invalid_ringer_mode_valid_values_are, join(", ",toNonNull(RingerMode.values())));
653 }
654 }
655 break;
656
657 case NCFILE:
658 if(args.length!=3){
659 Heavy.help(context, replyTo, toNonNull(Command.NCFILE));
660 break;
661 }
662
663 final int ncfilePort;
664 try{
665 ncfilePort=Integer.parseInt(args[2]);
666 } catch (NumberFormatException e){
667 sendMessage(context, replyTo, cannot_parse_port);
668 break;
669 }
670 Heavy.ncfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), ncfilePort);
671 break;
672
673 case PHOTO:
674 if(args.length!=3){
675 Heavy.help(context, replyTo, toNonNull(Command.PHOTO));
676 break;
677 }
678
679 final int cameraNumber;
680 try{
681 cameraNumber=Integer.parseInt(args[0]);
682 } catch (NumberFormatException e){
683 sendMessage(context, replyTo, cannot_parse_camera_number);
684 break;
685 }
686
687 final int photoPort;
688 try{
689 photoPort=Integer.parseInt(args[2]);
690 } catch (NumberFormatException e){
691 sendMessage(context, replyTo, cannot_parse_port);
692 break;
693 }
694 Heavy.photo(context, replyTo, cameraNumber, toNonNull(args[1]), photoPort);
695 break;
696
697 case SETNOTIFICATION:
698 if(args.length!=1){
699 Heavy.help(context, replyTo, toNonNull(Command.SETNOTIFICATION));
700 break;
701 }
702
703 try{
704 PreferenceManager.getDefaultSharedPreferences(context).edit()
705 .putString(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString(), replyTo.toString())
706 .commit();
707 sendConfirmMessage(context, replyTo, notification_enabled);
708 } catch (IllegalArgumentException e){
709 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
710 break;
711 }
712
713 break;
714
715 case DELNOTIFICATION:
716 if(args.length!=1){
717 Heavy.help(context, replyTo, toNonNull(Command.DELNOTIFICATION));
718 break;
719 }
720
721 try{
722 PreferenceManager.getDefaultSharedPreferences(context).edit()
723 .remove(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString())
724 .commit();
725 sendConfirmMessage(context, replyTo, notification_disabled);
726 } catch (IllegalArgumentException e){
727 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
728 break;
729 }
730
731
732 break;
733 case SETPASSWORD:
734 if(args.length > 1){
735 Heavy.help(context, replyTo, toNonNull(Command.SETPASSWORD));
736 break;
737 }
738
739 try{
740 if(args.length==0)
741 Heavy.setPassword(context, replyTo);
742 else
743 Heavy.setPassword(context, replyTo, toNonNull(args[0]));
744 } catch (SecurityException e){
745 sendMessage(context, replyTo, security_exception, e.getMessage());
746 }
747 break;
748
749 case WIPE:
750 if(args.length!=2){
751 Heavy.help(context, replyTo, toNonNull(Command.WIPE));
752 break;
753 }
754
755 if(!args[1].equalsIgnoreCase(WIPE_CONFIRM_STRING)){
756 sendMessage(context, replyTo, the_second_argument_to_wipe_must_be, WIPE_CONFIRM_STRING);
757 break;
758 }
759
760 try{
761 Heavy.wipe(context, toNonNull(WipeType.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
762 } catch (IllegalArgumentException e){
763 sendMessage(context, replyTo, wipetype_should_be_one_of, join (", ",toNonNull(WipeType.values())));
764 } catch (SecurityException e){
765 sendMessage(context, replyTo, security_exception, e.getMessage());
766 }
767 break;
768
769 case LOCK:
770 try{
771 Heavy.lock(context, replyTo);
772 } catch (SecurityException e){
773 sendMessage(context, replyTo, security_exception, e.getMessage());
774 }
775 break;
776
777 case VIEW:
778 if(args.length!=1){
779 Heavy.help(context, replyTo, toNonNull(Command.VIEW));
780 break;
781 }
782
783 Heavy.view(context, replyTo, toNonNull(Uri.parse(args[0])));
784 break;
785
786 case PLAY:
787 Heavy.musicPlayerCommand(context, replyTo, "play");
788 break;
789
790 case PAUSE:
791 Heavy.musicPlayerCommand(context, replyTo, "pause");
792 break;
793
794 case NEXT:
795 Heavy.musicPlayerCommand(context, replyTo, "next");
796 break;
797
798 case PREV:
799 Heavy.musicPlayerCommand(context, replyTo, "previous");
800 break;
801
802 case BATT:
803 Heavy.batt(context, replyTo);
804 break;
805
806 case CALLLOG:
807 if (args.length > 1) {
808 Heavy.help(context, replyTo, toNonNull(Command.CALLLOG));
809 break;
810 }
811
812 if (args.length == 0)
813 Heavy.calllog(context, replyTo, 5);
814 else {
815 try {
816 Heavy.calllog(context, replyTo, Integer.parseInt(args[0]));
817 } catch (IllegalArgumentException e){
818 sendMessage(context, replyTo, cannot_parse_count);
819 }
820 }
821 break;
822
823 case SMSLOG:
824 if (args.length > 1) {
825 Heavy.help(context, replyTo, toNonNull(Command.SMSLOG));
826 break;
827 }
828
829 if (args.length == 0)
830 Heavy.smslog(context, replyTo, 5);
831 else {
832 try {
833 Heavy.smslog(context, replyTo, Integer.parseInt(args[0]));
834 } catch (IllegalArgumentException e) {
835 sendMessage(context, replyTo, cannot_parse_count);
836 }
837 }
838 break;
839
840 case HELP:
841 if(args.length != 1){
842 Heavy.help(context, replyTo, toNonNull(Command.HELP));
843 break;
844 }
845
846 try {
847 Heavy.help(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
848 } catch (IllegalArgumentException e) {
849 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
850 }
851 break;
852
853 case LS:
854 if(args.length != 1){
855 Heavy.help(context, replyTo, toNonNull(Command.LS));
856 break;
857 }
858
859 Heavy.ls(context, replyTo, toNonNull(args[0]));
860 break;
861
862 case RM:
863 if(args.length != 1){
864 Heavy.help(context, replyTo, toNonNull(Command.RM));
865 break;
866 }
867
868 Heavy.rm(context, replyTo, toNonNull(args[0]));
869 break;
870
871 case CONTACTS:
872 if(args.length != 1){
873 Heavy.help(context, replyTo, toNonNull(Command.CONTACTS));
874 break;
875 }
876
877 Heavy.contacts(context, replyTo, toNonNull(args[0]));
878 break;
879
880 case DISABLE:
881 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
882 Heavy.help(context, replyTo, toNonNull(Command.DISABLE));
883 break;
884 }
885
886 try{
887 Heavy.disable(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
888 } catch (IllegalArgumentException e){
889 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
890 }
891 break;
892
893 case ENABLE:
894 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
895 Heavy.help(context, replyTo, toNonNull(Command.ENABLE));
896 break;
897 }
898
899 try{
900 Heavy.enable(context, replyTo, toNonNull(Command.valueOf(args[0].toUpperCase(Locale.ENGLISH))));
901 } catch (IllegalArgumentException e){
902 sendMessage(context, replyTo, no_such_command_command_list, join(", ", toNonNull(Command.values())));
903 }
904 break;
905
906 case POLL:
907 Heavy.poll(context, replyTo);
908 break;
909
910 case HANGUP:
911 Heavy.hangup(context, replyTo);
912 break;
913
914 case ANSWER:
915 Heavy.answer(context, replyTo);
916 break;
917
918 case LAUNCH:
919 if(args.length!=1){
920 Heavy.help(context, replyTo, toNonNull(Command.LAUNCH));
921 break;
922 }
923 Heavy.launch(context, replyTo, toNonNull(args[0]));
924 break;
925
926 case DATA:
927 if(args.length>1){
928 Heavy.help(context, replyTo, toNonNull(Command.DATA));
929 break;
930 }
931
932 if(args.length==0){
933 Heavy.data(context, replyTo);
934 break;
935 }
936 try {
937 Heavy.data(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
938 } catch(IllegalArgumentException e) {
939 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
940 }
941 break;
942
943 case GPS:
944 if(args.length>1){
945 Heavy.help(context, replyTo, toNonNull(Command.GPS));
946 break;
947 }
948
949 if(args.length==0){
950 Heavy.gps(context, replyTo);
951 break;
952 }
953
954 try {
955 Heavy.gps(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
956 } catch(IllegalArgumentException e) {
957 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
958 }
959 break;
960
961 case GLOCATION:
962 if(args.length>1){
963 Heavy.help(context, replyTo, toNonNull(Command.GLOCATION));
964 break;
965 }
966
967 if(args.length==0){
968 Heavy.glocation(context, replyTo);
969 break;
970 }
971
972 try {
973 Heavy.glocation(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
974 } catch(IllegalArgumentException e) {
975 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
976 }
977 break;
978
979 case REBOOT:
980 if(args.length>1){
981 Heavy.help(context, replyTo, toNonNull(Command.REBOOT));
982 break;
983 }
984
985 Heavy.reboot(context, replyTo, args.length==0?null:args[0]);
986 break;
987
988 case NOTIFY:
989 if(args.length!=1 && args.length!=3){
990 Heavy.help(context, replyTo, toNonNull(Command.NOTIFY));
991 return;
992 }
993
994 final int id;
995 try{
996 id=Integer.parseInt(args[0]);
997 } catch (NumberFormatException e){
998 sendMessage(context, replyTo, R.string.could_not_parse_id);
999 break;
1000 }
1001
1002 if(args.length==1)
1003 Heavy.notify(context, replyTo, id);
1004 else
1005 Heavy.notify(context, replyTo, id, toNonNull(args[1]), toNonNull(args[2]));
1006 break;
1007
1008 case SCREENCAP:
1009 if(args.length != 1){
1010 Heavy.help(context, replyTo, toNonNull(Command.SCREENCAP));
1011 return;
1012 }
1013
1014 Heavy.screencap(context, replyTo, args[0]);
1015 break;
1016
1017 case TORCH:
1018 Heavy.torch(context, replyTo);
1019 break;
1020
1021 case GETFILE:
1022 if(args.length != 3){
1023 Heavy.help(context, replyTo, toNonNull(Command.GETFILE));
1024 return;
1025 }
1026
1027 final int getfilePort;
1028 try{
1029 getfilePort=Integer.parseInt(args[2]);
1030 } catch (NumberFormatException e){
1031 sendMessage(context, replyTo, cannot_parse_port);
1032 break;
1033 }
1034 Heavy.getfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), getfilePort);
1035 break;
1036
1037 case SH:
1038 if(args.length == 0){
1039 Heavy.help(context, replyTo, toNonNull(Command.SH));
1040 return;
1041 }
1042
1043 Heavy.execute(context, replyTo, "sh", join(" ", args));
1044 break;
1045
1046 case ROOTSH:
1047 if(args.length == 0){
1048 Heavy.help(context, replyTo, toNonNull(Command.ROOTSH));
1049 return;
1050 }
1051
1052 Heavy.execute(context, replyTo, "su", join(" ", args));
1053 break;
1054 }
1055
1056 }
1057
1058 /**
1059 * Executes a given command
1060 *
1061 * @param context Context instance
1062 * @param cmd Command to execute
1063 * @param args arguments for the command
1064 * @param replyTo Address to send replies to
1065 */
1066 public static void processCommand(final Context context, final String cmd,final String[] args,final Address replyTo){
1067 final @NonNull Command command;
1068 try{
1069 command=toNonNull(Command.valueOf(cmd.toUpperCase(Locale.ENGLISH)));
1070 } catch (IllegalArgumentException e){
1071 sendMessage(context, replyTo, unknown_command, cmd.toUpperCase(Locale.ENGLISH), e.getMessage());
1072 return;
1073 }
1074
1075 try{
1076 processCommand(context, command,args,replyTo);
1077 } catch(Exception e){
1078 sendMessage(context, replyTo, error_while_processing_command, e.getClass().getName(), e.getMessage());
1079 Log.w(Utils.class.getName(), "Error while processing command", e);
1080 }
1081 }
1082 }
This page took 0.056591 seconds and 4 git commands to generate.