gui: Move action functions to function pointer map.

This allows the functions to be more readable and make
doActions readable.

Patch set 5: gui: remove threading in GUIAction

Multiple actions were started in another thread that was joined
immediately after starting it, so the input thread was blocked anyway.

Selected single actions were started in their own thread, but this
caused bugs like being able to install the same package twice in
parallel by quickly swiping the slider twice.

Change-Id: I28adadaedd032efc7bff3aaa48e659627aa3a3b3
diff --git a/gui/action.cpp b/gui/action.cpp
index ff2c2e0..d1daab7 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -53,11 +53,6 @@
 #include "../minadbd/adb.h"
 #include "../adb_install.h"
 #include "../set_metadata.h"
-
-int TWinstall_zip(const char* path, int* wipe_cache);
-void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm);
-int gui_console_only();
-int gui_start();
 };
 
 #include "rapidxml.hpp"
@@ -69,6 +64,11 @@
 
 void curtainClose(void);
 
+GUIAction::mapFunc GUIAction::mf;
+static string zip_queue[10];
+static int zip_queue_index;
+static pthread_t terminal_command;
+
 GUIAction::GUIAction(xml_node<>* node)
 	: GUIObject(node)
 {
@@ -78,6 +78,65 @@
 
 	if (!node)  return;
 
+	if (mf.empty()) {
+		mf["reboot"] = &GUIAction::reboot;
+		mf["home"] = &GUIAction::home;
+		mf["key"] = &GUIAction::key;
+		mf["page"] = &GUIAction::page;
+		mf["reload"] = &GUIAction::reload;
+		mf["readBackup"] = &GUIAction::readBackup;
+		mf["set"] = &GUIAction::set;
+		mf["clear"] = &GUIAction::clear;
+		mf["mount"] = &GUIAction::mount;
+		mf["unmount"] = &GUIAction::unmount;
+		mf["umount"] = &GUIAction::unmount;
+		mf["restoredefaultsettings"] = &GUIAction::restoredefaultsettings;
+		mf["copylog"] = &GUIAction::copylog;
+		mf["compute"] = &GUIAction::compute;
+		mf["addsubtract"] = &GUIAction::compute;
+		mf["setguitimezone"] = &GUIAction::setguitimezone;
+		mf["overlay"] = &GUIAction::overlay;
+		mf["queuezip"] = &GUIAction::queuezip;
+		mf["cancelzip"] = &GUIAction::cancelzip;
+		mf["queueclear"] = &GUIAction::queueclear;
+		mf["sleep"] = &GUIAction::sleep;
+		mf["appenddatetobackupname"] = &GUIAction::appenddatetobackupname;
+		mf["generatebackupname"] = &GUIAction::generatebackupname;
+		mf["checkpartitionlist"] = &GUIAction::checkpartitionlist;
+		mf["getpartitiondetails"] = &GUIAction::getpartitiondetails;
+		mf["screenshot"] = &GUIAction::screenshot;
+		mf["setbrightness"] = &GUIAction::setbrightness;
+
+		// threaded actions
+		mf["fileexists"] = &GUIAction::fileexists;
+		mf["flash"] = &GUIAction::flash;
+		mf["wipe"] = &GUIAction::wipe;
+		mf["refreshsizes"] = &GUIAction::refreshsizes;
+		mf["nandroid"] = &GUIAction::nandroid;
+		mf["fixpermissions"] = &GUIAction::fixpermissions;
+		mf["dd"] = &GUIAction::dd;
+		mf["partitionsd"] = &GUIAction::partitionsd;
+		mf["installhtcdumlock"] = &GUIAction::installhtcdumlock;
+		mf["htcdumlockrestoreboot"] = &GUIAction::htcdumlockrestoreboot;
+		mf["htcdumlockreflashrecovery"] = &GUIAction::htcdumlockreflashrecovery;
+		mf["cmd"] = &GUIAction::cmd;
+		mf["terminalcommand"] = &GUIAction::terminalcommand;
+		mf["killterminal"] = &GUIAction::killterminal;
+		mf["reinjecttwrp"] = &GUIAction::reinjecttwrp;
+		mf["checkbackupname"] = &GUIAction::checkbackupname;
+		mf["decrypt"] = &GUIAction::decrypt;
+		mf["adbsideload"] = &GUIAction::adbsideload;
+		mf["adbsideloadcancel"] = &GUIAction::adbsideloadcancel;
+		mf["openrecoveryscript"] = &GUIAction::openrecoveryscript;
+		mf["installsu"] = &GUIAction::installsu;
+		mf["fixsu"] = &GUIAction::fixsu;
+		mf["decrypt_backup"] = &GUIAction::decrypt_backup;
+		mf["repair"] = &GUIAction::repair;
+		mf["changefilesystem"] = &GUIAction::changefilesystem;
+		mf["startmtp"] = &GUIAction::startmtp;
+		mf["stopmtp"] = &GUIAction::stopmtp;
+	}
+
 	// First, get the action
 	actions = node->first_node("actions");
 	if (actions)	child = actions->first_node("action");
@@ -199,7 +258,7 @@
 	}
 }
 
-int GUIAction::flash_zip(std::string filename, std::string pageName, const int simulate, int* wipe_cache)
+int GUIAction::flash_zip(std::string filename, std::string pageName, int* wipe_cache)
 {
 	int ret_val = 0;
 
@@ -214,17 +273,12 @@
 	// We're going to jump to this page first, like a loading page
 	gui_changePage(pageName);
 
-	int fd = -1;
-	ZipArchive zip;
-
 	if (!PartitionManager.Mount_By_Path(filename, true))
 		return -1;
 
+	// TODO: why again?
 	gui_changePage(pageName);
 
-	if (fd >= 0)
-		close(fd);
-
 	if (simulate) {
 		simulate_progress_bar();
 	} else {
@@ -252,73 +306,35 @@
 
 int GUIAction::doActions()
 {
-	if (mActions.size() < 1)	return -1;
-	if (mActions.size() == 1)
-		return doAction(mActions.at(0), 0);
+	if (mActions.size() < 1)
+		return -1;
 
-	// For multi-action, we always use a thread
-	pthread_t t;
-	pthread_attr_t tattr;
-
-	if (pthread_attr_init(&tattr)) {
-		LOGERR("Unable to pthread_attr_init\n");
-		return -1;
-	}
-	if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
-		LOGERR("Error setting pthread_attr_setdetachstate\n");
-		return -1;
-	}
-	if (pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM)) {
-		LOGERR("Error setting pthread_attr_setscope\n");
-		return -1;
-	}
-	/*if (pthread_attr_setstacksize(&tattr, 524288)) {
-		LOGERR("Error setting pthread_attr_setstacksize\n");
-		return -1;
-	}
-	*/
-	int ret = pthread_create(&t, &tattr, thread_start, this);
-	if (ret) {
-		LOGERR("Unable to create more threads for actions... continuing in same thread! %i\n", ret);
-		thread_start(this);
-	} else {
-		if (pthread_join(t, NULL)) {
-			LOGERR("Error joining threads\n");
-		}
-	}
-	if (pthread_attr_destroy(&tattr)) {
-		LOGERR("Failed to pthread_attr_destroy\n");
-		return -1;
-	}
+	std::vector<Action>::iterator it;
+	for (it = mActions.begin(); it != mActions.end(); ++it)
+		doAction(*it);
 
 	return 0;
 }
 
-void* GUIAction::thread_start(void *cookie)
+int GUIAction::doAction(Action action)
 {
-	GUIAction* ourThis = (GUIAction*) cookie;
+	DataManager::GetValue(TW_SIMULATE_ACTIONS, simulate);
 
-	DataManager::SetValue(TW_ACTION_BUSY, 1);
+	std::string function = gui_parse_text(action.mFunction);
+	std::string arg = gui_parse_text(action.mArg);
 
-	if (ourThis->mActions.size() > 1)
-	{
-		std::vector<Action>::iterator iter;
-		for (iter = ourThis->mActions.begin(); iter != ourThis->mActions.end(); iter++)
-			ourThis->doAction(*iter, 1);
-	}
-	else
-	{
-		ourThis->doAction(ourThis->mActions.at(0), 1);
-	}
-	int check = 0;
-	DataManager::GetValue("tw_background_thread_running", check);
-	if (check == 0)
-		DataManager::SetValue(TW_ACTION_BUSY, 0);
-	return NULL;
+	// find function and execute it
+	mapFunc::const_iterator funcitr = mf.find(function);
+	if (funcitr != mf.end())
+		return (this->*funcitr->second)(arg);
+
+	LOGERR("Unknown action '%s'\n", function.c_str());
+	return -1;
 }
 
 void GUIAction::operation_start(const string operation_name)
 {
+	LOGINFO("operation_start: '%s'\n", operation_name.c_str());
 	time(&Start);
 	DataManager::SetValue(TW_ACTION_BUSY, 1);
 	DataManager::SetValue("ui_progress", 0);
@@ -327,7 +343,7 @@
 	DataManager::SetValue("tw_operation_state", 0);
 }
 
-void GUIAction::operation_end(const int operation_status, const int simulate)
+void GUIAction::operation_end(const int operation_status)
 {
 	time_t Stop;
 	int simulate_fail;
@@ -354,670 +370,666 @@
 	time(&Stop);
 	if ((int) difftime(Stop, Start) > 10)
 		DataManager::Vibrate("tw_action_vibrate");
+	LOGINFO("operation_end - status=%d\n", operation_status);
 }
 
-int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
+int GUIAction::reboot(std::string arg)
 {
-	static string zip_queue[10];
-	static int zip_queue_index;
-	static pthread_t terminal_command;
-	int simulate;
+	//curtainClose(); this sometimes causes a crash
 
-	std::string arg = gui_parse_text(action.mArg);
+	sync();
+	DataManager::SetValue("tw_gui_done", 1);
+	DataManager::SetValue("tw_reboot_arg", arg);
 
-	std::string function = gui_parse_text(action.mFunction);
+	return 0;
+}
 
-	DataManager::GetValue(TW_SIMULATE_ACTIONS, simulate);
+int GUIAction::home(std::string arg)
+{
+	PageManager::SelectPackage("TWRP");
+	gui_changePage("main");
+	return 0;
+}
 
