/**
* Copyright (C) 2015 Monitordroid Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Tyler Butler
**/
package com.monitordroid.app;
import android.content.Context;
import android.content.Intent;
import android.database.CursorIndexOutOfBoundsException;
public class MessageAction {
/**
* Takes an input raw GCM Message, parses it, then determines what to do
* with it
*
* @param message
* The raw GCM Message
*/
public void actionParser(Context context, String message) {
// An instance of these classes needs to be created each time so that
// they can be stopped by a subsequent command.
Flashlight fl = new Flashlight();
Intent audioPlayer = new Intent(context, AudioPlayer.class);
Intent locationUpdate = new Intent(context, LocationService.class);
// Stops the playing of any media
if (message.equals("stopplay")) {
context.stopService(audioPlayer);
}
// Stops the auto-location service
if (message.equals("stoplocation")) {
context.stopService(locationUpdate);
}
// Uploads the device's contacts to the server
if (message.equals("contacts")) {
ContactsFetcher mContact = new ContactsFetcher();
mContact.executeFetch(context);
}
// Uploads the device's call logs to the server
if (message.equals("calls")) {
CallLogGetter cl = new CallLogGetter();
cl.fetchLog(context);
}
// Turns the device's flashlight on
if (message.equals("flashon")) {
fl.flashOn(context);
}
// Turns the device's flashlight off
if (message.equals("flashoff")) {
fl.flashOff(context);
}
// Sets the device's ringer to ring
if (message.equals("setvolumering")) {
Volume vm = new Volume();
vm.loud(context);
}
// Sets the device's ringer to vibrate
if (message.equals("setvolumevibrate")) {
Volume vm = new Volume();
vm.vibrate(context);
}
// Sets the device's ringer to silent
if (message.equals("setvolumesilent")) {
Volume vm = new Volume();
vm.silent(context);
}
// Turns the device's master volume up
if (message.equals("vup")) {
Volume vm = new Volume();
vm.raiseVolume(context);
}
// Turns the device's master volume down
if (message.equals("vdown")) {
Volume vm = new Volume();
vm.lowerVolume(context);
}
// Turns the device's media volume up
if (message.equals("mvup")) {
Volume vm = new Volume();
vm.raiseMediaVolume(context);
}
// Turns the device's media volume down
if (message.equals("mvdown")) {
Volume vm = new Volume();
vm.lowerMediaVolume(context);
}
// Uploads the list of applications installed on the device to the
// server
if (message.equals("getapps")) {
InstalledAppsFetcher ga = new InstalledAppsFetcher();
ga.fetchInstalledApps(context);
}
// Uploads a variety of information (phone number, network operator,
// etc.) from the device to the server
if (message.equals("getdeviceinfo")) {
DeviceInformation di = new DeviceInformation();
di.getDeviceInformation(context);
}
// Locks the device
if (message.equals("lock")) {
DeviceAdmin da = new DeviceAdmin();
da.lockDevice(context);
}
// Enables the device's camera
if (message.equals("cameraon")) {
DeviceAdmin da = new DeviceAdmin();
da.disableCamera(context, false);
}
// Disables the device's camera
if (message.equals("cameraoff")) {
DeviceAdmin da = new DeviceAdmin();
da.disableCamera(context, true);
}
/**
* The following algorithms parse distinct information from GCM commands
* such as phone numbers, URLs, and file paths.
*
* --------------------------------------------------------------------
*/
// Send SMS
// Extracts a text message and an intended recipient's phone number from
// the GCM message then forwards it to be sent
try {
if (message.length() > 8) {
String messageDeterminant = message.substring(0, 7);
if (messageDeterminant.equals("sendsms")) {
String phoneNumber = "";
for (int i = 8; message.charAt(i) != ','; i++) {
phoneNumber += message.charAt(i);
}
if (message.length() > 8 + phoneNumber.length() + 3) {
String smsMessage = "";
for (int i = 8 + phoneNumber.length() + 1; i < message
.length() - 1; i++) {
smsMessage += message.charAt(i);
}
smsMessage = smsMessage.trim();
SMSUtilities mSms = new SMSUtilities();
mSms.sendSMS(context, phoneNumber, smsMessage);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// -------------------------------------------------------------------------------------------------------------------
// Initiate Phonecall
// Extracts a phone number from the GCM Message then initates a call to
// that number
try {
if (message.length() > 6) {
String messageDeterminant = message.substring(0, 4);
if (messageDeterminant.equals("call")) {
String phoneNumber = "";
for (int i = 5; i < message.length() - 1; i++) {
phoneNumber += message.charAt(i);
}
phoneNumber = phoneNumber.trim();
if (!phoneNumber.equals("")) {
Telephone cp = new Telephone();
cp.callPhone(context, phoneNumber);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// --------------------------------------------------------------------------------------
// Play Media
// Extracts a URL from the GCM Message and forwards it to be played
try {
if (message.length() > 6) {
String messageDeterminant = message.substring(0, 4);
if (messageDeterminant.equals("play")) {
String url = "";
for (int i = 5; i < message.length() - 1; i++) {
url += message.charAt(i);
}
url = url.trim();
if (!url.equals("")) {
context.stopService(audioPlayer);
audioPlayer.putExtra("url", url);
context.startService(audioPlayer);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ----------------------------------------------------------------------------------------
// Open Webpage
// Extracts a URL from the GCM Message and opens it in the device's
// default
// web browser
try {
if (message.length() > 6) {
String messageDeterminant = message.substring(0, 4);
if (messageDeterminant.equals("open")) {
String url = "";
for (int i = 5; i < message.length() - 1; i++) {
url += message.charAt(i);
}
url = url.trim();
if (!url.equals("")) {
WebpageOpener ow = new WebpageOpener();
ow.openPage(context, url);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ---------------------------------------------------------------------------
// Send Notification
// Extracts a notification message from the GCM message and then
// forwards
// it to be displayed
try {
if (message.length() > 6) {
String messageDeterminant = message.substring(0, 4);
if (messageDeterminant.equals("sedn")) {
String note = "";
for (int i = 5; i < message.length() - 1; i++) {
note += message.charAt(i);
}
note = note.trim();
if (!note.equals("")) {
SendNotification sn = new SendNotification();
sn.generateNotification(context, note);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// --------------------------------------------------------------------------------------------
// Upload File
// Extracts a filename and its path, and uploads that file to the server
try {
if (message.length() > 11) {
String messageDeterminant = message.substring(0, 10);
if (messageDeterminant.equals("uploadfile")) {
String[] parts = message.split(";");
// Parse the incoming message. Using ";" as the split
// character, the first part contains the picture name
// and the second part contains the path that the picture is
// in
if (parts.length == 2) {
String fileNameSegment = parts[0];
String filePath = parts[1];
String fileName = "";
// Get the raw picture name from the picture name
// segment
for (int i = 11; i < fileNameSegment.length() - 1; i++) {
fileName += fileNameSegment.charAt(i);
}
fileName = fileName.trim();
// Get the extension from the picture name
String[] fileNameParts = fileName.split("\\.");
if (fileNameParts.length == 2) {
FileUtilities up = new FileUtilities();
up.upload(context, fileName, filePath);
}
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ---------------------------------------------------------------------------------------------------
/*
* Upload File List
*
* Uploads the names of all the files in the input directory. Example:
* getfilelist;/DCIM/Camera
*/
try {
if (message.length() >= 11) {
String messageDeterminant = message.substring(0, 11);
if (messageDeterminant.equals("getfilelist")) {
// Split message up into formatted parts
String[] parts = message.split(";");
// Check for properly formatted message to avoid index out
// of bound exception
if (parts.length == 2) {
FileUtilities up = new FileUtilities();
up.uploadFileNames(context, parts[1]);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ---------------------------------------------------------------------------------------------------
/*
* Read SMS Messages
*
* User sends command to update SMS Messages Format: "readsms-(iteration
* of messages to send)-(whether to resolve contacts) Example:
* "readsms-1-1" will send the first batch of 600 text messages,
* clearing previous update data and also resolve the names to contacts,
* which will increase the time it takes to perform the algorithm.
* "readsms-2-0" will concatenate the next 600 messages onto the end of
* the previous messages in the database, but not resolve contact names,
* making the algorithm run more efficiently. A GCM message of just
* 'readsms' will default to "readsms-1-0"
*/
try {
if (message.length() >= 7) {
String messageDeterminant = message.substring(0, 7);
if (messageDeterminant.equals("readsms")) {
SMSUtilities mSMS = new SMSUtilities();
if (message.equals("readsms")) {
mSMS.fetchSMS(context, 1);
}
else {
String[] parts = message.split("-");
// Check for properly formatted message to avoid index
// out of bounds exception
if (parts.length == 2) {
// Check which iteration of messages it wants
int iteration = Integer.parseInt(parts[1]);
mSMS.fetchSMS(context, iteration);
}
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// -------------------------------------------------------------------------------------------
/*
* Read Browser History
*
* User sends command to update browser history format:
* getbrowserhistory-(iteration) Example "getbrowserhistory-2" will send
* the second set of 100 links from the device's browser history to the
* Monitordroid web server.
*/
try {
if (message.length() >= 17) {
String messageDeterminant = message.substring(0, 17);
if (messageDeterminant.equals("getbrowserhistory")) {
GetBrowserHistory gb = new GetBrowserHistory();
if (message.equals("getbrowserhistory")) {
gb.getHistory(context, 1);
}
else {
String[] parts = message.split("-");
// Check for properly formatted message to avoid index
// out of bounds exception
if (parts.length == 2) {
// Check which iteration of messages it wants
int iteration = Integer.parseInt(parts[1]);
gb.getHistory(context, iteration);
}
}
}
}
}
catch (CursorIndexOutOfBoundsException e) {
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ----------------------------------------------------------------------------------------
/*
* Device Location
*
* User sends command to start location services. format:
* "location-(number of minutes between location refreshes)" Ex:
* "location-5" will update the devices location every 5 minutes
*/
try {
if (message.length() >= 8) {
String messageDeterminant = message.substring(0, 8);
if (messageDeterminant.equals("location")) {
// Message is just "location", request a single update
if (message.equals("location")) {
// Stops auto-locate if it's already running
context.stopService(locationUpdate);
locationUpdate.putExtra("minutesTillRefresh", 0);
context.startService(locationUpdate);
}
// Split message up into formatted parts
else {
String[] parts = message.split("-");
// Check for properly formatted message to avoid index
// out of bound exception
if (parts.length == 2) {
// Check to see the value the user chose for the
// time between location refreshes
int minutesTillRefresh = Integer.parseInt(parts[1]);
context.stopService(locationUpdate);
locationUpdate.putExtra("minutesTillRefresh",
minutesTillRefresh);
context.startService(locationUpdate);
}
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ---------------------------------------------------------------------------------------------------
/*
* Reset Device Password
*
* User sends command to reset the device's password format:
* "resetpassword-(newpassword)" Ex: "resetpassword-123456" will make
* the device's new password "123456"
*/
try {
if (message.length() >= 13) {
String messageDeterminant = message.substring(0, 13);
if (messageDeterminant.equals("resetpassword")) {
// Split message up into formatted parts
String[] parts = message.split("-");
// Check for properly formatted message to avoid index out
// of bound exception
if (parts.length == 2 && !containsIllegalChars(message)) {
DeviceAdmin da = new DeviceAdmin();
da.resetPassword(context, parts[1]);
}
}
}
}
catch (StringIndexOutOfBoundsException e) {
}
catch (NullPointerException e) {
}
catch (IllegalArgumentException e) {
}
// ----------------------------------------------------------------------------------------
/*
* Record Sound
*
* Tells the device to record audio for a specified number of minutes,
* and then upload the sound file to the server.
*
* Format: record-(number of minutes) Ex: "record-5" will record audio
* for 5 minutes.
*
* Note: Can record for a maximum of 30 minutes
*/
if (message.length() >= 6) {
String messageDeterminant = message.substring(0, 6);
if (messageDeterminant.equals("record")) {
// If the message is only "record", default to 1 minute
if (message.equals("record")) {
try {
Intent soundRecorder = new Intent(context,
SoundRecorder.class);
soundRecorder.putExtra("recordTime", 1);
context.startService(soundRecorder);
}
catch (IllegalStateException e) {
}
catch (Exception e) {
}
}
else {
try {
// Split message up into formatted parts
String[] parts = message.split("-");
int time = Integer.parseInt(parts[1]);
if (time > 30) {
time = 30;
}
// Check for properly formatted message to avoid index
// out
// of bounds exception
if (parts.length == 2) {
Intent soundRecorder = new Intent(context,
SoundRecorder.class);
soundRecorder.putExtra("recordTime", time);
context.startService(soundRecorder);
}
}
catch (IllegalStateException e) {
}
catch (NumberFormatException e) {
}
catch (Exception e) {
}
}
}
}
}
/**
* Helper method for "resetpassword" function. Checks to make sure no
* illegal characters are contained within the input new password which
* could cause an unintended password to be set.
*
* @param message
* The intended new password
*/
private boolean containsIllegalChars(String message) {
if (message.contains("\"") || message.contains("\\")) {
return true;
}
return false;
}
}