import java.net.MalformedURLException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import android.location.LocationManager;
import android.media.AudioManager;
import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.preference.PreferenceManager;
import android.provider.ContactsContract.PhoneLookup;
import android.telephony.SmsManager;
*/
@SuppressWarnings("javadoc")
public static enum Command{
- TOAST, ECHO, SMS, FLASH, WIFI,
+ TOAST, ECHO, SMS, SMSQ, FLASH, WIFI,
BLUETOOTH, DIAL, RING, SPEAK, VIBRATE,
DIALOG, LOCATION, NOLOCATION, RINGER, NCFILE,
PHOTO, SETNOTIFICATION, DELNOTIFICATION, SETPASSWORD, HELP,
LS, RM, CONTACTS, DISABLE, ENABLE,
POLL, HANGUP, ANSWER, LAUNCH, DATA,
GPS, GLOCATION, REBOOT, NOTIFY, SCREENCAP,
- TORCH
+ TORCH, GETFILE, SH, ROOTSH
}
/**
* @throws AssertionError if the given object is null
*/
public static <T> T toNonNull(@Nullable T object) throws AssertionError{
- if(object==null){
- Log.wtf(Utils.class.getName(), "toNonNull called with null");
- throw new AssertionError("Log.wtf did not terminate the process");
- }
+ if(object==null)
+ throw new NullPointerException();
return object;
}
sendMessage(context, address, toNonNull(context.getString(resource, args)));
}
+ /**
+ * Send a confirmation message to a certain Address. A confirm message is a message that:
+ * 1) Confers no information (except for confirming that the command was executed).
+ * 2) May be dropped if the user asked so.
+ *
+ * @param context Context instance
+ * @param address destination Address
+ * @param resource String resource for the message text
+ * @param args format parameters for the resource
+ */
+ public static void sendConfirmMessage(final Context context, final Address address, final int resource, final Object... args){
+ final SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(context);
+ if(address.protocol != Protocol.SMS || !sp.getBoolean("expensive_sms", false))
+ sendMessage(context, address, resource, args);
+ }
+
/**
* Send a notification to the user.
*
public static void sendMessage(final Context context, final Address address, final String message){
switch(address.protocol){
case HTTP:
- new HttpCallExecutableRunnable("/send", toNonNull(Arrays.asList(
- new Header("X-Destination", toNonNull(address.data)))), context, null, true, message).execute();
+ new HttpCallExecutableRunnable("/send", toNonNull(Arrays.asList(new Header("X-Destination", toNonNull(address.data)))), context, null, true, address.requestId == null ? message : address.requestId + " " + message).execute();
break;
case SMS:
- SmsManager.getDefault().sendTextMessage(address.data, null, message, null, null);
+ new Handler(Looper.getMainLooper()).post(new Runnable(){
+ @Override
+ public void run(){
+ final ArrayList<String> parts = SmsManager.getDefault().divideMessage(message);
+ SmsManager.getDefault().sendMultipartTextMessage(address.data, null, parts, null, null);
+ }
+ });
break;
case LOCAL:
* @throws MalformedURLException if the user preferences create an invalid URL
*/
public static URL getServerURL(final Context context, final String path) throws MalformedURLException{
+ final String protocol=PreferenceManager.getDefaultSharedPreferences(context).getString("protocol", "https");
final String hostname=PreferenceManager.getDefaultSharedPreferences(context).getString("hostname", "fonbot.ieval.ro");
final int port=Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString("port", "443"));
- final URL url=new URL("http", hostname, port, path);
+ final URL url=new URL(protocol, hostname, port, path);
return url;
}
Heavy.help(context, replyTo, toNonNull(Command.SMS));
break;
}
- Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args));
+ Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args), false);
+ break;
+
+ case SMSQ:
+ if(args.length < 2){
+ Heavy.help(context, replyTo, toNonNull(Command.SMSQ));
+ break;
+ }
+ Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args), true);
break;
case FLASH:
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putString(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString(), replyTo.toString())
.commit();
- sendMessage(context, replyTo, notification_enabled);
+ sendConfirmMessage(context, replyTo, notification_enabled);
} catch (IllegalArgumentException e){
sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
break;
PreferenceManager.getDefaultSharedPreferences(context).edit()
.remove(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString())
.commit();
- sendMessage(context, replyTo, notification_disabled);
+ sendConfirmMessage(context, replyTo, notification_disabled);
} catch (IllegalArgumentException e){
sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
break;
else
Heavy.setPassword(context, replyTo, toNonNull(args[0]));
} catch (SecurityException e){
- sendMessage(context, replyTo, security_exception+e.getMessage());
+ sendMessage(context, replyTo, security_exception, e.getMessage());
}
break;
case TORCH:
Heavy.torch(context, replyTo);
break;
+
+ case GETFILE:
+ if(args.length != 3){
+ Heavy.help(context, replyTo, toNonNull(Command.GETFILE));
+ return;
+ }
+
+ final int getfilePort;
+ try{
+ getfilePort=Integer.parseInt(args[2]);
+ } catch (NumberFormatException e){
+ sendMessage(context, replyTo, cannot_parse_port);
+ break;
+ }
+ Heavy.getfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), getfilePort);
+ break;
+
+ case SH:
+ if(args.length == 0){
+ Heavy.help(context, replyTo, toNonNull(Command.SH));
+ return;
+ }
+
+ Heavy.execute(context, replyTo, "sh", join(" ", args));
+ break;
+
+ case ROOTSH:
+ if(args.length == 0){
+ Heavy.help(context, replyTo, toNonNull(Command.ROOTSH));
+ return;
+ }
+
+ Heavy.execute(context, replyTo, "su", join(" ", args));
+ break;
}
}