-	if (function == "reboot")
+int GUIAction::key(std::string arg)
+{
+	const int key = getKeyByName(arg);
+	PageManager::NotifyKey(key, true);
+	PageManager::NotifyKey(key, false);
+	return 0;
+}
+
+int GUIAction::page(std::string arg)
+{
+	std::string page_name = gui_parse_text(arg);
+	return gui_changePage(page_name);
+}
+
+int GUIAction::reload(std::string arg)
+{
+	int check = 0, ret_val = 0;
+	std::string theme_path;
+
+	operation_start("Reload Theme");
+	theme_path = DataManager::GetSettingsStoragePath();
+	if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
+		LOGERR("Unable to mount %s during reload function startup.\n", theme_path.c_str());
+		check = 1;
+	}
+
+	theme_path += "/TWRP/theme/ui.zip";
+	if (check != 0 || PageManager::ReloadPackage("TWRP", theme_path) != 0)
 	{
-			//curtainClose(); this sometimes causes a crash
-
-		sync();
-		DataManager::SetValue("tw_gui_done", 1);
-		DataManager::SetValue("tw_reboot_arg", arg);
-
-		return 0;
-	}
-	if (function == "home")
-	{
-		PageManager::SelectPackage("TWRP");
-		gui_changePage("main");
-		return 0;
-	}
-
-	if (function == "key")
-	{
-		const int key = getKeyByName(arg);
-		PageManager::NotifyKey(key, true);
-		PageManager::NotifyKey(key, false);
-		return 0;
-	}
-
-	if (function == "page") {
-		std::string page_name = gui_parse_text(arg);
-		return gui_changePage(page_name);
-	}
-
-	if (function == "reload") {
-		int check = 0, ret_val = 0;
-		std::string theme_path;
-
-		operation_start("Reload Theme");
-		theme_path = DataManager::GetSettingsStoragePath();
-		if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
-			LOGERR("Unable to mount %s during reload function startup.\n", theme_path.c_str());
-			check = 1;
-		}
-
-		theme_path += "/TWRP/theme/ui.zip";
-		if (check != 0 || PageManager::ReloadPackage("TWRP", theme_path) != 0)
+		// Loading the custom theme failed - try loading the stock theme
+		LOGINFO("Attempting to reload stock theme...\n");
+		if (PageManager::ReloadPackage("TWRP", "/res/ui.xml"))
 		{
-			// Loading the custom theme failed - try loading the stock theme
-			LOGINFO("Attempting to reload stock theme...\n");
-			if (PageManager::ReloadPackage("TWRP", "/res/ui.xml"))
-			{
-				LOGERR("Failed to load base packages.\n");
-				ret_val = 1;
-			}
+			LOGERR("Failed to load base packages.\n");
+			ret_val = 1;
 		}
-		operation_end(ret_val, simulate);
-		return 0;
 	}
+	operation_end(ret_val);
+	return 0;
+}
 
-	if (function == "readBackup")
+int GUIAction::readBackup(std::string arg)
+{
+	string Restore_Name;
+	DataManager::GetValue("tw_restore", Restore_Name);
+	PartitionManager.Set_Restore_Files(Restore_Name);
+	return 0;
+}
+
+int GUIAction::set(std::string arg)
+{
+	if (arg.find('=') != string::npos)
 	{
-		string Restore_Name;
-		DataManager::GetValue("tw_restore", Restore_Name);
-		PartitionManager.Set_Restore_Files(Restore_Name);
-		return 0;
-	}
+		string varName = arg.substr(0, arg.find('='));
+		string value = arg.substr(arg.find('=') + 1, string::npos);
 
-	if (function == "set")
-	{
-		if (arg.find('=') != string::npos)
-		{
-			string varName = arg.substr(0, arg.find('='));
-			string value = arg.substr(arg.find('=') + 1, string::npos);
-
-			DataManager::GetValue(value, value);
-			DataManager::SetValue(varName, value);
-		}
-		else
-			DataManager::SetValue(arg, "1");
-		return 0;
+		DataManager::GetValue(value, value);
+		DataManager::SetValue(varName, value);
 	}
-	if (function == "clear")
-	{
-		DataManager::SetValue(arg, "0");
-		return 0;
-	}
+	else
+		DataManager::SetValue(arg, "1");
+	return 0;
+}
 
-	if (function == "mount") {
-		if (arg == "usb") {
-			DataManager::SetValue(TW_ACTION_BUSY, 1);
-			if (!simulate)
-				PartitionManager.usb_storage_enable();
-			else
-				gui_print("Simulating actions...\n");
-		} else if (!simulate) {
-			PartitionManager.Mount_By_Path(arg, true);
-			PartitionManager.Add_MTP_Storage(arg);
-		} else
-			gui_print("Simulating actions...\n");
-		return 0;
-	}
+int GUIAction::clear(std::string arg)
+{
+	DataManager::SetValue(arg, "0");
+	return 0;
+}
 
