Files
android_bootable_recovery/openrecoveryscript.cpp
Ethan Yonker 74db157b94 Multiple Language Support
This is similar to https://gerrit.omnirom.org/#/c/14014

A lot of the features built in the older patch set have been split
out into separate patches, most of which have already been merged.
The remaining functionality here should all be directly related to
language selection and loading. We always load English as a base
before loading other languages over the top of the base. The idea
is that if another language is missing a translation, then we will
still display the English.

Maybe still to do: read the /cache/recovery/last_locale file and
load a language based on that. For me, this file contains just:
en_US
We probably won't bother with region specific translations so we
would have to look at either trimming off the _US or using some
other method like perhaps a symlink or a combination of the two.

Thanks to _that for twmsg.cpp class

Change-Id: I9647a22e47883a3ddd2de1da51f64aab7c328f74
2015-12-19 08:31:01 -06:00

592 lines
22 KiB
C++

/*
Copyright 2012 bigbiff/Dees_Troy TeamWin
This file is part of TWRP/TeamWin Recovery Project.
TWRP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TWRP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with TWRP. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <unistd.h>
#include <vector>
#include <dirent.h>
#include <time.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/wait.h>
#include "twrp-functions.hpp"
#include "partitions.hpp"
#include "twcommon.h"
#include "openrecoveryscript.hpp"
#include "variables.h"
#include "adb_install.h"
#include "data.hpp"
#include "adb_install.h"
#include "fuse_sideload.h"
#include "gui/gui.hpp"
extern "C" {
#include "twinstall.h"
#include "gui/gui.h"
#include "cutils/properties.h"
int TWinstall_zip(const char* path, int* wipe_cache);
}
#define SCRIPT_COMMAND_SIZE 512
int OpenRecoveryScript::check_for_script_file(void) {
if (!PartitionManager.Mount_By_Path(SCRIPT_FILE_CACHE, false)) {
LOGINFO("Unable to mount /cache for OpenRecoveryScript support.\n");
gui_msg(Msg(msg::kError, "unable_to_mount=Unable to mount {1}")(SCRIPT_FILE_CACHE));
return 0;
}
if (TWFunc::Path_Exists(SCRIPT_FILE_CACHE)) {
LOGINFO("Script file found: '%s'\n", SCRIPT_FILE_CACHE);
// Copy script file to /tmp
TWFunc::copy_file(SCRIPT_FILE_CACHE, SCRIPT_FILE_TMP, 0755);
// Delete the file from /cache
unlink(SCRIPT_FILE_CACHE);
return 1;
}
return 0;
}
int OpenRecoveryScript::copy_script_file(string filename) {
if (TWFunc::Path_Exists(filename)) {
LOGINFO("Script file found: '%s'\n", filename.c_str());
if (filename == SCRIPT_FILE_TMP)
return 1; // file is already in the right place
// Copy script file to /tmp
TWFunc::copy_file(filename, SCRIPT_FILE_TMP, 0755);
// Delete the old file
unlink(filename.c_str());
return 1;
}
return 0;
}
int OpenRecoveryScript::run_script_file(void) {
FILE *fp = fopen(SCRIPT_FILE_TMP, "r");
int ret_val = 0, cindex, line_len, i, remove_nl, install_cmd = 0, sideload = 0;
char script_line[SCRIPT_COMMAND_SIZE], command[SCRIPT_COMMAND_SIZE],
value[SCRIPT_COMMAND_SIZE], mount[SCRIPT_COMMAND_SIZE],
value1[SCRIPT_COMMAND_SIZE], value2[SCRIPT_COMMAND_SIZE];
char *val_start, *tok;
if (fp != NULL) {
DataManager::SetValue(TW_SIMULATE_ACTIONS, 0);
DataManager::SetValue("ui_progress", 0); // Reset the progress bar
while (fgets(script_line, SCRIPT_COMMAND_SIZE, fp) != NULL && ret_val == 0) {
cindex = 0;
line_len = strlen(script_line);
if (line_len < 2)
continue; // there's a blank line or line is too short to contain a command
//gui_print("script line: '%s'\n", script_line);
for (i=0; i<line_len; i++) {
if ((int)script_line[i] == 32) {
cindex = i;
i = line_len;
}
}
memset(command, 0, sizeof(command));
memset(value, 0, sizeof(value));
if ((int)script_line[line_len - 1] == 10)
remove_nl = 2;
else
remove_nl = 1;
if (cindex != 0) {
strncpy(command, script_line, cindex);
LOGINFO("command is: '%s'\n", command);
val_start = script_line;
val_start += cindex + 1;
if ((int) *val_start == 32)
val_start++; //get rid of space
if ((int) *val_start == 51)
val_start++; //get rid of = at the beginning
if ((int) *val_start == 32)
val_start++; //get rid of space
strncpy(value, val_start, line_len - cindex - remove_nl);
LOGINFO("value is: '%s'\n", value);
} else {
strncpy(command, script_line, line_len - remove_nl + 1);
gui_print("command is: '%s' and there is no value\n", command);
}
if (strcmp(command, "install") == 0) {
// Install Zip
DataManager::SetValue("tw_action_text2", "Installing Zip");
PartitionManager.Mount_All_Storage();
ret_val = Install_Command(value);
install_cmd = -1;
} else if (strcmp(command, "wipe") == 0) {
// Wipe
if (strcmp(value, "cache") == 0 || strcmp(value, "/cache") == 0) {
PartitionManager.Wipe_By_Path("/cache");
} else if (strcmp(value, "dalvik") == 0 || strcmp(value, "dalvick") == 0 || strcmp(value, "dalvikcache") == 0 || strcmp(value, "dalvickcache") == 0) {
PartitionManager.Wipe_Dalvik_Cache();
} else if (strcmp(value, "data") == 0 || strcmp(value, "/data") == 0 || strcmp(value, "factory") == 0 || strcmp(value, "factoryreset") == 0) {
PartitionManager.Factory_Reset();
} else {
LOGERR("Error with wipe command value: '%s'\n", value);
ret_val = 1;
}
} else if (strcmp(command, "backup") == 0) {
// Backup
DataManager::SetValue("tw_action_text2", gui_parse_text("{@backing}"));
tok = strtok(value, " ");
strcpy(value1, tok);
tok = strtok(NULL, " ");
if (tok != NULL) {
memset(value2, 0, sizeof(value2));
strcpy(value2, tok);
line_len = strlen(tok);
if ((int)value2[line_len - 1] == 10 || (int)value2[line_len - 1] == 13) {
if ((int)value2[line_len - 1] == 10 || (int)value2[line_len - 1] == 13)
remove_nl = 2;
else
remove_nl = 1;
} else
remove_nl = 0;
strncpy(value2, tok, line_len - remove_nl);
DataManager::SetValue(TW_BACKUP_NAME, value2);
gui_msg(Msg("backup_folder=Backup folder set to '{1}'")(value2));
if (PartitionManager.Check_Backup_Name(true) != 0) {
ret_val = 1;
continue;
}
} else {
char empt[50];
strcpy(empt, "(Current Date)");
DataManager::SetValue(TW_BACKUP_NAME, empt);
}
ret_val = Backup_Command(value1);
} else if (strcmp(command, "restore") == 0) {
// Restore
DataManager::SetValue("tw_action_text2", gui_parse_text("{@restore}"));
PartitionManager.Mount_All_Storage();
DataManager::SetValue(TW_SKIP_MD5_CHECK_VAR, 0);
char folder_path[512], partitions[512];
string val = value, restore_folder, restore_partitions;
size_t pos = val.find_last_of(" ");
if (pos == string::npos) {
restore_folder = value;
partitions[0] = '\0';
} else {
restore_folder = val.substr(0, pos);
restore_partitions = val.substr(pos + 1, val.size() - pos - 1);
strcpy(partitions, restore_partitions.c_str());
}
strcpy(folder_path, restore_folder.c_str());
LOGINFO("Restore folder is: '%s' and partitions: '%s'\n", folder_path, partitions);
gui_msg(Msg("restoring=Restoring {1}...")(folder_path));
if (folder_path[0] != '/') {
char backup_folder[512];
string folder_var;
std::vector<PartitionList> Storage_List;
PartitionManager.Get_Partition_List("storage", &Storage_List);
int listSize = Storage_List.size();
for (int i = 0; i < listSize; i++) {
if (PartitionManager.Is_Mounted_By_Path(Storage_List.at(i).Mount_Point)) {
DataManager::SetValue("tw_storage_path", Storage_List.at(i).Mount_Point);
DataManager::GetValue(TW_BACKUPS_FOLDER_VAR, folder_var);
sprintf(backup_folder, "%s/%s", folder_var.c_str(), folder_path);
if (TWFunc::Path_Exists(backup_folder)) {
strcpy(folder_path, backup_folder);
break;
}
}
}
} else {
if (folder_path[strlen(folder_path) - 1] == '/')
strcat(folder_path, ".");
else
strcat(folder_path, "/.");
}
if (!TWFunc::Path_Exists(folder_path)) {
gui_msg(Msg(msg::kError, "locate_backup_err=Unable to locate backup '{1}'")(folder_path));
ret_val = 1;
continue;
}
DataManager::SetValue("tw_restore", folder_path);
PartitionManager.Set_Restore_Files(folder_path);
string Partition_List;
int is_encrypted = 0;
DataManager::GetValue("tw_restore_encrypted", is_encrypted);
DataManager::GetValue("tw_restore_list", Partition_List);
if (strlen(partitions) != 0) {
string Restore_List;
memset(value2, 0, sizeof(value2));
strcpy(value2, partitions);
gui_msg(Msg("set_restore_opt=Setting restore options: '{1}':")(value2));
line_len = strlen(value2);
for (i=0; i<line_len; i++) {
if ((value2[i] == 'S' || value2[i] == 's') && Partition_List.find("/system;") != string::npos) {
Restore_List += "/system;";
gui_msg("system=System");
} else if ((value2[i] == 'D' || value2[i] == 'd') && Partition_List.find("/data;") != string::npos) {
Restore_List += "/data;";
gui_msg("data=Data");
} else if ((value2[i] == 'C' || value2[i] == 'c') && Partition_List.find("/cache;") != string::npos) {
Restore_List += "/cache;";
gui_msg("cache=Cache");
} else if ((value2[i] == 'R' || value2[i] == 'r') && Partition_List.find("/recovery;") != string::npos) {
Restore_List += "/recovery;";
gui_msg("recovery=Recovery");
} else if (value2[i] == '1' && DataManager::GetIntValue(TW_RESTORE_SP1_VAR) > 0) {
gui_print("%s\n", "Special1 -- No Longer Supported...");
} else if (value2[i] == '2' && DataManager::GetIntValue(TW_RESTORE_SP2_VAR) > 0) {
gui_print("%s\n", "Special2 -- No Longer Supported...");
} else if (value2[i] == '3' && DataManager::GetIntValue(TW_RESTORE_SP3_VAR) > 0) {
gui_print("%s\n", "Special3 -- No Longer Supported...");
} else if ((value2[i] == 'B' || value2[i] == 'b') && Partition_List.find("/boot;") != string::npos) {
Restore_List += "/boot;";
gui_msg("boot=Boot");
} else if ((value2[i] == 'A' || value2[i] == 'a') && Partition_List.find("/and-sec;") != string::npos) {
Restore_List += "/and-sec;";
gui_msg("android_secure=Android Secure");
} else if ((value2[i] == 'E' || value2[i] == 'e') && Partition_List.find("/sd-ext;") != string::npos) {
Restore_List += "/sd-ext;";
gui_msg("sdext=SD-EXT");
} else if (value2[i] == 'M' || value2[i] == 'm') {
DataManager::SetValue(TW_SKIP_MD5_CHECK_VAR, 1);
gui_msg("md5_check_skip=MD5 check skip is on");
}
}
DataManager::SetValue("tw_restore_selected", Restore_List);
} else {
DataManager::SetValue("tw_restore_selected", Partition_List);
}
if (is_encrypted) {
gui_err("ors_encrypt_restore_err=Unable to use OpenRecoveryScript to restore an encrypted backup.");
ret_val = 1;
} else if (!PartitionManager.Run_Restore(folder_path))
ret_val = 1;
else
gui_msg("done=Done.");
} else if (strcmp(command, "mount") == 0) {
// Mount
DataManager::SetValue("tw_action_text2", gui_parse_text("{@mounting}"));
if (value[0] != '/') {
strcpy(mount, "/");
strcat(mount, value);
} else
strcpy(mount, value);
if (PartitionManager.Mount_By_Path(mount, true))
gui_msg(Msg("mounted=Mounted '{1}'")(mount));
} else if (strcmp(command, "unmount") == 0 || strcmp(command, "umount") == 0) {
// Unmount
DataManager::SetValue("tw_action_text2", gui_parse_text("{@unmounting}"));
if (value[0] != '/') {
strcpy(mount, "/");
strcat(mount, value);
} else
strcpy(mount, value);
if (PartitionManager.UnMount_By_Path(mount, true))
gui_msg(Msg("unmounted=Unounted '{1}'")(mount));
} else if (strcmp(command, "set") == 0) {
// Set value
size_t len = strlen(value);
tok = strtok(value, " ");
strcpy(value1, tok);
if (len > strlen(value1) + 1) {
char *val2 = value + strlen(value1) + 1;
gui_msg(Msg("setting=Setting '{1}' to '{2}'")(value1)(val2));
DataManager::SetValue(value1, val2);
} else {
gui_msg(Msg("setting_empty=Setting '{1}' to empty")(value1));
DataManager::SetValue(value1, "");
}
} else if (strcmp(command, "mkdir") == 0) {
// Make directory (recursive)
DataManager::SetValue("tw_action_text2", gui_parse_text("{@making_dir1}"));
gui_msg(Msg("making_dir2=Making directory: '{1}'")(value));
if (TWFunc::Recursive_Mkdir(value)) {
gui_msg(Msg(msg::kError, "create_folder_strerr=Can not create '{1}' folder ({2}).")(value)(strerror(errno)));
ret_val = 1;
}
} else if (strcmp(command, "reboot") == 0) {
if (strlen(value) && strcmp(value, "recovery") == 0)
TWFunc::tw_reboot(rb_recovery);
else if (strlen(value) && strcmp(value, "poweroff") == 0)
TWFunc::tw_reboot(rb_poweroff);
else if (strlen(value) && strcmp(value, "bootloader") == 0)
TWFunc::tw_reboot(rb_bootloader);
else if (strlen(value) && strcmp(value, "download") == 0)
TWFunc::tw_reboot(rb_download);
else
TWFunc::tw_reboot(rb_system);
} else if (strcmp(command, "cmd") == 0) {
DataManager::SetValue("tw_action_text2", gui_parse_text("{@running_command}"));
if (cindex != 0) {
TWFunc::Exec_Cmd(value);
} else {
LOGERR("No value given for cmd\n");
}
} else if (strcmp(command, "print") == 0) {
gui_print("%s\n", value);
} else if (strcmp(command, "sideload") == 0) {
// ADB Sideload
DataManager::SetValue("tw_action_text2", gui_parse_text("{@sideload}"));
install_cmd = -1;
int wipe_cache = 0;
string result;
pid_t sideload_child_pid;
gui_msg("start_sideload=Starting ADB sideload feature...");
ret_val = apply_from_adb("/", &sideload_child_pid);
if (ret_val != 0) {
if (ret_val == -2)
gui_err("need_new_adb=You need adb 1.0.32 or newer to sideload to this device.");
ret_val = 1; // failure
} else if (TWinstall_zip(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache) == 0) {
if (wipe_cache)
PartitionManager.Wipe_By_Path("/cache");
} else {
ret_val = 1; // failure
}
sideload = 1; // Causes device to go to the home screen afterwards
if (sideload_child_pid != 0) {
LOGINFO("Signaling child sideload process to exit.\n");
struct stat st;
// Calling stat() on this magic filename signals the minadbd
// subprocess to shut down.
stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
int status;
LOGINFO("Waiting for child sideload process to exit.\n");
waitpid(sideload_child_pid, &status, 0);
}
property_set("ctl.start", "adbd");
gui_msg("done=Done.");
} else if (strcmp(command, "fixperms") == 0 || strcmp(command, "fixpermissions") == 0) {
ret_val = PartitionManager.Fix_Permissions();
if (ret_val != 0)
ret_val = 1; // failure
} else if (strcmp(command, "decrypt") == 0) {
if (*value) {
ret_val = PartitionManager.Decrypt_Device(value);
if (ret_val != 0)
ret_val = 1; // failure
} else {
gui_err("no_pwd=No password provided.");
ret_val = 1; // failure
}
} else {
LOGERR("Unrecognized script command: '%s'\n", command);
ret_val = 1;
}
}
fclose(fp);
gui_msg("done_ors=Done processing script file");
} else {
gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(SCRIPT_FILE_TMP)(strerror(errno)));
return 1;
}
if (install_cmd && DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
gui_msg("injecttwrp=Injecting TWRP into boot image...");
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.c_str());
}
gui_msg("done=Done.");
}
if (sideload)
ret_val = 1; // Forces booting to the home page after sideload
return ret_val;
}
int OpenRecoveryScript::Insert_ORS_Command(string Command) {
ofstream ORSfile(SCRIPT_FILE_TMP);
if (ORSfile.is_open()) {
//if (Command.substr(Command.size() - 1, 1) != "\n")
// Command += "\n";
LOGINFO("Inserting '%s'\n", Command.c_str());
ORSfile << Command.c_str();
ORSfile.close();
return 1;
}
LOGERR("Unable to append '%s' to '%s'\n", Command.c_str(), SCRIPT_FILE_TMP);
return 0;
}
int OpenRecoveryScript::Install_Command(string Zip) {
// Install zip
string ret_string;
int ret_val = 0, wipe_cache = 0;
std::vector<PartitionList> Storage_List;
string Full_Path;
if (Zip.substr(0, 1) == "@") {
// This is a special file that contains a map of blocks on the data partition
Full_Path = Zip.substr(1);
if (!PartitionManager.Mount_By_Path(Full_Path, true) || !TWFunc::Path_Exists(Full_Path)) {
LOGINFO("Unable to install via mapped zip '%s'\n", Full_Path.c_str());
gui_msg(Msg(msg::kError, "zip_err=Error installing zip file '{1}'")(Zip));
return 1;
}
LOGINFO("Installing mapped zip file '%s'\n", Full_Path.c_str());
gui_msg(Msg("installing_zip=Installing zip file '{1}'")(Zip));
} else if (!TWFunc::Path_Exists(Zip)) {
PartitionManager.Mount_All_Storage();
PartitionManager.Get_Partition_List("storage", &Storage_List);
int listSize = Storage_List.size();
for (int i = 0; i < listSize; i++) {
if (PartitionManager.Is_Mounted_By_Path(Storage_List.at(i).Mount_Point)) {
Full_Path = Storage_List.at(i).Mount_Point + "/" + Zip;
if (TWFunc::Path_Exists(Full_Path)) {
Zip = Full_Path;
break;
}
Full_Path = Zip;
LOGINFO("Trying to find zip '%s' on '%s'...\n", Full_Path.c_str(), Storage_List.at(i).Mount_Point.c_str());
ret_string = Locate_Zip_File(Full_Path, Storage_List.at(i).Mount_Point);
if (!ret_string.empty()) {
Zip = ret_string;
break;
}
}
}
if (!TWFunc::Path_Exists(Zip)) {
// zip file doesn't exist
gui_print("Unable to locate zip file '%s'.\n", Zip.c_str());
ret_val = 1;
} else
gui_msg(Msg("installing_zip=Installing zip file '{1}'")(Zip));
}
ret_val = TWinstall_zip(Zip.c_str(), &wipe_cache);
if (ret_val != 0) {
gui_msg(Msg(msg::kError, "zip_err=Error installing zip file '{1}'")(Zip));
ret_val = 1;
} else if (wipe_cache)
PartitionManager.Wipe_By_Path("/cache");
return ret_val;
}
string OpenRecoveryScript::Locate_Zip_File(string Zip, string Storage_Root) {
string Path = TWFunc::Get_Path(Zip);
string File = TWFunc::Get_Filename(Zip);
string pathCpy = Path;
string wholePath;
size_t pos = Path.find("/", 1);
while (pos != string::npos)
{
pathCpy = Path.substr(pos, Path.size() - pos);
wholePath = pathCpy + File;
LOGINFO("Looking for zip at '%s'\n", wholePath.c_str());
if (TWFunc::Path_Exists(wholePath))
return wholePath;
wholePath = Storage_Root + wholePath;
LOGINFO("Looking for zip at '%s'\n", wholePath.c_str());
if (TWFunc::Path_Exists(wholePath))
return wholePath;
pos = Path.find("/", pos + 1);
}
return "";
}
int OpenRecoveryScript::Backup_Command(string Options) {
char value1[SCRIPT_COMMAND_SIZE];
int line_len, i;
string Backup_List;
strcpy(value1, Options.c_str());
DataManager::SetValue(TW_USE_COMPRESSION_VAR, 0);
DataManager::SetValue(TW_SKIP_MD5_GENERATE_VAR, 0);
gui_msg("select_backup_opt=Setting backup options:");
line_len = Options.size();
for (i=0; i<line_len; i++) {
if (Options.substr(i, 1) == "S" || Options.substr(i, 1) == "s") {
Backup_List += "/system;";
gui_msg("system=System");
} else if (Options.substr(i, 1) == "D" || Options.substr(i, 1) == "d") {
Backup_List += "/data;";
gui_msg("data=Data");
} else if (Options.substr(i, 1) == "C" || Options.substr(i, 1) == "c") {
Backup_List += "/cache;";
gui_msg("cache=Cache");
} else if (Options.substr(i, 1) == "R" || Options.substr(i, 1) == "r") {
Backup_List += "/recovery;";
gui_msg("recovery=Recovery");
} else if (Options.substr(i, 1) == "1") {
gui_print("%s\n", "Special1 -- No Longer Supported...");
} else if (Options.substr(i, 1) == "2") {
gui_print("%s\n", "Special2 -- No Longer Supported...");
} else if (Options.substr(i, 1) == "3") {
gui_print("%s\n", "Special3 -- No Longer Supported...");
} else if (Options.substr(i, 1) == "B" || Options.substr(i, 1) == "b") {
Backup_List += "/boot;";
gui_msg("boot=Boot");
} else if (Options.substr(i, 1) == "A" || Options.substr(i, 1) == "a") {
Backup_List += "/and-sec;";
gui_msg("android_secure=Android Secure");
} else if (Options.substr(i, 1) == "E" || Options.substr(i, 1) == "e") {
Backup_List += "/sd-ext;";
gui_msg("sdext=SD-EXT");
} else if (Options.substr(i, 1) == "O" || Options.substr(i, 1) == "o") {
DataManager::SetValue(TW_USE_COMPRESSION_VAR, 1);
gui_msg("compression_on=Compression is on");
} else if (Options.substr(i, 1) == "M" || Options.substr(i, 1) == "m") {
DataManager::SetValue(TW_SKIP_MD5_GENERATE_VAR, 1);
gui_msg("md5_off=MD5 Generation is off");
}
}
DataManager::SetValue("tw_backup_list", Backup_List);
if (!PartitionManager.Run_Backup()) {
gui_err("backup_fail=Backup Failed");
return 1;
}
gui_msg("backup_complete=Backup complete!");
return 0;
}
void OpenRecoveryScript::Run_OpenRecoveryScript(void) {
DataManager::SetValue("tw_back", "main");
DataManager::SetValue("tw_action", "openrecoveryscript");
DataManager::SetValue("tw_has_action2", "0");
DataManager::SetValue("tw_action2", "");
DataManager::SetValue("tw_action2_param", "");
#ifdef TW_OEM_BUILD
DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands"));
DataManager::SetValue("tw_complete_text1", gui_lookup("recovery_commands_complete", "Recovery Commands Complete"));
#else
DataManager::SetValue("tw_action_text1", gui_lookup("running_ors", "Running OpenRecoveryScript"));
DataManager::SetValue("tw_complete_text1", gui_lookup("ors_complete", "OpenRecoveryScript Complete"));
#endif
DataManager::SetValue("tw_action_text2", "");
DataManager::SetValue("tw_has_cancel", 0);
DataManager::SetValue("tw_show_reboot", 0);
if (gui_startPage("action_page", 0, 1) != 0) {
LOGERR("Failed to load OpenRecoveryScript GUI page.\n");
}
}