summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2012-02-05 22:18:15 +0100
committerGravatar Nikias Bassen2012-02-05 22:18:15 +0100
commitfdea23960ae9ea99fa28db49c4da5791a8affca7 (patch)
treef1e06bb4be19ae3cd0482f8de8c8ed849831bc7a
parent19d604ff509afd00f83a2687b243774d18654b65 (diff)
downloadidevicerestore-fdea23960ae9ea99fa28db49c4da5791a8affca7.tar.gz
idevicerestore-fdea23960ae9ea99fa28db49c4da5791a8affca7.tar.bz2
download and cache version information from itunes.com
-rw-r--r--src/Makefile.am2
-rw-r--r--src/common.h7
-rw-r--r--src/download.c104
-rw-r--r--src/download.h24
-rw-r--r--src/idevicerestore.c61
5 files changed, 196 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5fbcdef..93b0d98 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,6 @@ AM_LDFLAGS =\
bin_PROGRAMS = idevicerestore
-idevicerestore_SOURCES = idevicerestore.c common.c tss.c img3.c ipsw.c normal.c dfu.c recovery.c restore.c asr.c libirecovery.c limera1n.c
+idevicerestore_SOURCES = idevicerestore.c common.c tss.c img3.c ipsw.c normal.c dfu.c recovery.c restore.c asr.c libirecovery.c limera1n.c download.c
idevicerestore_CFLAGS = $(AM_CFLAGS)
idevicerestore_LDFLAGS = $(AM_LDFLAGS) -lusb-1.0
diff --git a/src/common.h b/src/common.h
index 9a84188..19ce881 100644
--- a/src/common.h
+++ b/src/common.h
@@ -129,6 +129,7 @@ struct idevicerestore_device_t {
struct idevicerestore_client_t {
int flags;
plist_t tss;
+ plist_t version_data;
uint64_t ecid;
unsigned char* nonce;
int nonce_size;
@@ -183,6 +184,12 @@ int write_file(const char* filename, const void* data, size_t size);
char *generate_guid();
+#ifdef WIN32
+#define __mkdir(path, mode) mkdir(path)
+#else
+#define __mkdir(path, mode) mkdir(path, mode)
+#endif
+
extern struct idevicerestore_client_t* idevicerestore;
#ifdef __cplusplus
diff --git a/src/download.c b/src/download.c
new file mode 100644
index 0000000..211987a
--- /dev/null
+++ b/src/download.c
@@ -0,0 +1,104 @@
+/*
+ * download.c
+ * file download helper functions
+ *
+ * Copyright (c) 2012 Nikias Bassen. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <curl/curl.h>
+
+#include "download.h"
+
+typedef struct {
+ int length;
+ char* content;
+} curl_response;
+
+static size_t download_write_buffer_callback(char* data, size_t size, size_t nmemb, curl_response* response) {
+ size_t total = size * nmemb;
+ if (total != 0) {
+ response->content = realloc(response->content, response->length + total + 1);
+ memcpy(response->content + response->length, data, total);
+ response->content[response->length + total] = '\0';
+ response->length += total;
+ }
+ return total;
+}
+
+int download_to_buffer(const char* url, char** buf, uint32_t* length)
+{
+ curl_global_init(CURL_GLOBAL_ALL);
+ CURL* handle = curl_easy_init();
+ if (handle == NULL) {
+ error("ERROR: could not initialize CURL\n");
+ return -1;
+ }
+
+ curl_response response;
+ response.length = 0;
+ response.content = malloc(1);
+ response.content[0] = '\0';
+
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&download_write_buffer_callback);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, &response);
+ curl_easy_setopt(handle, CURLOPT_USERAGENT, "InetURL/1.0");
+ curl_easy_setopt(handle, CURLOPT_URL, url);
+
+ curl_easy_perform(handle);
+ curl_easy_cleanup(handle);
+
+ if (response.content) {
+ *length = response.length;
+ *buf = response.content;
+ }
+
+ curl_global_cleanup();
+
+ return 0;
+}
+
+int download_to_file(const char* url, const char* filename)
+{
+ curl_global_init(CURL_GLOBAL_ALL);
+ CURL* handle = curl_easy_init();
+ if (handle == NULL) {
+ error("ERROR: could not initialize CURL\n");
+ return -1;
+ }
+
+ FILE* f = fopen(filename, "wb");
+ if (!f) {
+ error("ERROR: cannot open '%s' for writing\n", filename);
+ return -1;
+ }
+
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&fwrite);
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, f);
+ curl_easy_setopt(handle, CURLOPT_USERAGENT, "InetURL/1.0");
+ curl_easy_setopt(handle, CURLOPT_URL, url);
+
+ curl_easy_perform(handle);
+ curl_easy_cleanup(handle);
+
+ fclose(f);
+
+ curl_global_cleanup();
+
+ return 0;
+}
diff --git a/src/download.h b/src/download.h
new file mode 100644
index 0000000..4900b18
--- /dev/null
+++ b/src/download.h
@@ -0,0 +1,24 @@
+/*
+ * download.h
+ * file download helper functions (header file)
+ *
+ * Copyright (c) 2012 Nikias Bassen. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdint.h>
+
+int download_to_buffer(const char* url, char** buf, uint32_t* length);
+int download_to_file(const char* url, const char* filename);
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 23e49f5..93c6766 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -34,11 +34,14 @@
#include "common.h"
#include "normal.h"
#include "restore.h"
+#include "download.h"
#include "recovery.h"
#include "idevicerestore.h"
#include "limera1n.h"
+#define VERSION_XML "cache/version.xml"
+
int use_apple_server;
static struct option longopts[] = {
@@ -70,6 +73,59 @@ void usage(int argc, char* argv[]) {
printf("\n");
}
+static int load_version_data(struct idevicerestore_client_t* client)
+{
+ if (!client) {
+ return -1;
+ }
+
+ struct stat fst;
+ int cached = 0;
+
+ if ((stat(VERSION_XML, &fst) < 0) || ((time(NULL)-86400) > fst.st_mtime)) {
+ char tmpf[256];
+ tmpf[0] = '\0';
+ if (!tmpnam(tmpf) || (tmpf[0] == '\0')) {
+ error("ERROR: Could not get temporary filename\n");
+ return -1;
+ }
+
+ if (download_to_file("http://itunes.com/version", tmpf) == 0) {
+ __mkdir("cache", 0755);
+ remove(VERSION_XML);
+ if (rename(tmpf, VERSION_XML) < 0) {
+ error("ERROR: Could not update '" VERSION_XML "'\n");
+ } else {
+ info("NOTE: Updated version data.\n");
+ }
+ }
+ } else {
+ cached = 1;
+ }
+
+ char *verbuf = NULL;
+ size_t verlen = 0;
+ read_file(VERSION_XML, (void**)&verbuf, &verlen);
+ if (!verbuf) {
+ error("ERROR: Could not load '" VERSION_XML "'.\n");
+ return -1;
+ }
+
+ client->version_data = NULL;
+ plist_from_xml(verbuf, verlen, &client->version_data);
+
+ if (!client->version_data) {
+ error("ERROR: Cannot parse plist data from '" VERSION_XML "'.\n");
+ return -1;
+ }
+
+ if (cached) {
+ info("NOTE: using cached version data\n");
+ }
+
+ return 0;
+}
+
int main(int argc, char* argv[]) {
int opt = 0;
int optindex = 0;
@@ -151,6 +207,9 @@ int main(int argc, char* argv[]) {
client->uuid = uuid;
client->ipsw = ipsw;
+ // update version data (from cache, or apple if too old)
+ load_version_data(client);
+
// check which mode the device is currently in so we know where to start
if (check_mode(client) < 0 || client->mode->index == MODE_UNKNOWN) {
error("ERROR: Unable to discover device mode. Please make sure a device is attached.\n");
@@ -428,7 +487,7 @@ int main(int argc, char* argv[]) {
if (bin) {
char zfn[512];
sprintf(zfn, "shsh/%lld-%s-%s.shsh", (long long int)client->ecid, client->device->product, client->version);
- mkdir("shsh", 0755);
+ __mkdir("shsh", 0755);
struct stat fst;
if (stat(zfn, &fst) != 0) {
gzFile zf = gzopen(zfn, "wb");