-	if (function == "umount" || function == "unmount") {
-		if (arg == "usb") {
-			if (!simulate)
-				PartitionManager.usb_storage_disable();
-			else
-				gui_print("Simulating actions...\n");
-			DataManager::SetValue(TW_ACTION_BUSY, 0);
-		} else if (!simulate) {
-			PartitionManager.UnMount_By_Path(arg, true);
-		} else
-			gui_print("Simulating actions...\n");
-		return 0;
-	}
-
-	if (function == "restoredefaultsettings")
-	{
-		operation_start("Restore Defaults");
-		if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting
-			gui_print("Simulating actions...\n");
-		else {
-			DataManager::ResetDefaults();
-			PartitionManager.Update_System_Details();
-			PartitionManager.Mount_Current_Storage(true);
-		}
-		operation_end(0, simulate);
-		return 0;
-	}
-
-	if (function == "copylog")
-	{
-		operation_start("Copy Log");
+int GUIAction::mount(std::string arg)
+{
+	if (arg == "usb") {
+		DataManager::SetValue(TW_ACTION_BUSY, 1);
 		if (!simulate)
-		{
-			string dst;
-			PartitionManager.Mount_Current_Storage(true);
-			dst = DataManager::GetCurrentStoragePath() + "/recovery.log";
-			TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755);
-			tw_set_default_metadata(dst.c_str());
-			sync();
-			gui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str());
-		} else
-			simulate_progress_bar();
-		operation_end(0, simulate);
+			PartitionManager.usb_storage_enable();
+		else
+			gui_print("Simulating actions...\n");
+	} else if (!simulate) {
+		PartitionManager.Mount_By_Path(arg, true);
+		PartitionManager.Add_MTP_Storage(arg);
+	} else
+		gui_print("Simulating actions...\n");
+	return 0;
+}
+
+int GUIAction::unmount(std::string arg)
+{
+	if (arg == "usb") {
+		if (!simulate)
+			PartitionManager.usb_storage_disable();
+		else
+			gui_print("Simulating actions...\n");
+		DataManager::SetValue(TW_ACTION_BUSY, 0);
+	} else if (!simulate) {
+		PartitionManager.UnMount_By_Path(arg, true);
+	} else
+		gui_print("Simulating actions...\n");
+	return 0;
+}
+
+int GUIAction::restoredefaultsettings(std::string arg)
+{
+	operation_start("Restore Defaults");
+	if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting
+		gui_print("Simulating actions...\n");
+	else {
+		DataManager::ResetDefaults();
+		PartitionManager.Update_System_Details();
+		PartitionManager.Mount_Current_Storage(true);
+	}
+	operation_end(0);
+	return 0;
+}
+
+int GUIAction::copylog(std::string arg)
+{
+	operation_start("Copy Log");
+	if (!simulate)
+	{
+		string dst;
+		PartitionManager.Mount_Current_Storage(true);
+		dst = DataManager::GetCurrentStoragePath() + "/recovery.log";
+		TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755);
+		tw_set_default_metadata(dst.c_str());
+		sync();
+		gui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str());
+	} else
+		simulate_progress_bar();
+	operation_end(0);
+	return 0;
+}
+
+
+int GUIAction::compute(std::string arg)
+{
+	if (arg.find("+") != string::npos)
+	{
+		string varName = arg.substr(0, arg.find('+'));
+		string string_to_add = arg.substr(arg.find('+') + 1, string::npos);
+		int amount_to_add = atoi(string_to_add.c_str());
+		int value;
+
+		DataManager::GetValue(varName, value);
+		DataManager::SetValue(varName, value + amount_to_add);
 		return 0;
 	}
-
-	if (function == "compute" || function == "addsubtract")
+	if (arg.find("-") != string::npos)
 	{
-		if (arg.find("+") != string::npos)
-		{
-			string varName = arg.substr(0, arg.find('+'));
-			string string_to_add = arg.substr(arg.find('+') + 1, string::npos);
-			int amount_to_add = atoi(string_to_add.c_str());
-			int value;
+		string varName = arg.substr(0, arg.find('-'));
+		string string_to_subtract = arg.substr(arg.find('-') + 1, string::npos);
+		int amount_to_subtract = atoi(string_to_subtract.c_str());
+		int value;
 
+		DataManager::GetValue(varName, value);
+		value -= amount_to_subtract;
+		if (value <= 0)
+			value = 0;
+		DataManager::SetValue(varName, value);
+		return 0;
+	}
+	if (arg.find("*") != string::npos)
+	{
+		string varName = arg.substr(0, arg.find('*'));
+		string multiply_by_str = gui_parse_text(arg.substr(arg.find('*') + 1, string::npos));
+		int multiply_by = atoi(multiply_by_str.c_str());
+		int value;
+
+		DataManager::GetValue(varName, value);
+		DataManager::SetValue(varName, value*multiply_by);
+		return 0;
+	}
+	if (arg.find("/") != string::npos)
+	{
+		string varName = arg.substr(0, arg.find('/'));
+		string divide_by_str = gui_parse_text(arg.substr(arg.find('/') + 1, string::npos));
+		int divide_by = atoi(divide_by_str.c_str());
+		int value;
+
+		if(divide_by != 0)
+		{
 			DataManager::GetValue(varName, value);
-			DataManager::SetValue(varName, value + amount_to_add);
-			return 0;
-		}
-		if (arg.find("-") != string::npos)
-		{
-			string varName = arg.substr(0, arg.find('-'));
-			string string_to_subtract = arg.substr(arg.find('-') + 1, string::npos);
-			int amount_to_subtract = atoi(string_to_subtract.c_str());
-			int value;
-
-			DataManager::GetValue(varName, value);
-			value -= amount_to_subtract;
-			if (value <= 0)
-				value = 0;
-			DataManager::SetValue(varName, value);
-			return 0;
-		}
-		if (arg.find("*") != string::npos)
-		{
-			string varName = arg.substr(0, arg.find('*'));
-			string multiply_by_str = gui_parse_text(arg.substr(arg.find('*') + 1, string::npos));
-			int multiply_by = atoi(multiply_by_str.c_str());
-			int value;
-
-			DataManager::GetValue(varName, value);
-			DataManager::SetValue(varName, value*multiply_by);
-			return 0;
-		}
-		if (arg.find("/") != string::npos)
-		{
-			string varName = arg.substr(0, arg.find('/'));
-			string divide_by_str = gui_parse_text(arg.substr(arg.find('/') + 1, string::npos));
-			int divide_by = atoi(divide_by_str.c_str());
-			int value;
-
-			if(divide_by != 0)
-			{
-				DataManager::GetValue(varName, value);
-				DataManager::SetValue(varName, value/divide_by);
-			}
-			return 0;
-		}
-		LOGERR("Unable to perform compute '%s'\n", arg.c_str());
-		return -1;
-	}
-
-	if (function == "setguitimezone")
-	{
-		string SelectedZone;
-		DataManager::GetValue(TW_TIME_ZONE_GUISEL, SelectedZone); // read the selected time zone into SelectedZone
-		string Zone = SelectedZone.substr(0, SelectedZone.find(';')); // parse to get time zone
-		string DSTZone = SelectedZone.substr(SelectedZone.find(';') + 1, string::npos); // parse to get DST component
-
-		int dst;
-		DataManager::GetValue(TW_TIME_ZONE_GUIDST, dst); // check wether user chose to use DST
-
-		string offset;
-		DataManager::GetValue(TW_TIME_ZONE_GUIOFFSET, offset); // pull in offset
-
-		string NewTimeZone = Zone;
-		if (offset != "0")
-			NewTimeZone += ":" + offset;
-
-		if (dst != 0)
-			NewTimeZone += DSTZone;
-
-		DataManager::SetValue(TW_TIME_ZONE_VAR, NewTimeZone);
-		DataManager::update_tz_environment_variables();
-		return 0;
-	}
-
-	if (function == "togglestorage") {
-		LOGERR("togglestorage action was deprecated from TWRP\n");
-		return 0;
-	}
-
-	if (function == "overlay")
-		return gui_changeOverlay(arg);
-
-	if (function == "queuezip")
-	{
-		if (zip_queue_index >= 10) {
-			gui_print("Maximum zip queue reached!\n");
-			return 0;
-		}
-		DataManager::GetValue("tw_filename", zip_queue[zip_queue_index]);
-		if (strlen(zip_queue[zip_queue_index].c_str()) > 0) {
-			zip_queue_index++;
-			DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+			DataManager::SetValue(varName, value/divide_by);
 		}
 		return 0;
 	}
+	LOGERR("Unable to perform compute '%s'\n", arg.c_str());
+	return -1;
+}
 
-	if (function == "cancelzip")
-	{
-		if (zip_queue_index <= 0) {
-			gui_print("Minimum zip queue reached!\n");
-			return 0;
-		} else {
-			zip_queue_index--;
-			DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
-		}
+int GUIAction::setguitimezone(std::string arg)
+{
+	string SelectedZone;
+	DataManager::GetValue(TW_TIME_ZONE_GUISEL, SelectedZone); // read the selected time zone into SelectedZone
+	string Zone = SelectedZone.substr(0, SelectedZone.find(';')); // parse to get time zone
+	string DSTZone = SelectedZone.substr(SelectedZone.find(';') + 1, string::npos); // parse to get DST component
+
+	int dst;
+	DataManager::GetValue(TW_TIME_ZONE_GUIDST, dst); // check wether user chose to use DST
+
+	string offset;
+	DataManager::GetValue(TW_TIME_ZONE_GUIOFFSET, offset); // pull in offset
+
+	string NewTimeZone = Zone;
+	if (offset != "0")
+		NewTimeZone += ":" + offset;
+
+	if (dst != 0)
+		NewTimeZone += DSTZone;
+
+	DataManager::SetValue(TW_TIME_ZONE_VAR, NewTimeZone);
+	DataManager::update_tz_environment_variables();
+	return 0;
+}
+
+int GUIAction::overlay(std::string arg)
+{
+	return gui_changeOverlay(arg);
+}
+
+int GUIAction::queuezip(std::string arg)
+{
+	if (zip_queue_index >= 10) {
+		gui_print("Maximum zip queue reached!\n");
 		return 0;
 	}
-
-	if (function == "queueclear")
-	{
-		zip_queue_index = 0;
+	DataManager::GetValue("tw_filename", zip_queue[zip_queue_index]);
+	if (strlen(zip_queue[zip_queue_index].c_str()) > 0) {
+		zip_queue_index++;
 		DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+	}
+	return 0;
+}
+
+int GUIAction::cancelzip(std::string arg)
+{
+	if (zip_queue_index <= 0) {
+		gui_print("Minimum zip queue reached!\n");
 		return 0;
+	} else {
+		zip_queue_index--;
+		DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
 	}
+	return 0;
+}
 
-	if (function == "sleep")
-	{
-		operation_start("Sleep");
-		usleep(atoi(arg.c_str()));
-		operation_end(0, simulate);
-		return 0;
-	}
+int GUIAction::queueclear(std::string arg)
+{
+	zip_queue_index = 0;
+	DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+	return 0;
+}
 
-	if (function == "appenddatetobackupname")
-	{
-		operation_start("AppendDateToBackupName");
-		string Backup_Name;
-		DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
-		Backup_Name += TWFunc::Get_Current_Date();
-		if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
-			Backup_Name.resize(MAX_BACKUP_NAME_LEN);
-		DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
-		operation_end(0, simulate);
-		return 0;
-	}
+int GUIAction::sleep(std::string arg)
+{
+	operation_start("Sleep");
+	usleep(atoi(arg.c_str()));
+	operation_end(0);
+	return 0;
+}
 
-	if (function == "generatebackupname")
-	{
-		operation_start("GenerateBackupName");
-		TWFunc::Auto_Generate_Backup_Name();
-		operation_end(0, simulate);
-		return 0;
-	}
-	if (function == "checkpartitionlist") {
-		string Wipe_List, wipe_path;
-		int count = 0;
+int GUIAction::appenddatetobackupname(std::string arg)
+{
+	operation_start("AppendDateToBackupName");
+	string Backup_Name;
+	DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
+	Backup_Name += TWFunc::Get_Current_Date();
+	if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
+		Backup_Name.resize(MAX_BACKUP_NAME_LEN);
+	DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
+	operation_end(0);
+	return 0;
+}
 
-		DataManager::GetValue("tw_wipe_list", Wipe_List);
-		LOGINFO("checkpartitionlist list '%s'\n", Wipe_List.c_str());
-		if (!Wipe_List.empty()) {
-			size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
-			while (end_pos != string::npos && start_pos < Wipe_List.size()) {
-				wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
-				LOGINFO("checkpartitionlist wipe_path '%s'\n", wipe_path.c_str());
-				if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") {
-					// Do nothing
-				} else {
-					count++;
-				}
-				start_pos = end_pos + 1;
-				end_pos = Wipe_List.find(";", start_pos);
-			}
-			DataManager::SetValue("tw_check_partition_list", count);
-		} else {
-			DataManager::SetValue("tw_check_partition_list", 0);
-		}
-		return 0;
-	}
-	if (function == "getpartitiondetails") {
-		string Wipe_List, wipe_path;
-		int count = 0;
+int GUIAction::generatebackupname(std::string arg)
+{
+	operation_start("GenerateBackupName");
+	TWFunc::Auto_Generate_Backup_Name();
+	operation_end(0);
+	return 0;
+}
 
-		DataManager::GetValue("tw_wipe_list", Wipe_List);
-		LOGINFO("getpartitiondetails list '%s'\n", Wipe_List.c_str());
-		if (!Wipe_List.empty()) {
-			size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
-			while (end_pos != string::npos && start_pos < Wipe_List.size()) {
-				wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
-				LOGINFO("getpartitiondetails wipe_path '%s'\n", wipe_path.c_str());
-				if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") {
-					// Do nothing
-				} else {
-					DataManager::SetValue("tw_partition_path", wipe_path);
-					break;
-				}
-				start_pos = end_pos + 1;
-				end_pos = Wipe_List.find(";", start_pos);
-			}
-			if (!wipe_path.empty()) {
-				TWPartition* Part = PartitionManager.Find_Partition_By_Path(wipe_path);
-				if (Part) {
-					unsigned long long mb = 1048576;
+int GUIAction::checkpartitionlist(std::string arg)
+{
+	string Wipe_List, wipe_path;
+	int count = 0;
 
-					DataManager::SetValue("tw_partition_name", Part->Display_Name);
-					DataManager::SetValue("tw_partition_mount_point", Part->Mount_Point);
-					DataManager::SetValue("tw_partition_file_system", Part->Current_File_System);
-					DataManager::SetValue("tw_partition_size", Part->Size / mb);
-					DataManager::SetValue("tw_partition_used", Part->Used / mb);
-					DataManager::SetValue("tw_partition_free", Part->Free / mb);
-					DataManager::SetValue("tw_partition_backup_size", Part->Backup_Size / mb);
-					DataManager::SetValue("tw_partition_removable", Part->Removable);
-					DataManager::SetValue("tw_partition_is_present", Part->Is_Present);
-
-					if (Part->Can_Repair())
-						DataManager::SetValue("tw_partition_can_repair", 1);
-					else
-						DataManager::SetValue("tw_partition_can_repair", 0);
-					if (TWFunc::Path_Exists("/sbin/mkdosfs"))
-						DataManager::SetValue("tw_partition_vfat", 1);
-					else
-						DataManager::SetValue("tw_partition_vfat", 0);
-					if (TWFunc::Path_Exists("/sbin/mkfs.exfat"))
-						DataManager::SetValue("tw_partition_exfat", 1);
-					else
-						DataManager::SetValue("tw_partition_exfat", 0);
-					if (TWFunc::Path_Exists("/sbin/mkfs.f2fs"))
-						DataManager::SetValue("tw_partition_f2fs", 1);
-					else
-						DataManager::SetValue("tw_partition_f2fs", 0);
-					if (TWFunc::Path_Exists("/sbin/mke2fs"))
-						DataManager::SetValue("tw_partition_ext", 1);
-					else
-						DataManager::SetValue("tw_partition_ext", 0);
-					return 0;
-				} else {
-					LOGERR("Unable to locate partition: '%s'\n", wipe_path.c_str());
-				}
-			}
-		}
-		DataManager::SetValue("tw_partition_name", "");
-		DataManager::SetValue("tw_partition_file_system", "");
-		return 0;
-	}
-
-	if (function == "screenshot")
-	{
-		time_t tm;
-		char path[256];
-		int path_len;
-		uid_t uid = -1;
-		gid_t gid = -1;
-
-		struct passwd *pwd = getpwnam("media_rw");
-		if(pwd) {
-			uid = pwd->pw_uid;
-			gid = pwd->pw_gid;
-		}
-
-		const std::string storage = DataManager::GetCurrentStoragePath();
-		if(PartitionManager.Is_Mounted_By_Path(storage)) {
-			snprintf(path, sizeof(path), "%s/Pictures/Screenshots/", storage.c_str());
-		} else {
-			strcpy(path, "/tmp/");
-		}
-
-		if(!TWFunc::Create_Dir_Recursive(path, 0666, uid, gid))
-			return 0;
-
-		tm = time(NULL);
-		path_len = strlen(path);
-
-		// Screenshot_2014-01-01-18-21-38.png
-		strftime(path+path_len, sizeof(path)-path_len, "Screenshot_%Y-%m-%d-%H-%M-%S.png", localtime(&tm));
-
-		int res = gr_save_screenshot(path);
-		if(res == 0) {
-			chmod(path, 0666);
-			chown(path, uid, gid);
-
-			gui_print("Screenshot was saved to %s\n", path);
-
-			// blink to notify that the screenshow was taken
-			gr_color(255, 255, 255, 255);
-			gr_fill(0, 0, gr_fb_width(), gr_fb_height());
-			gr_flip();
-			gui_forceRender();
-		} else {
-			LOGERR("Failed to take a screenshot!\n");
-		}
-		return 0;
-	}
-
-	if (function == "setbrightness")
-	{
-		return TWFunc::Set_Brightness(arg);
-	}
-
-	if (isThreaded)
-	{
-		if (function == "fileexists")
-		{
-			struct stat st;
-			string newpath = arg + "/.";
-
-			operation_start("FileExists");
-			if (stat(arg.c_str(), &st) == 0 || stat(newpath.c_str(), &st) == 0)
-				operation_end(0, simulate);
-			else
-				operation_end(1, simulate);
-			return 0;
-		}
-
-		if (function == "flash")
-		{
-			int i, ret_val = 0, wipe_cache = 0;
-
-			for (i=0; i<zip_queue_index; i++) {
-				operation_start("Flashing");
-				DataManager::SetValue("tw_filename", zip_queue[i]);
-				DataManager::SetValue(TW_ZIP_INDEX, (i + 1));
-
-				TWFunc::SetPerformanceMode(true);
-				ret_val = flash_zip(zip_queue[i], arg, simulate, &wipe_cache);
-				TWFunc::SetPerformanceMode(false);
-				if (ret_val != 0) {
-					gui_print("Error flashing zip '%s'\n", zip_queue[i].c_str());
-					i = 10; // Error flashing zip - exit queue
-					ret_val = 1;
-				}
-			}
-			zip_queue_index = 0;
-			DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
-
-			if (wipe_cache)
-				PartitionManager.Wipe_By_Path("/cache");
-
-			if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
-				operation_start("ReinjectTWRP");
-				gui_print("Injecting TWRP into boot image...\n");
-				if (simulate) {
-					simulate_progress_bar();
-				} else {
-					TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
-					if (Boot == NULL || Boot->Current_File_System != "emmc")
-						TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
-					else {
-						string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device;
-						TWFunc::Exec_Cmd(injectcmd);
-					}
-					gui_print("TWRP injection complete.\n");
-				}
-			}
-			PartitionManager.Update_System_Details();
-			operation_end(ret_val, simulate);
-			return 0;
-		}
-		if (function == "wipe")
-		{
-			operation_start("Format");
-			DataManager::SetValue("tw_partition", arg);
-
-			int ret_val = false;
-
-			if (simulate) {
-				simulate_progress_bar();
+	DataManager::GetValue("tw_wipe_list", Wipe_List);
+	LOGINFO("checkpartitionlist list '%s'\n", Wipe_List.c_str());
+	if (!Wipe_List.empty()) {
+		size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
+		while (end_pos != string::npos && start_pos < Wipe_List.size()) {
+			wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
+			LOGINFO("checkpartitionlist wipe_path '%s'\n", wipe_path.c_str());
+			if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") {
+				// Do nothing
 			} else {
-				if (arg == "data")
-					ret_val = PartitionManager.Factory_Reset();
-				else if (arg == "battery")
-					ret_val = PartitionManager.Wipe_Battery_Stats();
-				else if (arg == "rotate")
-					ret_val = PartitionManager.Wipe_Rotate_Data();
-				else if (arg == "dalvik")
-					ret_val = PartitionManager.Wipe_Dalvik_Cache();
-				else if (arg == "DATAMEDIA") {
-					ret_val = PartitionManager.Format_Data();
-				} else if (arg == "INTERNAL") {
-					int has_datamedia, dual_storage;
+				count++;
+			}
+			start_pos = end_pos + 1;
+			end_pos = Wipe_List.find(";", start_pos);
+		}
+		DataManager::SetValue("tw_check_partition_list", count);
+	} else {
+		DataManager::SetValue("tw_check_partition_list", 0);
+	}
+		return 0;
+}
 
-					DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
-					if (has_datamedia) {
-						ret_val = PartitionManager.Wipe_Media_From_Data();
-					} else {
-						ret_val = PartitionManager.Wipe_By_Path(DataManager::GetSettingsStoragePath());
-					}
-				} else if (arg == "EXTERNAL") {
-					string External_Path;
+int GUIAction::getpartitiondetails(std::string arg)
+{
+	string Wipe_List, wipe_path;
+	int count = 0;
 
-					DataManager::GetValue(TW_EXTERNAL_PATH, External_Path);
-					ret_val = PartitionManager.Wipe_By_Path(External_Path);
-				} else if (arg == "ANDROIDSECURE") {
-					ret_val = PartitionManager.Wipe_Android_Secure();
-				} else if (arg == "LIST") {
-					string Wipe_List, wipe_path;
-					bool skip = false;
-					ret_val = true;
-					TWPartition* wipe_part = NULL;
+	DataManager::GetValue("tw_wipe_list", Wipe_List);
+	LOGINFO("getpartitiondetails list '%s'\n", Wipe_List.c_str());
+	if (!Wipe_List.empty()) {
+		size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
+		while (end_pos != string::npos && start_pos < Wipe_List.size()) {
+			wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
+			LOGINFO("getpartitiondetails wipe_path '%s'\n", wipe_path.c_str());
+			if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") {
+				// Do nothing
+			} else {
+				DataManager::SetValue("tw_partition_path", wipe_path);
+				break;
+			}
+			start_pos = end_pos + 1;
+			end_pos = Wipe_List.find(";", start_pos);
+		}
+		if (!wipe_path.empty()) {
+			TWPartition* Part = PartitionManager.Find_Partition_By_Path(wipe_path);
+			if (Part) {
+				unsigned long long mb = 1048576;
 
-					DataManager::GetValue("tw_wipe_list", Wipe_List);
-					LOGINFO("wipe list '%s'\n", Wipe_List.c_str());
-					if (!Wipe_List.empty()) {
-						size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
-						while (end_pos != string::npos && start_pos < Wipe_List.size()) {
-							wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
-							LOGINFO("wipe_path '%s'\n", wipe_path.c_str());
-							if (wipe_path == "/and-sec") {
-								if (!PartitionManager.Wipe_Android_Secure()) {
-									LOGERR("Unable to wipe android secure\n");
-									ret_val = false;
-									break;
-								} else {
-									skip = true;
-								}
-							} else if (wipe_path == "DALVIK") {
-								if (!PartitionManager.Wipe_Dalvik_Cache()) {
-									LOGERR("Failed to wipe dalvik\n");
-									ret_val = false;
-									break;
-								} else {
-									skip = true;
-								}
-							} else if (wipe_path == "INTERNAL") {
-								if (!PartitionManager.Wipe_Media_From_Data()) {
-									ret_val = false;
-									break;
-								} else {
-									skip = true;
-								}
-							}
-							if (!skip) {
-								if (!PartitionManager.Wipe_By_Path(wipe_path)) {
-									LOGERR("Unable to wipe '%s'\n", wipe_path.c_str());
-									ret_val = false;
-									break;
-								} else if (wipe_path == DataManager::GetSettingsStoragePath()) {
-									arg = wipe_path;
-								}
-							} else {
-								skip = false;
-							}
-							start_pos = end_pos + 1;
-							end_pos = Wipe_List.find(";", start_pos);
+				DataManager::SetValue("tw_partition_name", Part->Display_Name);
+				DataManager::SetValue("tw_partition_mount_point", Part->Mount_Point);
+				DataManager::SetValue("tw_partition_file_system", Part->Current_File_System);
+				DataManager::SetValue("tw_partition_size", Part->Size / mb);
+				DataManager::SetValue("tw_partition_used", Part->Used / mb);
+				DataManager::SetValue("tw_partition_free", Part->Free / mb);
+				DataManager::SetValue("tw_partition_backup_size", Part->Backup_Size / mb);
+				DataManager::SetValue("tw_partition_removable", Part->Removable);
+				DataManager::SetValue("tw_partition_is_present", Part->Is_Present);
+
+				if (Part->Can_Repair())
+					DataManager::SetValue("tw_partition_can_repair", 1);
+				else
+					DataManager::SetValue("tw_partition_can_repair", 0);
+				if (TWFunc::Path_Exists("/sbin/mkdosfs"))
+					DataManager::SetValue("tw_partition_vfat", 1);
+				else
+					DataManager::SetValue("tw_partition_vfat", 0);
+				if (TWFunc::Path_Exists("/sbin/mkfs.exfat"))
+					DataManager::SetValue("tw_partition_exfat", 1);
+				else
+					DataManager::SetValue("tw_partition_exfat", 0);
+				if (TWFunc::Path_Exists("/sbin/mkfs.f2fs"))
+					DataManager::SetValue("tw_partition_f2fs", 1);
+				else
+					DataManager::SetValue("tw_partition_f2fs", 0);
+				if (TWFunc::Path_Exists("/sbin/mke2fs"))
+					DataManager::SetValue("tw_partition_ext", 1);
+				else
+					DataManager::SetValue("tw_partition_ext", 0);
+				return 0;
+			} else {
+				LOGERR("Unable to locate partition: '%s'\n", wipe_path.c_str());
+			}
+		}
+	}
+	DataManager::SetValue("tw_partition_name", "");
+	DataManager::SetValue("tw_partition_file_system", "");
+	return 0;
+}
+
+int GUIAction::screenshot(std::string arg)
+{
+	time_t tm;
+	char path[256];
+	int path_len;
+	uid_t uid = -1;
+	gid_t gid = -1;
+
+	struct passwd *pwd = getpwnam("media_rw");
+	if(pwd) {
+		uid = pwd->pw_uid;
+		gid = pwd->pw_gid;
+	}
+
+	const std::string storage = DataManager::GetCurrentStoragePath();
+	if(PartitionManager.Is_Mounted_By_Path(storage)) {
+		snprintf(path, sizeof(path), "%s/Pictures/Screenshots/", storage.c_str());
+	} else {
+		strcpy(path, "/tmp/");
+	}
+
+	if(!TWFunc::Create_Dir_Recursive(path, 0666, uid, gid))
+		return 0;
+
+	tm = time(NULL);
+	path_len = strlen(path);
+
+	// Screenshot_2014-01-01-18-21-38.png
+	strftime(path+path_len, sizeof(path)-path_len, "Screenshot_%Y-%m-%d-%H-%M-%S.png", localtime(&tm));
+
+	int res = gr_save_screenshot(path);
+	if(res == 0) {
+		chmod(path, 0666);
+		chown(path, uid, gid);
+
+		gui_print("Screenshot was saved to %s\n", path);
+
+		// blink to notify that the screenshow was taken
+		gr_color(255, 255, 255, 255);
+		gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+		gr_flip();
+		gui_forceRender();
+	} else {
+		LOGERR("Failed to take a screenshot!\n");
+	}
+	return 0;
+}
+
+int GUIAction::setbrightness(std::string arg)
+{
+	return TWFunc::Set_Brightness(arg);
+}
+
+int GUIAction::fileexists(std::string arg)
+{
+	struct stat st;
+	string newpath = arg + "/.";
+
+	operation_start("FileExists");
+	if (stat(arg.c_str(), &st) == 0 || stat(newpath.c_str(), &st) == 0)
+		operation_end(0);
+	else
+		operation_end(1);
+	return 0;
+}
+
+int GUIAction::flash(std::string arg)
+{
+	int i, ret_val = 0, wipe_cache = 0;
+	for (i=0; i<zip_queue_index; i++) {
+		operation_start("Flashing");
+		DataManager::SetValue("tw_filename", zip_queue[i]);
+		DataManager::SetValue(TW_ZIP_INDEX, (i + 1));
+
+		TWFunc::SetPerformanceMode(true);
+		ret_val = flash_zip(zip_queue[i], arg, &wipe_cache);
+		TWFunc::SetPerformanceMode(false);
+		if (ret_val != 0) {
+			gui_print("Error flashing zip '%s'\n", zip_queue[i].c_str());
+			i = 10; // Error flashing zip - exit queue
+			ret_val = 1;
+		}
+	}
+	zip_queue_index = 0;
+	DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+
+	if (wipe_cache)
+		PartitionManager.Wipe_By_Path("/cache");
+
+	if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
+		operation_start("ReinjectTWRP");
+		gui_print("Injecting TWRP into boot image...\n");
+		if (simulate) {
+			simulate_progress_bar();
+		} else {
+			TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
+			if (Boot == NULL || Boot->Current_File_System != "emmc")
+				TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
+			else {
+				string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device;
+				TWFunc::Exec_Cmd(injectcmd);
+			}
+			gui_print("TWRP injection complete.\n");
+		}
+	}
+	PartitionManager.Update_System_Details();
+	operation_end(ret_val);
+	return 0;
+}
+
+int GUIAction::wipe(std::string arg)
+{
+	operation_start("Format");
+	DataManager::SetValue("tw_partition", arg);
+
+	int ret_val = false;
+
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		if (arg == "data")
+			ret_val = PartitionManager.Factory_Reset();
+		else if (arg == "battery")
+			ret_val = PartitionManager.Wipe_Battery_Stats();
+		else if (arg == "rotate")
+			ret_val = PartitionManager.Wipe_Rotate_Data();
+		else if (arg == "dalvik")
+			ret_val = PartitionManager.Wipe_Dalvik_Cache();
+		else if (arg == "DATAMEDIA") {
+			ret_val = PartitionManager.Format_Data();
+		} else if (arg == "INTERNAL") {
+			int has_datamedia, dual_storage;
+
+			DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
+			if (has_datamedia) {
+				ret_val = PartitionManager.Wipe_Media_From_Data();
+			} else {
+				ret_val = PartitionManager.Wipe_By_Path(DataManager::GetSettingsStoragePath());
+			}
+		} else if (arg == "EXTERNAL") {
+			string External_Path;
+
+			DataManager::GetValue(TW_EXTERNAL_PATH, External_Path);
+			ret_val = PartitionManager.Wipe_By_Path(External_Path);
+		} else if (arg == "ANDROIDSECURE") {
+			ret_val = PartitionManager.Wipe_Android_Secure();
+		} else if (arg == "LIST") {
+			string Wipe_List, wipe_path;
+			bool skip = false;
+			ret_val = true;
+			TWPartition* wipe_part = NULL;
+
+			DataManager::GetValue("tw_wipe_list", Wipe_List);
+			LOGINFO("wipe list '%s'\n", Wipe_List.c_str());
+			if (!Wipe_List.empty()) {
+				size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
+				while (end_pos != string::npos && start_pos < Wipe_List.size()) {
+					wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
+					LOGINFO("wipe_path '%s'\n", wipe_path.c_str());
+					if (wipe_path == "/and-sec") {
+						if (!PartitionManager.Wipe_Android_Secure()) {
+							LOGERR("Unable to wipe android secure\n");
+							ret_val = false;
+							break;
+						} else {
+							skip = true;
+						}
+					} else if (wipe_path == "DALVIK") {
+						if (!PartitionManager.Wipe_Dalvik_Cache()) {
+							LOGERR("Failed to wipe dalvik\n");
+							ret_val = false;
+							break;
+						} else {
+							skip = true;
+						}
+					} else if (wipe_path == "INTERNAL") {
+						if (!PartitionManager.Wipe_Media_From_Data()) {
+							ret_val = false;
+							break;
+						} else {
+							skip = true;
 						}
 					}
-				} else
-					ret_val = PartitionManager.Wipe_By_Path(arg);
-#ifdef TW_OEM_BUILD
-				if (arg == DataManager::GetSettingsStoragePath()) {
-					// If we wiped the settings storage path, recreate the TWRP folder and dump the settings
-					string Storage_Path = DataManager::GetSettingsStoragePath();
-
-					if (PartitionManager.Mount_By_Path(Storage_Path, true)) {
-						LOGINFO("Making TWRP folder and saving settings.\n");
-						Storage_Path += "/TWRP";
-						mkdir(Storage_Path.c_str(), 0777);
-						DataManager::Flush();
+					if (!skip) {
+						if (!PartitionManager.Wipe_By_Path(wipe_path)) {
+							LOGERR("Unable to wipe '%s'\n", wipe_path.c_str());
+							ret_val = false;
+							break;
+						} else if (wipe_path == DataManager::GetSettingsStoragePath()) {
+							arg = wipe_path;
+						}
 					} else {
-						LOGERR("Unable to recreate TWRP folder and save settings.\n");
+						skip = false;
 					}
+					start_pos = end_pos + 1;
+					end_pos = Wipe_List.find(";", start_pos);
 				}
-#endif
 			}
-			PartitionManager.Update_System_Details();
-			if (ret_val)
-				ret_val = 0; // 0 is success
-			else
-				ret_val = 1; // 1 is failure
-			operation_end(ret_val, simulate);
-			return 0;
-		}
-		if (function == "refreshsizes")
-		{
-			operation_start("Refreshing Sizes");
-			if (simulate) {
-				simulate_progress_bar();
-			} else
-				PartitionManager.Update_System_Details();
-			operation_end(0, simulate);
-			return 0;
-		}
-		if (function == "nandroid")
-		{
-			operation_start("Nandroid");
-			int ret = 0;
+		} else
+			ret_val = PartitionManager.Wipe_By_Path(arg);
+#ifdef TW_OEM_BUILD
+		if (arg == DataManager::GetSettingsStoragePath()) {
+			// If we wiped the settings storage path, recreate the TWRP folder and dump the settings
+			string Storage_Path = DataManager::GetSettingsStoragePath();
 
-			if (simulate) {
-				DataManager::SetValue("tw_partition", "Simulation");
-				simulate_progress_bar();
+			if (PartitionManager.Mount_By_Path(Storage_Path, true)) {
+				LOGINFO("Making TWRP folder and saving settings.\n");
+				Storage_Path += "/TWRP";
+				mkdir(Storage_Path.c_str(), 0777);
+				DataManager::Flush();
 			} else {
-				if (arg == "backup") {
-					string Backup_Name;
-					DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
-					if (Backup_Name == "(Auto Generate)" || Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(true) == 0) {
-						ret = PartitionManager.Run_Backup();
-					}
-					else {
-						operation_end(1, simulate);
-						return -1;
+				LOGERR("Unable to recreate TWRP folder and save settings.\n");
+			}
+		}
+#endif
+	}
+	PartitionManager.Update_System_Details();
+	if (ret_val)
+		ret_val = 0; // 0 is success
+	else
+		ret_val = 1; // 1 is failure
+	operation_end(ret_val);
+	return 0;
+}
 
-					}
-					DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)");
-				} else if (arg == "restore") {
-					string Restore_Name;
-					DataManager::GetValue("tw_restore", Restore_Name);
-					ret = PartitionManager.Run_Restore(Restore_Name);
-				} else {
-					operation_end(1, simulate);
+int GUIAction::refreshsizes(std::string arg)
+{
+	operation_start("Refreshing Sizes");
+	if (simulate) {
+		simulate_progress_bar();
+	} else
+		PartitionManager.Update_System_Details();
+	operation_end(0);
+	return 0;
+}
+
+int GUIAction::nandroid(std::string arg)
+{
+	operation_start("Nandroid");
+	int ret = 0;
+
+	if (simulate) {
+		DataManager::SetValue("tw_partition", "Simulation");
+		simulate_progress_bar();
+	} else {
+		if (arg == "backup") {
+			string Backup_Name;
+			DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
+			if (Backup_Name == "(Auto Generate)" || Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(true) == 0) {
+				ret = PartitionManager.Run_Backup();
+			}
+			else {
+				operation_end(1);
+				return -1;
+
+			}
+			DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)");
+		} else if (arg == "restore") {
+			string Restore_Name;
+			DataManager::GetValue("tw_restore", Restore_Name);
+			ret = PartitionManager.Run_Restore(Restore_Name);
+		} else {
+			operation_end(1);
 					return -1;
 				}
 			}
@@ -1026,487 +1038,501 @@
 				ret = 1; // 1 for failure
 			else
 				ret = 0; // 0 for success
-			operation_end(ret, simulate);
+			operation_end(ret);
 			return 0;
-		}
-		if (function == "fixpermissions")
-		{
-			operation_start("Fix Permissions");
-			LOGINFO("fix permissions started!\n");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				int op_status = PartitionManager.Fix_Permissions();
-				if (op_status != 0)
-					op_status = 1; // failure
-				operation_end(op_status, simulate);
-			}
-			return 0;
-		}
-		if (function == "dd")
-		{
-			operation_start("imaging");
+}
 
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				string cmd = "dd " + arg;
-				TWFunc::Exec_Cmd(cmd);
-			}
-			operation_end(0, simulate);
-			return 0;
+int GUIAction::fixpermissions(std::string arg)
+{
+	operation_start("Fix Permissions");
+	LOGINFO("fix permissions started!\n");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		int op_status = PartitionManager.Fix_Permissions();
+		if (op_status != 0)
+			op_status = 1; // failure
+		operation_end(op_status);
+	}
+	return 0;
+}
+
+int GUIAction::dd(std::string arg)
+{
+	operation_start("imaging");
+
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		string cmd = "dd " + arg;
+		TWFunc::Exec_Cmd(cmd);
+	}
+	operation_end(0);
+	return 0;
+}
+
+int GUIAction::partitionsd(std::string arg)
+{
+	operation_start("Partition SD Card");
+	int ret_val = 0;
+
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		int allow_partition;
+		DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition);
+		if (allow_partition == 0) {
+			gui_print("This device does not have a real SD Card!\nAborting!\n");
+		} else {
+			if (!PartitionManager.Partition_SDCard())
+				ret_val = 1; // failed
 		}
