diff options
| author | 2012-02-05 22:18:15 +0100 | |
|---|---|---|
| committer | 2012-02-05 22:18:15 +0100 | |
| commit | fdea23960ae9ea99fa28db49c4da5791a8affca7 (patch) | |
| tree | f1e06bb4be19ae3cd0482f8de8c8ed849831bc7a /src | |
| parent | 19d604ff509afd00f83a2687b243774d18654b65 (diff) | |
| download | idevicerestore-fdea23960ae9ea99fa28db49c4da5791a8affca7.tar.gz idevicerestore-fdea23960ae9ea99fa28db49c4da5791a8affca7.tar.bz2 | |
download and cache version information from itunes.com
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/common.h | 7 | ||||
| -rw-r--r-- | src/download.c | 104 | ||||
| -rw-r--r-- | src/download.h | 24 | ||||
| -rw-r--r-- | src/idevicerestore.c | 61 | 
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"); | 
