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