diff --git a/twinstall.cpp b/twinstall.cpp
new file mode 100644
index 0000000..0c3d837
--- /dev/null
+++ b/twinstall.cpp
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include "common.h"
+#include "twmincrypt/twrsa.h"
+#include "twmincrypt/twsha.h"
+#include "minui/minui.h"
+#include "minzip/SysUtil.h"
+#include "minzip/Zip.h"
+#include "mtdutils/mounts.h"
+#include "mtdutils/mtdutils.h"
+#include "roots.h"
+#include "verifier.h"
+#include "ui.h"
+#include "variables.h"
+#include "data.hpp"
+#include "partitions.hpp"
+
+extern "C" {
+#include "extra-functions.h"
+int __system(const char *command);
+};
+
+extern RecoveryUI* ui;
+
+#define ASSUMED_UPDATE_BINARY_NAME  "META-INF/com/google/android/update-binary"
+#define PUBLIC_KEYS_FILE "/res/keys"
+
+// Default allocation of progress bar segments to operations
+static const int VERIFICATION_PROGRESS_TIME = 60;
+static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
+static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
+static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
+
+enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
+
+// Look for an RSA signature embedded in the .ZIP file comment given
+// the path to the zip.  Verify it matches one of the given public
+// keys.
+//
+// Return VERIFY_SUCCESS, VERIFY_FAILURE (if any error is encountered
+// or no key matches the signature).
+
+int TWverify_file(const char* path, const RSAPublicKey *pKeys, unsigned int numKeys) {
+    ui->SetProgress(0.0);
+
+    FILE* f = fopen(path, "rb");
+    if (f == NULL) {
+        LOGE("failed to open %s (%s)\n", path, strerror(errno));
+        return VERIFY_FAILURE;
+    }
+
+    // An archive with a whole-file signature will end in six bytes:
+    //
+    //   (2-byte signature start) $ff $ff (2-byte comment size)
+    //
+    // (As far as the ZIP format is concerned, these are part of the
+    // archive comment.)  We start by reading this footer, this tells
+    // us how far back from the end we have to start reading to find
+    // the whole comment.
+
+#define FOOTER_SIZE 6
+
+    if (fseek(f, -FOOTER_SIZE, SEEK_END) != 0) {
+        LOGE("failed to seek in %s (%s)\n", path, strerror(errno));
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    unsigned char footer[FOOTER_SIZE];
+    if (fread(footer, 1, FOOTER_SIZE, f) != FOOTER_SIZE) {
+        LOGE("failed to read footer from %s (%s)\n", path, strerror(errno));
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    if (footer[2] != 0xff || footer[3] != 0xff) {
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    size_t comment_size = footer[4] + (footer[5] << 8);
+    size_t signature_start = footer[0] + (footer[1] << 8);
+    LOGI("comment is %d bytes; signature %d bytes from end\n",
+         comment_size, signature_start);
+
+    if (signature_start - FOOTER_SIZE < RSANUMBYTES) {
+        // "signature" block isn't big enough to contain an RSA block.
+        LOGE("signature is too short\n");
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+#define EOCD_HEADER_SIZE 22
+
+    // The end-of-central-directory record is 22 bytes plus any
+    // comment length.
+    size_t eocd_size = comment_size + EOCD_HEADER_SIZE;
+
+    if (fseek(f, -eocd_size, SEEK_END) != 0) {
+        LOGE("failed to seek in %s (%s)\n", path, strerror(errno));
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    // Determine how much of the file is covered by the signature.
+    // This is everything except the signature data and length, which
+    // includes all of the EOCD except for the comment length field (2
+    // bytes) and the comment data.
+    size_t signed_len = ftell(f) + EOCD_HEADER_SIZE - 2;
+
+    unsigned char* eocd = (unsigned char*)malloc(eocd_size);
+    if (eocd == NULL) {
+        LOGE("malloc for EOCD record failed\n");
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+    if (fread(eocd, 1, eocd_size, f) != eocd_size) {
+        LOGE("failed to read eocd from %s (%s)\n", path, strerror(errno));
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    // If this is really is the EOCD record, it will begin with the
+    // magic number $50 $4b $05 $06.
+    if (eocd[0] != 0x50 || eocd[1] != 0x4b ||
+        eocd[2] != 0x05 || eocd[3] != 0x06) {
+        LOGE("signature length doesn't match EOCD marker\n");
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    size_t i;
+    for (i = 4; i < eocd_size-3; ++i) {
+        if (eocd[i  ] == 0x50 && eocd[i+1] == 0x4b &&
+            eocd[i+2] == 0x05 && eocd[i+3] == 0x06) {
+            // if the sequence $50 $4b $05 $06 appears anywhere after
+            // the real one, minzip will find the later (wrong) one,
+            // which could be exploitable.  Fail verification if
+            // this sequence occurs anywhere after the real one.
+            LOGE("EOCD marker occurs after start of EOCD\n");
+            fclose(f);
+            return VERIFY_FAILURE;
+        }
+    }
+
+#define BUFFER_SIZE 4096
+
+    SHA_CTX ctx;
+    SHA_init(&ctx);
+    unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE);
+    if (buffer == NULL) {
+        LOGE("failed to alloc memory for sha1 buffer\n");
+        fclose(f);
+        return VERIFY_FAILURE;
+    }
+
+    double frac = -1.0;
+    size_t so_far = 0;
+    fseek(f, 0, SEEK_SET);
+    while (so_far < signed_len) {
+        size_t size = BUFFER_SIZE;
+        if (signed_len - so_far < size) size = signed_len - so_far;
+        if (fread(buffer, 1, size, f) != size) {
+            LOGE("failed to read data from %s (%s)\n", path, strerror(errno));
+            fclose(f);
+            return VERIFY_FAILURE;
+        }
+        SHA_update(&ctx, buffer, size);
+        so_far += size;
+        double f = so_far / (double)signed_len;
+        if (f > frac + 0.02 || size == so_far) {
+            ui->SetProgress(f);
+            frac = f;
+        }
+    }
+    fclose(f);
+    free(buffer);
+
+    const uint8_t* sha1 = SHA_final(&ctx);
+    for (i = 0; i < numKeys; ++i) {
+        // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that
+        // the signing tool appends after the signature itself.
+        if (RSA_verify(pKeys+i, eocd + eocd_size - 6 - RSANUMBYTES,
+                       RSANUMBYTES, sha1)) {
+            LOGI("whole-file signature verified against key %d\n", i);
+            free(eocd);
+            return VERIFY_SUCCESS;
+        }
+    }
+    free(eocd);
+    LOGE("failed to verify whole-file signature\n");
+    return VERIFY_FAILURE;
+}
+
+// If the package contains an update binary, extract it and run it.
+static int
+try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
+    const ZipEntry* binary_entry =
+            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
+    if (binary_entry == NULL) {
+        mzCloseZipArchive(zip);
+        return INSTALL_CORRUPT;
+    }
+
+    const char* binary = "/tmp/update_binary";
+    unlink(binary);
+    int fd = creat(binary, 0755);
+    if (fd < 0) {
+        mzCloseZipArchive(zip);
+        LOGE("Can't make %s\n", binary);
+        return INSTALL_ERROR;
+    }
+    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
+    close(fd);
+    mzCloseZipArchive(zip);
+
+    if (!ok) {
+        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
+        return INSTALL_ERROR;
+    }
+
+    int pipefd[2];
+    pipe(pipefd);
+
+    // When executing the update binary contained in the package, the
+    // arguments passed are:
+    //
+    //   - the version number for this interface
+    //
+    //   - an fd to which the program can write in order to update the
+    //     progress bar.  The program can write single-line commands:
+    //
+    //        progress <frac> <secs>
+    //            fill up the next <frac> part of of the progress bar
+    //            over <secs> seconds.  If <secs> is zero, use
+    //            set_progress commands to manually control the
+    //            progress of this segment of the bar
+    //
+    //        set_progress <frac>
+    //            <frac> should be between 0.0 and 1.0; sets the
+    //            progress bar within the segment defined by the most
+    //            recent progress command.
+    //
+    //        firmware <"hboot"|"radio"> <filename>
+    //            arrange to install the contents of <filename> in the
+    //            given partition on reboot.
+    //
+    //            (API v2: <filename> may start with "PACKAGE:" to
+    //            indicate taking a file from the OTA package.)
+    //
+    //            (API v3: this command no longer exists.)
+    //
+    //        ui_print <string>
+    //            display <string> on the screen.
+    //
+    //   - the name of the package zip file.
+    //
+
+    const char** args = (const char**)malloc(sizeof(char*) * 5);
+    args[0] = binary;
+    args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
+    char* temp = (char*)malloc(10);
+    sprintf(temp, "%d", pipefd[1]);
+    args[2] = temp;
+    args[3] = (char*)path;
+    args[4] = NULL;
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        close(pipefd[0]);
+        execv(binary, (char* const*)args);
+        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
+        _exit(-1);
+    }
+    close(pipefd[1]);
+
+    *wipe_cache = 0;
+
+    char buffer[1024];
+    FILE* from_child = fdopen(pipefd[0], "r");
+    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
+        char* command = strtok(buffer, " \n");
+        if (command == NULL) {
+            continue;
+        } else if (strcmp(command, "progress") == 0) {
+            char* fraction_s = strtok(NULL, " \n");
+            char* seconds_s = strtok(NULL, " \n");
+
+            float fraction = strtof(fraction_s, NULL);
+            int seconds = strtol(seconds_s, NULL, 10);
+
+            ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
+        } else if (strcmp(command, "set_progress") == 0) {
+            char* fraction_s = strtok(NULL, " \n");
+            float fraction = strtof(fraction_s, NULL);
+            ui->SetProgress(fraction);
+        } else if (strcmp(command, "ui_print") == 0) {
+            char* str = strtok(NULL, "\n");
+            if (str) {
+                ui->Print("%s", str);
+            } else {
+                ui->Print("\n");
+            }
+        } else if (strcmp(command, "wipe_cache") == 0) {
+            *wipe_cache = 1;
+        } else if (strcmp(command, "clear_display") == 0) {
+            //ui->SetBackground(RecoveryUI::NONE);
+        } else {
+            LOGE("unknown command [%s]\n", command);
+        }
+    }
+    fclose(from_child);
+
+    int status;
+    waitpid(pid, &status, 0);
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+        LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
+        return INSTALL_ERROR;
+    }
+
+    return INSTALL_SUCCESS;
+}
+
+// Reads a file containing one or more public keys as produced by
+// DumpPublicKey:  this is an RSAPublicKey struct as it would appear
+// as a C source literal, eg:
+//
+//  "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
+//
+// (Note that the braces and commas in this example are actual
+// characters the parser expects to find in the file; the ellipses
+// indicate more numbers omitted from this example.)
+//
+// The file may contain multiple keys in this format, separated by
+// commas.  The last key must not be followed by a comma.
+//
+// Returns NULL if the file failed to parse, or if it contain zero keys.
+static RSAPublicKey*
+load_keys(const char* filename, int* numKeys) {
+    RSAPublicKey* out = NULL;
+    *numKeys = 0;
+
+    FILE* f = fopen(filename, "r");
+    if (f == NULL) {
+        LOGE("opening %s: %s\n", filename, strerror(errno));
+        goto exit;
+    }
+
+    {
+        int i;
+        bool done = false;
+        while (!done) {
+            ++*numKeys;
+            out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey));
+            RSAPublicKey* key = out + (*numKeys - 1);
+            if (fscanf(f, " { %i , 0x%x , { %u",
+                       &(key->len), &(key->n0inv), &(key->n[0])) != 3) {
+                goto exit;
+            }
+            if (key->len != RSANUMWORDS) {
+                LOGE("key length (%d) does not match expected size\n", key->len);
+                goto exit;
+            }
+            for (i = 1; i < key->len; ++i) {
+                if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
+            }
+            if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
+            for (i = 1; i < key->len; ++i) {
+                if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
+            }
+            fscanf(f, " } } ");
+
+            // if the line ends in a comma, this file has more keys.
+            switch (fgetc(f)) {
+            case ',':
+                // more keys to come.
+                break;
+
+            case EOF:
+                done = true;
+                break;
+
+            default:
+                LOGE("unexpected character between keys\n");
+                goto exit;
+            }
+        }
+    }
+
+    fclose(f);
+    return out;
+
+exit:
+    if (f) fclose(f);
+    free(out);
+    *numKeys = 0;
+    return NULL;
+}
+
+char* get_path (char* path) {
+        char *s;
+
+        /* Go to the end of the string.  */
+        s = path + strlen(path) - 1;
+
+        /* Strip off trailing /s (unless it is also the leading /).  */
+        while (path < s && s[0] == '/')
+                s--;
+
+        /* Strip the last component.  */
+        while (path <= s && s[0] != '/')
+                s--;
+
+        while (path < s && s[0] == '/')
+                s--;
+
+        if (s < path)
+                return (char*)(".");
+
+        s[1] = '\0';
+	return path;
+}
+
+/*
+    Checks md5 for a path
+    Return values:
+        -1 : MD5 does not exist
+        0 : Failed
+        1 : Success
+*/
+int check_md5(const char* path) {
+	FILE* fp;
+	char command[255], line[512], actual_md5[512], md5[512];
+	char md5file[PATH_MAX + 40];
+	char *ptr;
+	unsigned int line_len, index = 0;
+	struct stat st;
+
+	// Check to see if the filename.zip.md5 file exists
+	strcpy(md5file, path);
+    strcat(md5file, ".md5");
+	if (stat(md5file, &st) != 0)
+		return -1; // no MD5 file found
+
+	// Dump the md5 of the zip to a text file for reading
+	sprintf(command, "md5sum '%s' > /tmp/md5output.txt", path);
+	__system(command);
+	fp = fopen("/tmp/md5output.txt", "rt");
+	if (fp == NULL) {
+		LOGI("Unable to open /tmp/md5output.txt.\n");
+		return false;
+	}
+
+	while (fgets(line, sizeof(line), fp) != NULL)
+	{
+		line_len = strlen(line);
+		for (index = 0; index < line_len; index++) {
+			if (line[index] <= 32)
+				line[index] = '\0';
+		}
+		strcpy(actual_md5, line);
+		break;
+	}
+	fclose(fp);
+
+	// Read the filename.zip.md5 file
+	fp = fopen(md5file, "rt");
+	if (fp == NULL) {
+		LOGI("Unable to open '%s'.\n", md5file);
+		return false;
+	}
+
+	while (fgets(line, sizeof(line), fp) != NULL)
+	{
+		line_len = strlen(line);
+		for (index = 0; index < line_len; index++) {
+			if (line[index] <= 32)
+				line[index] = '\0';
+		}
+		strcpy(md5, line);
+		break;
+	}
+	fclose(fp);
+
+	// Comare the 2 MD5 values
+	if (strcmp(actual_md5, md5) == 0)
+		return 1;
+	LOGI("MD5 did not match: '%s' != '%s'\n", actual_md5, md5);
+	return 0;
+}
+
+extern "C" int TWinstall_zip(const char* path, int* wipe_cache) {
+	int err, zip_verify, md5_return, md5_verify;
+
+	ui_print("Installing '%s'...\n", path);
+
+	if (!PartitionManager.Mount_By_Path(path, 0)) {
+		LOGE("Failed to mount '%s'\n", path);
+		return -1;
+	}
+
+	ui_print("Checking for MD5 file...\n");
+	md5_return = check_md5(path);
+	if (md5_return == 0) {
+		// MD5 did not match.
+		LOGE("Zip MD5 does not match.\nUnable to install zip.\n");
+		return INSTALL_CORRUPT;
+	} else if (md5_return == -1) {
+		DataManager::GetValue(TW_FORCE_MD5_CHECK_VAR, md5_verify);
+		if (md5_verify == 1) {
+			// Forced MD5 checking is on and no MD5 file found.
+			LOGE("No MD5 file found for '%s'.\nDisable force MD5 check to avoid this error.\n", path);
+			return INSTALL_CORRUPT;
+		} else
+			ui_print("No MD5 file found, this is not an error.\n");
+	} else if (md5_return == 1)
+		ui_print("Zip MD5 matched.\n"); // MD5 found and matched.
+
+	DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
+	if (zip_verify) {
+		ui_print("Verifying zip signature...\n");
+		int numKeys;
+		RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
+		if (loadedKeys == NULL) {
+			LOGE("Failed to load keys\n");
+			return -1;
+		}
+		LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);
+
+		// Give verification half the progress bar...
+		ui->Print("Verifying update package...\n");
+		ui->SetProgressType(RecoveryUI::DETERMINATE);
+		ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
+
+		err = TWverify_file(path, loadedKeys, numKeys);
+		free(loadedKeys);
+		LOGI("verify_file returned %d\n", err);
+		if (err != VERIFY_SUCCESS) {
+			LOGE("signature verification failed\n");
+			return -1;
+		}
+	}
+	/* Try to open the package.
+     */
+    ZipArchive zip;
+    err = mzOpenZipArchive(path, &zip);
+    if (err != 0) {
+        LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
+        return INSTALL_CORRUPT;
+    }
+
+    /* Verify and install the contents of the package.
+     */
+    return try_update_binary(path, &zip, wipe_cache);
+}
