/*
 * This patches MobileSafari in the 1.1.1 ipod touch (and probably iphone) to allow
 * access to local files. It tweaks two instructions to eliminate the effects of
 * isFileURL checks.
 *
 * If run with no arguments, it will look for MobileSafari in its default location. When
 * run with an argument, it will patch that file. (For use outside of the touch.)
 *
 * This assumes a little endian platform - it won't work on the PPC, sorry.
 *
 * The C code was adapted from a springboard patch I found on pastebin.
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MS_SIZE   432940
#define MS_FILE "/Applications/MobileSafari.app/MobileSafari"



struct Patch {
        unsigned int offset;
        unsigned int old;
        unsigned int new;
};

struct Patch patches[] = {
    { 0x21694, 0x13a04000, 0xe1a04004}, // Changes a conditional mov to a nop mov
    { 0x21940, 0x0a00000e, 0xea00000e}, // Changes a conditional branch to unconditional
    { 0, 0, 0 }
};

int main(int argc, char** argv) {
    unsigned int DATA[(MS_SIZE)/4+1];
    FILE *fd;
    struct stat s;
    
    char* filename = MS_FILE;
    if (argc > 1) {
            filename = argv[1];
    }
    
    /* Patch MobileSafari */
    printf("Patching %s\n", filename);
    if (stat(filename, &s)) {
        fprintf(stderr, "Could not stat file '%s': %s\n", filename, strerror(errno));
        exit(-1);
    }
    if (s.st_size != MS_SIZE) {
        fprintf(stderr, "%s: file size mismatch: %d; expecting %d\n", filename, s.st_size, MS_SIZE);
        exit(-1);
    }
    fd = fopen(filename, "rb");
    if (!fd) {
        fprintf(stderr, "Could not open '%s' for reading: %s\n", filename, strerror(errno));
        exit(-1);
    }
    fread(&DATA, MS_SIZE, 1, fd);
    fclose(fd);

    struct Patch *patch = patches;
    while (patch->offset) {
            fprintf(stderr,"Patch %08x: %08x -> %08x\n", patch->offset, patch->old, patch->new);
            int offset = patch->offset / 4;
            unsigned int old = DATA[offset];
            if (old != patch->old) {
                    fprintf(stderr, "Mismatch at %08x: got %08x instead of %08x\n", 
                            patch->offset, DATA[offset], patch->old);
                    exit(-1);
            }
            DATA[offset] = patch->new;
            patch++;
    }


    fd = fopen(filename, "wb");
    if (!fd) {
        fprintf(stderr, "Could not open '%s' for writing: %s\n", filename, strerror(errno));
        exit(-1);
    }
    fwrite(&DATA, MS_SIZE, 1, fd);
    fclose(fd);
    return 0;
}