-		if (function == "partitionsd")
-		{
-			operation_start("Partition SD Card");
-			int ret_val = 0;
+	}
+	operation_end(ret_val);
+	return 0;
 
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				int allow_partition;
-				DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition);
-				if (allow_partition == 0) {
-					gui_print("This device does not have a real SD Card!\nAborting!\n");
-				} else {
-					if (!PartitionManager.Partition_SDCard())
-						ret_val = 1; // failed
-				}
-			}
-			operation_end(ret_val, simulate);
-			return 0;
-		}
-		if (function == "installhtcdumlock")
-		{
-			operation_start("Install HTC Dumlock");
-			if (simulate) {
-				simulate_progress_bar();
-			} else
-				TWFunc::install_htc_dumlock();
+}
 
-			operation_end(0, simulate);
-			return 0;
-		}
-		if (function == "htcdumlockrestoreboot")
-		{
-			operation_start("HTC Dumlock Restore Boot");
-			if (simulate) {
-				simulate_progress_bar();
-			} else
-				TWFunc::htc_dumlock_restore_original_boot();
+int GUIAction::installhtcdumlock(std::string arg)
+{
+	operation_start("Install HTC Dumlock");
+	if (simulate) {
+		simulate_progress_bar();
+	} else
+		TWFunc::install_htc_dumlock();
 
-			operation_end(0, simulate);
-			return 0;
-		}
-		if (function == "htcdumlockreflashrecovery")
-		{
-			operation_start("HTC Dumlock Reflash Recovery");
-			if (simulate) {
-				simulate_progress_bar();
-			} else
-				TWFunc::htc_dumlock_reflash_recovery_to_boot();
+	operation_end(0);
+	return 0;
+}
 
-			operation_end(0, simulate);
-			return 0;
-		}
-		if (function == "cmd")
-		{
-			int op_status = 0;
+int GUIAction::htcdumlockrestoreboot(std::string arg)
+{
+	operation_start("HTC Dumlock Restore Boot");
+	if (simulate) {
+		simulate_progress_bar();
+	} else
+		TWFunc::htc_dumlock_restore_original_boot();
 
-			operation_start("Command");
-			LOGINFO("Running command: '%s'\n", arg.c_str());
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				op_status = TWFunc::Exec_Cmd(arg);
-				if (op_status != 0)
-					op_status = 1;
-			}
+	operation_end(0);
+	return 0;
+}
 
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "terminalcommand")
-		{
-			int op_status = 0;
-			string cmdpath, command;
+int GUIAction::htcdumlockreflashrecovery(std::string arg)
+{
+	operation_start("HTC Dumlock Reflash Recovery");
+	if (simulate) {
+		simulate_progress_bar();
+	} else
+		TWFunc::htc_dumlock_reflash_recovery_to_boot();
 
-			DataManager::GetValue("tw_terminal_location", cmdpath);
-			operation_start("CommandOutput");
-			gui_print("%s # %s\n", cmdpath.c_str(), arg.c_str());
-			if (simulate) {
-				simulate_progress_bar();
-				operation_end(op_status, simulate);
-			} else {
-				command = "cd \"" + cmdpath + "\" && " + arg + " 2>&1";;
-				LOGINFO("Actual command is: '%s'\n", command.c_str());
-				DataManager::SetValue("tw_terminal_command_thread", command);
-				DataManager::SetValue("tw_terminal_state", 1);
-				DataManager::SetValue("tw_background_thread_running", 1);
-				op_status = pthread_create(&terminal_command, NULL, command_thread, NULL);
-				if (op_status != 0) {
-					LOGERR("Error starting terminal command thread, %i.\n", op_status);
-					DataManager::SetValue("tw_terminal_state", 0);
-					DataManager::SetValue("tw_background_thread_running", 0);
-					operation_end(1, simulate);
-				}
-			}
-			return 0;
-		}
-		if (function == "killterminal")
-		{
-			int op_status = 0;
+	operation_end(0);
+	return 0;
+}
 
-			LOGINFO("Sending kill command...\n");
-			operation_start("KillCommand");
-			DataManager::SetValue("tw_operation_status", 0);
-			DataManager::SetValue("tw_operation_state", 1);
+int GUIAction::cmd(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Command");
+	LOGINFO("Running command: '%s'\n", arg.c_str());
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		op_status = TWFunc::Exec_Cmd(arg);
+		if (op_status != 0)
+			op_status = 1;
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::terminalcommand(std::string arg)
+{
+	int op_status = 0;
+	string cmdpath, command;
+
+	DataManager::GetValue("tw_terminal_location", cmdpath);
+	operation_start("CommandOutput");
+	gui_print("%s # %s\n", cmdpath.c_str(), arg.c_str());
+	if (simulate) {
+		simulate_progress_bar();
+		operation_end(op_status);
+	} else {
+		command = "cd \"" + cmdpath + "\" && " + arg + " 2>&1";;
+		LOGINFO("Actual command is: '%s'\n", command.c_str());
+		DataManager::SetValue("tw_terminal_command_thread", command);
+		DataManager::SetValue("tw_terminal_state", 1);
+		DataManager::SetValue("tw_background_thread_running", 1);
+		op_status = pthread_create(&terminal_command, NULL, command_thread, NULL);
+		if (op_status != 0) {
+			LOGERR("Error starting terminal command thread, %i.\n", op_status);
 			DataManager::SetValue("tw_terminal_state", 0);
 			DataManager::SetValue("tw_background_thread_running", 0);
-			DataManager::SetValue(TW_ACTION_BUSY, 0);
-			return 0;
+			operation_end(1);
 		}
-		if (function == "reinjecttwrp")
-		{
-			int op_status = 0;
+	}
+	return 0;
+}
+
+int GUIAction::killterminal(std::string arg)
+{
+	int op_status = 0;
+
+	LOGINFO("Sending kill command...\n");
+	operation_start("KillCommand");
+	DataManager::SetValue("tw_operation_status", 0);
+	DataManager::SetValue("tw_operation_state", 1);
+	DataManager::SetValue("tw_terminal_state", 0);
+	DataManager::SetValue("tw_background_thread_running", 0);
+	DataManager::SetValue(TW_ACTION_BUSY, 0);
+	return 0;
+}
+
+int GUIAction::reinjecttwrp(std::string arg)
+{
+	int op_status = 0;
+	operation_start("ReinjectTWRP");
+	gui_print("Injecting TWRP into boot image...\n");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
+		gui_print("TWRP injection complete.\n");
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::checkbackupname(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("CheckBackupName");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		op_status = PartitionManager.Check_Backup_Name(true);
+		if (op_status != 0)
+			op_status = 1;
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::decrypt(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Decrypt");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		string Password;
+		DataManager::GetValue("tw_crypto_password", Password);
+		op_status = PartitionManager.Decrypt_Device(Password);
+		if (op_status != 0)
+			op_status = 1;
+		else {
+			int load_theme = 1;
+
+			DataManager::SetValue(TW_IS_ENCRYPTED, 0);
+
+			if (load_theme) {
+				int has_datamedia;
+
+				// Check for a custom theme and load it if exists
+				DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
+				if (has_datamedia != 0) {
+					struct stat st;
+					int check = 0;
+					std::string theme_path;
+
+					if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
+						LOGERR("Failed to get default contexts and file mode for storage files.\n");
+					} else {
+						LOGINFO("Got default contexts and file mode for storage files.\n");
+					}
+
+					theme_path = DataManager::GetSettingsStoragePath();
+					if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
+						LOGERR("Unable to mount %s during reload function startup.\n", theme_path.c_str());
+						check = 1;
+					}
+
+					theme_path += "/TWRP/theme/ui.zip";
+					if (check == 0 && stat(theme_path.c_str(), &st) == 0) {
+						if (PageManager::ReloadPackage("TWRP", theme_path) != 0)
+						{
+							// Loading the custom theme failed - try loading the stock theme
+							LOGINFO("Attempting to reload stock theme...\n");
+							if (PageManager::ReloadPackage("TWRP", "/res/ui.xml"))
+							{
+								LOGERR("Failed to load base packages.\n");
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::adbsideload(std::string arg)
+{
+	int ret = 0;
+
+	operation_start("Sideload");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		int wipe_cache = 0;
+		int wipe_dalvik = 0;
+
+		gui_print("Starting ADB sideload feature...\n");
+		bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
+		DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik);
+		ret = apply_from_adb("/");
+		DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start
+		char file_prop[PROPERTY_VALUE_MAX];
+		property_get("tw_sideload_file", file_prop, "error");
+		if (ret != 0) {
+			ret = 1; // failure
+			if (ret == -2)
+				gui_print("You need adb 1.0.32 or newer to sideload to this device.\n");
+		} else {
+			if (TWinstall_zip(file_prop, &wipe_cache) == 0) {
+				if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache"))
+					PartitionManager.Wipe_By_Path("/cache");
+				if (wipe_dalvik)
+					PartitionManager.Wipe_Dalvik_Cache();
+			} else {
+				ret = 1; // failure
+			}
+			set_usb_driver(false);
+			maybe_restart_adbd();
+		}
+		TWFunc::Toggle_MTP(mtp_was_enabled);
+		if (strcmp(file_prop, "error") != 0) {
+			struct stat st;
+			stat("/sideload/exit", &st);
+			int child_pid, status;
+			char child_prop[PROPERTY_VALUE_MAX];
+			property_get("tw_child_pid", child_prop, "error");
+			if (strcmp(child_prop, "error") == 0) {
+				LOGERR("Unable to get child ID from prop\n");
+			} else {
+				child_pid = atoi(child_prop);
+				LOGINFO("Waiting for child sideload process to exit.\n");
+				waitpid(child_pid, &status, 0);
+			}
+		}
+		if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
 			operation_start("ReinjectTWRP");
 			gui_print("Injecting TWRP into boot image...\n");
 			if (simulate) {
 				simulate_progress_bar();
 			} else {
-				TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
+				TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
+				if (Boot == NULL || Boot->Current_File_System != "emmc")
+					TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
+				else {
+					string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device;
+					TWFunc::Exec_Cmd(injectcmd);
+				}
 				gui_print("TWRP injection complete.\n");
 			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "checkbackupname")
-		{
-			int op_status = 0;
-
-			operation_start("CheckBackupName");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				op_status = PartitionManager.Check_Backup_Name(true);
-				if (op_status != 0)
-					op_status = 1;
-			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "decrypt")
-		{
-			int op_status = 0;
-
-			operation_start("Decrypt");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				string Password;
-				DataManager::GetValue("tw_crypto_password", Password);
-				op_status = PartitionManager.Decrypt_Device(Password);
-				if (op_status != 0)
-					op_status = 1;
-				else {
-					int load_theme = 1;
-
-					DataManager::SetValue(TW_IS_ENCRYPTED, 0);
-
-					if (load_theme) {
-						int has_datamedia;
-
-						// Check for a custom theme and load it if exists
-						DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
-						if (has_datamedia != 0) {
-							struct stat st;
-							int check = 0;
-							std::string theme_path;
-
-							if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
-								LOGERR("Failed to get default contexts and file mode for storage files.\n");
-							} else {
-								LOGINFO("Got default contexts and file mode for storage files.\n");
-							}
-
-							theme_path = DataManager::GetSettingsStoragePath();
-							if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
-								LOGERR("Unable to mount %s during reload function startup.\n", theme_path.c_str());
-								check = 1;
-							}
-
-							theme_path += "/TWRP/theme/ui.zip";
-							if (check == 0 && stat(theme_path.c_str(), &st) == 0) {
-								if (PageManager::ReloadPackage("TWRP", theme_path) != 0)
-								{
-									// Loading the custom theme failed - try loading the stock theme
-									LOGINFO("Attempting to reload stock theme...\n");
-									if (PageManager::ReloadPackage("TWRP", "/res/ui.xml"))
-									{
-										LOGERR("Failed to load base packages.\n");
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "adbsideload")
-		{
-			int ret = 0;
-
-			operation_start("Sideload");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				int wipe_cache = 0;
-				int wipe_dalvik = 0;
-
-				gui_print("Starting ADB sideload feature...\n");
-				bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
-				DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik);
-				ret = apply_from_adb("/");
-				DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start
-				char file_prop[PROPERTY_VALUE_MAX];
-				property_get("tw_sideload_file", file_prop, "error");
-				if (ret != 0) {
-					ret = 1; // failure
-					if (ret == -2)
-						gui_print("You need adb 1.0.32 or newer to sideload to this device.\n");
-				} else {
-					if (TWinstall_zip(file_prop, &wipe_cache) == 0) {
-						if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache"))
-							PartitionManager.Wipe_By_Path("/cache");
-						if (wipe_dalvik)
-							PartitionManager.Wipe_Dalvik_Cache();
-					} else {
-						ret = 1; // failure
-					}
-					set_usb_driver(false);
-					maybe_restart_adbd();
-				}
-				TWFunc::Toggle_MTP(mtp_was_enabled);
-				if (strcmp(file_prop, "error") != 0) {
-					struct stat st;
-					stat("/sideload/exit", &st);
-					int child_pid, status;
-					char child_prop[PROPERTY_VALUE_MAX];
-					property_get("tw_child_pid", child_prop, "error");
-					if (strcmp(child_prop, "error") == 0) {
-						LOGERR("Unable to get child ID from prop\n");
-					} else {
-						child_pid = atoi(child_prop);
-						LOGINFO("Waiting for child sideload process to exit.\n");
-						waitpid(child_pid, &status, 0);
-					}
-				}
-				if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
-					operation_start("ReinjectTWRP");
-					gui_print("Injecting TWRP into boot image...\n");
-					if (simulate) {
-						simulate_progress_bar();
-					} else {
-						TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
-						if (Boot == NULL || Boot->Current_File_System != "emmc")
-							TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
-						else {
-							string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device;
-							TWFunc::Exec_Cmd(injectcmd);
-						}
-						gui_print("TWRP injection complete.\n");
-					}
-				}
-			}
-			operation_end(ret, simulate);
-			return 0;
-		}
-		if (function == "adbsideloadcancel")
-		{
-			int child_pid, status;
-			char child_prop[PROPERTY_VALUE_MAX];
-			struct stat st;
-			DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui
-			gui_print("Cancelling ADB sideload...\n");
-			stat("/sideload/exit", &st);
-			sleep(1);
-			property_get("tw_child_pid", child_prop, "error");
-			if (strcmp(child_prop, "error") == 0) {
-				LOGERR("Unable to get child ID from prop\n");
-				return 0;
-			}
-			child_pid = atoi(child_prop);
-			kill(child_pid, SIGTERM);
-			DataManager::SetValue("tw_page_done", "1"); // For OpenRecoveryScript support
-			return 0;
-		}
-		if (function == "openrecoveryscript") {
-			operation_start("OpenRecoveryScript");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				// Check for the SCRIPT_FILE_TMP first as these are AOSP recovery commands
-				// that we converted to ORS commands during boot in recovery.cpp.
-				// Run those first.
-				int reboot = 0;
-				if (TWFunc::Path_Exists(SCRIPT_FILE_TMP)) {
-					gui_print("Processing AOSP recovery commands...\n");
-					if (OpenRecoveryScript::run_script_file() == 0) {
-						reboot = 1;
-					}
-				}
-				// Check for the ORS file in /cache and attempt to run those commands.
-				if (OpenRecoveryScript::check_for_script_file()) {
-					gui_print("Processing OpenRecoveryScript file...\n");
-					if (OpenRecoveryScript::run_script_file() == 0) {
-						reboot = 1;
-					}
-				}
-				if (reboot) {
-					usleep(2000000); // Sleep for 2 seconds before rebooting
-					TWFunc::tw_reboot(rb_system);
-				} else {
-					DataManager::SetValue("tw_page_done", 1);
-				}
-			}
-			return 0;
-		}
-		if (function == "installsu")
-		{
-			int op_status = 0;
-
-			operation_start("Install SuperSU");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				if (!TWFunc::Install_SuperSU())
-					op_status = 1;
-			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "fixsu")
-		{
-			int op_status = 0;
-
-			operation_start("Fixing Superuser Permissions");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				LOGERR("Fixing su permissions was deprecated from TWRP.\n");
-				LOGERR("4.3+ ROMs with SELinux will always lose su perms.\n");
-			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "decrypt_backup")
-		{
-			int op_status = 0;
-
-			operation_start("Try Restore Decrypt");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				string Restore_Path, Filename, Password;
-				DataManager::GetValue("tw_restore", Restore_Path);
-				Restore_Path += "/";
-				DataManager::GetValue("tw_restore_password", Password);
-				TWFunc::SetPerformanceMode(true);
-				if (TWFunc::Try_Decrypting_Backup(Restore_Path, Password))
-					op_status = 0; // success
-				else
-					op_status = 1; // fail
-				TWFunc::SetPerformanceMode(false);
-			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "repair")
-		{
-			int op_status = 0;
-
-			operation_start("Repair Partition");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				string part_path;
-				DataManager::GetValue("tw_partition_mount_point", part_path);
-				if (PartitionManager.Repair_By_Path(part_path, true)) {
-					op_status = 0; // success
-				} else {
-					LOGERR("Error repairing file system.\n");
-					op_status = 1; // fail
-				}
-			}
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "changefilesystem")
-		{
-			int op_status = 0;
-
-			operation_start("Change File System");
-			if (simulate) {
-				simulate_progress_bar();
-			} else {
-				string part_path, file_system;
-				DataManager::GetValue("tw_partition_mount_point", part_path);
-				DataManager::GetValue("tw_action_new_file_system", file_system);
-				if (PartitionManager.Wipe_By_Path(part_path, file_system)) {
-					op_status = 0; // success
-				} else {
-					LOGERR("Error changing file system.\n");
-					op_status = 1; // fail
-				}
-			}
-			PartitionManager.Update_System_Details();
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "startmtp")
-		{
-			int op_status = 0;
-
-			operation_start("Start MTP");
-			if (PartitionManager.Enable_MTP())
-				op_status = 0; // success
-			else
-				op_status = 1; // fail
-
-			operation_end(op_status, simulate);
-			return 0;
-		}
-		if (function == "stopmtp")
-		{
-			int op_status = 0;
-
-			operation_start("Stop MTP");
-			if (PartitionManager.Disable_MTP())
-				op_status = 0; // success
-			else
-				op_status = 1; // fail
-
-			operation_end(op_status, simulate);
-			return 0;
 		}
 	}
-	else
-	{
-		pthread_t t;
-		pthread_create(&t, NULL, thread_start, this);
+	operation_end(ret);
+	return 0;
+}
+
+int GUIAction::adbsideloadcancel(std::string arg)
+{
+	int child_pid;
+	char child_prop[PROPERTY_VALUE_MAX];
+	struct stat st;
+	DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui
+	gui_print("Cancelling ADB sideload...\n");
+	stat("/sideload/exit", &st);
+	::sleep(1);
+	property_get("tw_child_pid", child_prop, "error");
+	if (strcmp(child_prop, "error") == 0) {
+		LOGERR("Unable to get child ID from prop\n");
 		return 0;
 	}
-	LOGERR("Unknown action '%s'\n", function.c_str());
-	return -1;
+	child_pid = atoi(child_prop);
+	kill(child_pid, SIGTERM);
+	DataManager::SetValue("tw_page_done", "1"); // For OpenRecoveryScript support
+	return 0;
+}
+
+int GUIAction::openrecoveryscript(std::string arg)
+{
+	operation_start("OpenRecoveryScript");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		// Check for the SCRIPT_FILE_TMP first as these are AOSP recovery commands
+		// that we converted to ORS commands during boot in recovery.cpp.
+		// Run those first.
+		int reboot = 0;
+		if (TWFunc::Path_Exists(SCRIPT_FILE_TMP)) {
+			gui_print("Processing AOSP recovery commands...\n");
+			if (OpenRecoveryScript::run_script_file() == 0) {
+				reboot = 1;
+			}
+		}
+		// Check for the ORS file in /cache and attempt to run those commands.
+		if (OpenRecoveryScript::check_for_script_file()) {
+			gui_print("Processing OpenRecoveryScript file...\n");
+			if (OpenRecoveryScript::run_script_file() == 0) {
+				reboot = 1;
+			}
+		}
+		if (reboot) {
+			usleep(2000000); // Sleep for 2 seconds before rebooting
+			TWFunc::tw_reboot(rb_system);
+		} else {
+			DataManager::SetValue("tw_page_done", 1);
+		}
+	}
+	return 0;
+}
+
+int GUIAction::installsu(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Install SuperSU");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		if (!TWFunc::Install_SuperSU())
+			op_status = 1;
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::fixsu(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Fixing Superuser Permissions");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		LOGERR("Fixing su permissions was deprecated from TWRP.\n");
+		LOGERR("4.3+ ROMs with SELinux will always lose su perms.\n");
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::decrypt_backup(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Try Restore Decrypt");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		string Restore_Path, Filename, Password;
+		DataManager::GetValue("tw_restore", Restore_Path);
+		Restore_Path += "/";
+		DataManager::GetValue("tw_restore_password", Password);
+		TWFunc::SetPerformanceMode(true);
+		if (TWFunc::Try_Decrypting_Backup(Restore_Path, Password))
+			op_status = 0; // success
+		else
+			op_status = 1; // fail
+		TWFunc::SetPerformanceMode(false);
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::repair(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Repair Partition");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		string part_path;
+		DataManager::GetValue("tw_partition_mount_point", part_path);
+		if (PartitionManager.Repair_By_Path(part_path, true)) {
+			op_status = 0; // success
+		} else {
+			LOGERR("Error repairing file system.\n");
+			op_status = 1; // fail
+		}
+	}
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::changefilesystem(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Change File System");
+	if (simulate) {
+		simulate_progress_bar();
+	} else {
+		string part_path, file_system;
+		DataManager::GetValue("tw_partition_mount_point", part_path);
+		DataManager::GetValue("tw_action_new_file_system", file_system);
+		if (PartitionManager.Wipe_By_Path(part_path, file_system)) {
+			op_status = 0; // success
+		} else {
+			LOGERR("Error changing file system.\n");
+			op_status = 1; // fail
+		}
+	}
+	PartitionManager.Update_System_Details();
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::startmtp(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Start MTP");
+	if (PartitionManager.Enable_MTP())
+		op_status = 0; // success
+	else
+		op_status = 1; // fail
+
+	operation_end(op_status);
+	return 0;
+}
+
+int GUIAction::stopmtp(std::string arg)
+{
+	int op_status = 0;
+
+	operation_start("Stop MTP");
+	if (PartitionManager.Disable_MTP())
+		op_status = 0; // success
+	else
+		op_status = 1; // fail
+
+	operation_end(op_status);
+	return 0;
 }
 
 int GUIAction::getKeyByName(std::string key)
diff --git a/gui/objects.hpp b/gui/objects.hpp
index 310ba4e..3f12ea7 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -264,7 +264,8 @@
 	virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
 	virtual int NotifyKey(int key, bool down);
 	virtual int NotifyVarChange(const std::string& varName, const std::string& value);
-	virtual int doActions();
+
+	int doActions();
 
 protected:
 	class Action
@@ -279,14 +280,76 @@
 
 protected:
 	int getKeyByName(std::string key);
-	virtual int doAction(Action action, int isThreaded = 0);
-	static void* thread_start(void *cookie);
+	int doAction(Action action);
 	void simulate_progress_bar(void);
-	int flash_zip(std::string filename, std::string pageName, const int simulate, int* wipe_cache);
+	int flash_zip(std::string filename, std::string pageName, int* wipe_cache);
 	void operation_start(const string operation_name);
-	void operation_end(const int operation_status, const int simulate);
+	void operation_end(const int operation_status);
 	static void* command_thread(void *cookie);
 	time_t Start;
+
+	// map action name to function pointer
+	typedef int (GUIAction::*execFunction)(std::string);
+	typedef std::map<std::string, execFunction> mapFunc;
+	static mapFunc mf;
+
+	// GUI actions
+	int reboot(std::string arg);
+	int home(std::string arg);
+	int key(std::string arg);
+	int page(std::string arg);
+	int reload(std::string arg);
+	int readBackup(std::string arg);
+	int set(std::string arg);
+	int clear(std::string arg);
+	int mount(std::string arg);
+	int unmount(std::string arg);
+	int restoredefaultsettings(std::string arg);
+	int copylog(std::string arg);
+	int compute(std::string arg);
+	int setguitimezone(std::string arg);
+	int overlay(std::string arg);
+	int queuezip(std::string arg);
+	int cancelzip(std::string arg);
+	int queueclear(std::string arg);
+	int sleep(std::string arg);
+	int appenddatetobackupname(std::string arg);
+	int generatebackupname(std::string arg);
+	int checkpartitionlist(std::string arg);
+	int getpartitiondetails(std::string arg);
+	int screenshot(std::string arg);
+	int setbrightness(std::string arg);
+
+	// threaded actions
+	int fileexists(std::string arg);
+	int flash(std::string arg);
+	int wipe(std::string arg);
+	int refreshsizes(std::string arg);
+	int nandroid(std::string arg);
+	int fixpermissions(std::string arg);
+	int dd(std::string arg);
+	int partitionsd(std::string arg);
+	int installhtcdumlock(std::string arg);
+	int htcdumlockrestoreboot(std::string arg);
+	int htcdumlockreflashrecovery(std::string arg);
+	int cmd(std::string arg);
+	int terminalcommand(std::string arg);
+	int killterminal(std::string arg);
+	int reinjecttwrp(std::string arg);
+	int checkbackupname(std::string arg);
+	int decrypt(std::string arg);
+	int adbsideload(std::string arg);
+	int adbsideloadcancel(std::string arg);
+	int openrecoveryscript(std::string arg);
+	int installsu(std::string arg);
+	int fixsu(std::string arg);
+	int decrypt_backup(std::string arg);
+	int repair(std::string arg);
+	int changefilesystem(std::string arg);
+	int startmtp(std::string arg);
+	int stopmtp(std::string arg);
+
+	int simulate;
 };
 
 class GUIConsole : public GUIObject, public RenderObject, public ActionObject