From e28d96d4e976ecb19a4d2a094609f122e08ea8fa Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Tue, 5 Apr 2022 01:43:29 +0200 Subject: ipsw: Use libplist's new plist_from_json API --- src/Makefile.am | 4 +- src/ipsw.c | 4 +- src/jsmn.c | 280 ------------------------------------------------------- src/jsmn.h | 91 ------------------ src/json_plist.c | 229 --------------------------------------------- src/json_plist.h | 34 ------- 6 files changed, 3 insertions(+), 639 deletions(-) delete mode 100644 src/jsmn.c delete mode 100644 src/jsmn.h delete mode 100644 src/json_plist.c delete mode 100644 src/json_plist.h diff --git a/src/Makefile.am b/src/Makefile.am index 4a99dec..a89a9c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,9 +45,7 @@ idevicerestore_SOURCES = \ limera1n_payload.h \ limera1n.c limera1n.h \ download.c download.h \ - locking.c locking.h \ - jsmn.c jsmn.h \ - json_plist.c json_plist.h + locking.c locking.h if USE_INTERNAL_SHA idevicerestore_SOURCES += sha1.c sha1.h sha512.c sha512.h fixedint.h endif diff --git a/src/ipsw.c b/src/ipsw.c index da00a6e..03e10c2 100644 --- a/src/ipsw.c +++ b/src/ipsw.c @@ -45,13 +45,13 @@ #endif #include +#include #include "ipsw.h" #include "locking.h" #include "download.h" #include "common.h" #include "idevicerestore.h" -#include "json_plist.h" #define BUFSIZE 0x100000 @@ -892,7 +892,7 @@ int ipsw_get_signed_firmwares(const char* product, plist_t* firmwares) error("ERROR: Download from %s failed.\n", url); return -1; } - dict = json_to_plist(jdata); + plist_from_json(jdata, jsize, &dict); free(jdata); if (!dict || plist_get_node_type(dict) != PLIST_DICT) { error("ERROR: Failed to parse json data.\n"); diff --git a/src/jsmn.c b/src/jsmn.c deleted file mode 100644 index a56f20a..0000000 --- a/src/jsmn.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * jsmn.c - * Simple JSON parser - * - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "jsmn.h" - -/** - * Allocates a fresh unused token from the token pull. - */ -static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *tok; - if (parser->toknext >= num_tokens) { - return NULL; - } - tok = &tokens[parser->toknext++]; - tok->start = tok->end = -1; - tok->size = 0; -#ifdef JSMN_PARENT_LINKS - tok->parent = -1; -#endif - return tok; -} - -/** - * Fills token type and boundaries. - */ -static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, - int start, int end) { - token->type = type; - token->start = start; - token->end = end; - token->size = 0; -} - -/** - * Fills next available token with JSON primitive. - */ -static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - int start; - - start = parser->pos; - - for (; js[parser->pos] != '\0'; parser->pos++) { - switch (js[parser->pos]) { -#ifndef JSMN_STRICT - /* In strict mode primitive must be followed by "," or "}" or "]" */ - case ':': -#endif - case '\t' : case '\r' : case '\n' : case ' ' : - case ',' : case ']' : case '}' : - goto found; - } - if (js[parser->pos] < 32 || js[parser->pos] >= 127) { - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } -#ifdef JSMN_STRICT - /* In strict mode primitive must be followed by a comma/object/array */ - parser->pos = start; - return JSMN_ERROR_PART; -#endif - -found: - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - parser->pos--; - return JSMN_SUCCESS; -} - -/** - * Filsl next token with JSON string. - */ -static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, - jsmntok_t *tokens, size_t num_tokens) { - jsmntok_t *token; - - int start = parser->pos; - - parser->pos++; - - /* Skip starting quote */ - for (; js[parser->pos] != '\0'; parser->pos++) { - char c = js[parser->pos]; - - /* Quote: end of string */ - if (c == '\"') { - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) { - parser->pos = start; - return JSMN_ERROR_NOMEM; - } - jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - return JSMN_SUCCESS; - } - - /* Backslash: Quoted symbol expected */ - if (c == '\\') { - parser->pos++; - switch (js[parser->pos]) { - /* Allowed escaped symbols */ - case '\"': case '/' : case '\\' : case 'b' : - case 'f' : case 'r' : case 'n' : case 't' : - break; - /* Allows escaped symbol \uXXXX */ - case 'u': - /* TODO */ - break; - /* Unexpected symbol */ - default: - parser->pos = start; - return JSMN_ERROR_INVAL; - } - } - } - parser->pos = start; - return JSMN_ERROR_PART; -} - -/** - * Parse JSON string and fill tokens. - */ -jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, - unsigned int num_tokens) { - jsmnerr_t r; - int i; - jsmntok_t *token; - - for (; js[parser->pos] != '\0'; parser->pos++) { - char c; - jsmntype_t type; - - c = js[parser->pos]; - switch (c) { - case '{': case '[': - token = jsmn_alloc_token(parser, tokens, num_tokens); - if (token == NULL) - return JSMN_ERROR_NOMEM; - if (parser->toksuper != -1) { - tokens[parser->toksuper].size++; -#ifdef JSMN_PARENT_LINKS - token->parent = parser->toksuper; -#endif - } - token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); - token->start = parser->pos; - parser->toksuper = parser->toknext - 1; - break; - case '}': case ']': - type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); -#ifdef JSMN_PARENT_LINKS - if (parser->toknext < 1) { - return JSMN_ERROR_INVAL; - } - token = &tokens[parser->toknext - 1]; - for (;;) { - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - token->end = parser->pos + 1; - parser->toksuper = token->parent; - break; - } - if (token->parent == -1) { - break; - } - token = &tokens[token->parent]; - } -#else - for (i = parser->toknext - 1; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - if (token->type != type) { - return JSMN_ERROR_INVAL; - } - parser->toksuper = -1; - token->end = parser->pos + 1; - break; - } - } - /* Error if unmatched closing bracket */ - if (i == -1) return JSMN_ERROR_INVAL; - for (; i >= 0; i--) { - token = &tokens[i]; - if (token->start != -1 && token->end == -1) { - parser->toksuper = i; - break; - } - } -#endif - break; - case '\"': - r = jsmn_parse_string(parser, js, tokens, num_tokens); - if (r < 0) return r; - if (parser->toksuper != -1) - tokens[parser->toksuper].size++; - break; - case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': - break; -#ifdef JSMN_STRICT - /* In strict mode primitives are: numbers and booleans */ - case '-': case '0': case '1' : case '2': case '3' : case '4': - case '5': case '6': case '7' : case '8': case '9': - case 't': case 'f': case 'n' : -#else - /* In non-strict mode every unquoted value is a primitive */ - default: -#endif - r = jsmn_parse_primitive(parser, js, tokens, num_tokens); - if (r < 0) return r; - if (parser->toksuper != -1) - tokens[parser->toksuper].size++; - break; - -#ifdef JSMN_STRICT - /* Unexpected char in strict mode */ - default: - return JSMN_ERROR_INVAL; -#endif - - } - } - - for (i = parser->toknext - 1; i >= 0; i--) { - /* Unmatched opened object or array */ - if (tokens[i].start != -1 && tokens[i].end == -1) { - return JSMN_ERROR_PART; - } - } - - return JSMN_SUCCESS; -} - -/** - * Creates a new parser based over a given buffer with an array of tokens - * available. - */ -void jsmn_init(jsmn_parser *parser) { - parser->pos = 0; - parser->toknext = 0; - parser->toksuper = -1; -} - diff --git a/src/jsmn.h b/src/jsmn.h deleted file mode 100644 index f12dc5a..0000000 --- a/src/jsmn.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * jsmn.h - * Simple JSON parser (header file) - * - * Copyright (c) 2010 Serge A. Zaitsev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef __JSMN_H_ -#define __JSMN_H_ - -/** - * JSON type identifier. Basic types are: - * o Object - * o Array - * o String - * o Other primitive: number, boolean (true/false) or null - */ -typedef enum { - JSMN_PRIMITIVE = 0, - JSMN_OBJECT = 1, - JSMN_ARRAY = 2, - JSMN_STRING = 3 -} jsmntype_t; - -typedef enum { - /* Not enough tokens were provided */ - JSMN_ERROR_NOMEM = -1, - /* Invalid character inside JSON string */ - JSMN_ERROR_INVAL = -2, - /* The string is not a full JSON packet, more bytes expected */ - JSMN_ERROR_PART = -3, - /* Everything was fine */ - JSMN_SUCCESS = 0 -} jsmnerr_t; - -/** - * JSON token description. - * @param type type (object, array, string etc.) - * @param start start position in JSON data string - * @param end end position in JSON data string - */ -typedef struct { - jsmntype_t type; - int start; - int end; - int size; -#ifdef JSMN_PARENT_LINKS - int parent; -#endif -} jsmntok_t; - -/** - * JSON parser. Contains an array of token blocks available. Also stores - * the string being parsed now and current position in that string - */ -typedef struct { - unsigned int pos; /* offset in the JSON string */ - int toknext; /* next token to allocate */ - int toksuper; /* superior token node, e.g parent object or array */ -} jsmn_parser; - -/** - * Create JSON parser over an array of tokens - */ -void jsmn_init(jsmn_parser *parser); - -/** - * Run JSON parser. It parses a JSON data string into and array of tokens, each describing - * a single JSON object. - */ -jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, - jsmntok_t *tokens, unsigned int num_tokens); - -#endif /* __JSMN_H_ */ diff --git a/src/json_plist.c b/src/json_plist.c deleted file mode 100644 index 7bbead0..0000000 --- a/src/json_plist.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * json_plist.c - * JSON/property list functions - * - * Copyright (c) 2013 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 -#include -#include - -#include -#include - -#include "json_plist.h" - -static plist_t parse_primitive(const char* js, jsmntok_t* tokens, int* index); -static plist_t parse_string(const char* js, jsmntok_t* tokens, int* index); -static plist_t parse_array(const char* js, jsmntok_t* tokens, int* index); -static plist_t parse_object(const char* js, jsmntok_t* tokens, int* index); - -static char* get_string_value(const char* js, jsmntok_t token) -{ - int len = (token.end - token.start); - char* str = malloc(len+1); - memcpy(str, js + token.start, len); - str[len] = 0; - return str; -} - -static plist_t parse_primitive(const char* js, jsmntok_t* tokens, int* index) -{ - if (tokens[*index].type != JSMN_PRIMITIVE) { - fprintf(stderr, "%s: ERROR: token type != JSMN_PRIMITIVE?!\n", __func__); - return NULL; - } - plist_t val = NULL; - char* strval = get_string_value(js, tokens[*index]); - if (strval[0] == 'f') { - val = plist_new_bool(0); - } else if (strval[0] == 't') { - val = plist_new_bool(1); - } else if ((strval[0] == '-') || ((strval[0] >= '0') && (strval[0] <= '9'))) { - val = plist_new_uint(strtoll(strval, NULL, 10)); - } else { - fprintf(stderr, "%s: WARNING: invalid primitive value '%s' encountered, will return as string\n", __func__, strval); - val = plist_new_string(strval); - } - free(strval); - (*index)++; - return val; -} - -static plist_t parse_string(const char* js, jsmntok_t* tokens, int* index) -{ - if (tokens[*index].type != JSMN_STRING) { - fprintf(stderr, "%s: ERROR: token type != JSMN_STRING?!\n", __func__); - return NULL; - } - char* str = get_string_value(js, tokens[*index]); - plist_t val = plist_new_string(str); - free(str); - (*index)++; - return val; -} - -static plist_t parse_array(const char* js, jsmntok_t* tokens, int* index) -{ - if (tokens[*index].type != JSMN_ARRAY) { - fprintf(stderr, "%s: ERROR: token type != JSMN_ARRAY?!\n", __func__); - return NULL; - } - plist_t arr = plist_new_array(); - int num_tokens = tokens[*index].size; - int num; - int j = (*index)+1; - for (num = 0; num < num_tokens; num++) { - plist_t val = NULL; - switch (tokens[j].type) { - case JSMN_OBJECT: - val = parse_object(js, tokens, &j); - break; - case JSMN_ARRAY: - val = parse_array(js, tokens, &j); - break; - case JSMN_STRING: - val = parse_string(js, tokens, &j); - break; - case JSMN_PRIMITIVE: - val = parse_primitive(js, tokens, &j); - break; - default: - break; - } - if (val) { - plist_array_append_item(arr, val); - } - } - *(index) = j; - return arr; -} - -static plist_t parse_object(const char* js, jsmntok_t* tokens, int* index) -{ - if (tokens[*index].type != JSMN_OBJECT) { - fprintf(stderr, "%s: ERROR: token type != JSMN_OBJECT?!\n", __func__); - return NULL; - } - plist_t obj = plist_new_dict(); - int num_tokens = tokens[*index].size; - int num; - int j = (*index)+1; - for (num = 0; num < num_tokens; num++) { - if (tokens[j].type == JSMN_STRING) { - char* key = get_string_value(js, tokens[j]); - plist_t val = NULL; - j++; - num++; - switch (tokens[j].type) { - case JSMN_OBJECT: - val = parse_object(js, tokens, &j); - break; - case JSMN_ARRAY: - val = parse_array(js, tokens, &j); - break; - case JSMN_STRING: - val = parse_string(js, tokens, &j); - break; - case JSMN_PRIMITIVE: - val = parse_primitive(js, tokens, &j); - break; - default: - break; - } - if (val) { - plist_dict_set_item(obj, key, val); - } - free(key); - } else { - fprintf(stderr, "%s: keys must be of type STRING\n", __func__); - return NULL; - } - } - (*index) = j; - return obj; -} - -plist_t json_to_plist(const char* json_string) -{ - jsmn_parser parser; - jsmn_init(&parser); - int maxtoks = 256; - jsmntok_t *tokens; - - if (!json_string) { - fprintf(stderr, "%s: ERROR: no JSON string given.\n", __func__); - return NULL; - } - - tokens = malloc(sizeof(jsmntok_t)*maxtoks); - if (!tokens) { - fprintf(stderr, "%s: Out of memory\n", __func__); - return NULL; - } - - int r = 0; -reparse: - r = jsmn_parse(&parser, json_string, tokens, maxtoks); - if (r == JSMN_ERROR_NOMEM) { - //printf("not enough tokens (%d), retrying...\n", maxtoks); - maxtoks+=256; - jsmntok_t* newtokens = realloc(tokens, sizeof(jsmntok_t)*maxtoks); - if (newtokens) { - tokens = newtokens; - goto reparse; - } - } - - switch(r) { - case JSMN_ERROR_NOMEM: - fprintf(stderr, "%s: ERROR: Out of memory...\n", __func__); - return NULL; - case JSMN_ERROR_INVAL: - fprintf(stderr, "%s: ERROR: Invalid character inside JSON string\n", __func__); - return NULL; - case JSMN_ERROR_PART: - fprintf(stderr, "%s: ERROR: The string is not a full JSON packet, more bytes expected\n", __func__); - return NULL; - default: - break; - } - - int startindex = 0; - plist_t plist = NULL; - switch (tokens[startindex].type) { - case JSMN_PRIMITIVE: - plist = parse_primitive(json_string, tokens, &startindex); - break; - case JSMN_STRING: - plist = parse_string(json_string, tokens, &startindex); - break; - case JSMN_ARRAY: - plist = parse_array(json_string, tokens, &startindex); - break; - case JSMN_OBJECT: - plist = parse_object(json_string, tokens, &startindex); - break; - default: - break; - } - - free(tokens); - - return plist; -} - diff --git a/src/json_plist.h b/src/json_plist.h deleted file mode 100644 index d6eec0b..0000000 --- a/src/json_plist.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * json_plist.h - * JSON/property list functions (header file) - * - * Copyright (c) 2013 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 - */ -#ifndef __JSON_PLIST_H -#define __JSON_PLIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -plist_t json_to_plist(const char* json_string); - -#ifdef __cplusplus -} -#endif - -#endif -- cgit v1.1-32-gdbae