libdmg-hfsplus/ipsw-patch/plist.c

534 строки
14 KiB
C

#include <stdlib.h>
#include <string.h>
#include <xpwn/plist.h>
#include "common.h"
Tag* getNextTag(char** xmlPtr) {
char* xml;
char* tagEnd;
char* curChar;
Tag* tag;
int tagDepth;
xml = *xmlPtr;
xml = strchr(xml, '<');
if(xml == NULL) {
return NULL;
}
tag = (Tag*) malloc(sizeof(Tag));
tagEnd = strchr(xml, '>');
tag->name = (char*) malloc(sizeof(char) * (tagEnd - xml));
memcpy(tag->name, xml + 1, tagEnd - xml - 1);
tag->name[tagEnd - xml - 1] = '\0';
if((tagEnd - xml - 1) > 0) {
if(tag->name[tagEnd - xml - 2] == '/') {
tag->xml = malloc(sizeof(char) * 1);
tag->xml[0] = '\0';
*xmlPtr = tagEnd + 1;
return tag;
}
}
xml = tagEnd;
curChar = xml;
tagDepth = 1;
while(*curChar != '\0') {
if(*curChar == '<') {
if(*(curChar + 1) == '/') {
tagDepth--;
if(tagDepth == 0) {
break;
}
} else {
tagDepth++;
}
} else if(*curChar == '>') {
if(*(curChar - 1) == '/') {
tagDepth--;
}
}
curChar++;
}
tag->xml = (char*) malloc(sizeof(char) * (curChar - xml));
memcpy(tag->xml, xml + 1, curChar - xml - 1);
tag->xml[curChar - xml - 1] = '\0';
*xmlPtr = strchr(curChar, '>') + 1;
return tag;
}
void releaseTag(Tag* tag) {
free(tag->name);
free(tag->xml);
free(tag);
}
void releaseArray(ArrayValue* myself) {
int i;
free(myself->dValue.key);
for(i = 0; i < myself->size; i++) {
switch(myself->values[i]->type) {
case DictionaryType:
releaseDictionary((Dictionary*) myself->values[i]);
break;
case ArrayType:
releaseArray((ArrayValue*) myself->values[i]);
break;
case StringType:
free(((StringValue*)(myself->values[i]))->value);
case BoolType:
case IntegerType:
free(myself->values[i]->key);
free(myself->values[i]);
break;
}
}
free(myself->values);
free(myself);
}
void releaseDictionary(Dictionary* myself) {
DictValue* next;
DictValue* toRelease;
free(myself->dValue.key);
next = myself->values;
while(next != NULL) {
toRelease = next;
next = next->next;
switch(toRelease->type) {
case DictionaryType:
releaseDictionary((Dictionary*) toRelease);
break;
case ArrayType:
releaseArray((ArrayValue*) toRelease);
break;
case StringType:
free(((StringValue*)(toRelease))->value);
case IntegerType:
case BoolType:
free(toRelease->key);
free(toRelease);
break;
}
}
free(myself);
}
void createArray(ArrayValue* myself, char* xml) {
Tag* valueTag;
DictValue* curValue;
myself->values = NULL;
myself->size = 0;
while(*xml != '\0') {
valueTag = getNextTag(&xml);
if(valueTag == NULL) {
break;
}
myself->size++;
myself->values = realloc(myself->values, sizeof(DictValue*) * myself->size);
curValue = (DictValue*) malloc(sizeof(DictValue));
curValue->key = (char*) malloc(sizeof("arraykey"));
strcpy(curValue->key, "arraykey");
curValue->next = NULL;
if(strcmp(valueTag->name, "dict") == 0) {
curValue->type = DictionaryType;
curValue = (DictValue*) realloc(curValue, sizeof(Dictionary));
createDictionary((Dictionary*) curValue, valueTag->xml);
} else if(strcmp(valueTag->name, "string") == 0) {
curValue->type = StringType;
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(valueTag->xml) + 1));
strcpy(((StringValue*)curValue)->value, valueTag->xml);
} else if(strcmp(valueTag->name, "integer") == 0) {
curValue->type = IntegerType;
curValue = (DictValue*) realloc(curValue, sizeof(IntegerValue));
sscanf(valueTag->xml, "%d", &(((IntegerValue*)curValue)->value));
} else if(strcmp(valueTag->name, "array") == 0) {
curValue->type = ArrayType;
curValue = (DictValue*) realloc(curValue, sizeof(ArrayValue));
createArray((ArrayValue*) curValue, valueTag->xml);
} else if(strcmp(valueTag->name, "true/") == 0) {
curValue->type = BoolType;
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
((BoolValue*)curValue)->value = TRUE;
} else if(strcmp(valueTag->name, "false/") == 0) {
curValue->type = BoolType;
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
((BoolValue*)curValue)->value = FALSE;
}
myself->values[myself->size - 1] = curValue;
releaseTag(valueTag);
}
}
void removeKey(Dictionary* dict, char* key) {
DictValue* next;
DictValue* toRelease;
next = dict->values;
while(next != NULL) {
if(strcmp(next->key, key) == 0) {
toRelease = next;
if(toRelease->prev) {
toRelease->prev->next = toRelease->next;
} else {
dict->values = toRelease->next;
}
if(toRelease->next) {
toRelease->next->prev = toRelease->prev;
}
switch(toRelease->type) {
case DictionaryType:
releaseDictionary((Dictionary*) toRelease);
break;
case ArrayType:
releaseArray((ArrayValue*) toRelease);
break;
case StringType:
free(((StringValue*)(toRelease))->value);
case IntegerType:
case BoolType:
free(toRelease->key);
free(toRelease);
break;
}
return;
}
next = next->next;
}
return;
}
void createDictionary(Dictionary* myself, char* xml) {
Tag* keyTag;
Tag* valueTag;
DictValue* curValue;
DictValue* lastValue;
curValue = NULL;
lastValue = NULL;
while(*xml != '\0') {
keyTag = getNextTag(&xml);
if(keyTag == NULL) {
break;
}
if(strcmp(keyTag->name, "key") != 0) {
releaseTag(keyTag);
continue;
}
curValue = (DictValue*) malloc(sizeof(DictValue));
curValue->key = (char*) malloc(sizeof(char) * (strlen(keyTag->xml) + 1));
strcpy(curValue->key, keyTag->xml);
curValue->next = NULL;
releaseTag(keyTag);
valueTag = getNextTag(&xml);
if(valueTag == NULL) {
break;
}
if(strcmp(valueTag->name, "dict") == 0) {
curValue->type = DictionaryType;
curValue = (DictValue*) realloc(curValue, sizeof(Dictionary));
createDictionary((Dictionary*) curValue, valueTag->xml);
} else if(strcmp(valueTag->name, "string") == 0) {
curValue->type = StringType;
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(valueTag->xml) + 1));
strcpy(((StringValue*)curValue)->value, valueTag->xml);
} else if(strcmp(valueTag->name, "integer") == 0) {
curValue->type = IntegerType;
curValue = (DictValue*) realloc(curValue, sizeof(IntegerValue));
sscanf(valueTag->xml, "%d", &(((IntegerValue*)curValue)->value));
} else if(strcmp(valueTag->name, "array") == 0) {
curValue->type = ArrayType;
curValue = (DictValue*) realloc(curValue, sizeof(ArrayValue));
createArray((ArrayValue*) curValue, valueTag->xml);
} else if(strcmp(valueTag->name, "true/") == 0) {
curValue->type = BoolType;
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
((BoolValue*)curValue)->value = TRUE;
} else if(strcmp(valueTag->name, "false/") == 0) {
curValue->type = BoolType;
curValue = (DictValue*) realloc(curValue, sizeof(BoolValue));
((BoolValue*)curValue)->value = FALSE;
}
curValue->prev = lastValue;
if(lastValue == NULL) {
myself->values = curValue;
} else {
lastValue->next = curValue;
}
lastValue = curValue;
releaseTag(valueTag);
}
}
char* getXmlFromArrayValue(ArrayValue* myself, int tabsCount) {
char tabs[100];
char buffer[4096];
char* toReturn;
char* ret;
size_t toReturnSize;
int i;
DictValue* curValue;
tabs[0] = '\0';
for(i = 0; i < tabsCount; i++) {
strcat(tabs, "\t");
}
sprintf(buffer, "%s<array>\n", tabs);
toReturnSize = sizeof(char) * (strlen(buffer) + 1);
toReturn = malloc(toReturnSize);
toReturn = strcpy(toReturn, buffer);
for(i = 0; i < myself->size; i++) {
curValue = myself->values[i];
if(curValue->type == DictionaryType) {
ret = getXmlFromDictionary((Dictionary*)curValue, tabsCount + 1);
toReturnSize += sizeof(char) * (strlen(ret) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, ret);
free(ret);
} else if(curValue->type == StringType) {
sprintf(buffer, "%s\t<string>%s</string>\n", tabs, ((StringValue*)curValue)->value);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
} else if(curValue->type == IntegerType) {
sprintf(buffer, "%s\t<integer>%d</integer>\n", tabs, ((IntegerValue*)curValue)->value);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
} else if(curValue->type == ArrayType) {
ret = getXmlFromArrayValue((ArrayValue*)curValue, tabsCount + 1);
toReturnSize += sizeof(char) * (strlen(ret) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, ret);
free(ret);
} else if(curValue->type == BoolType) {
if(((BoolValue*)curValue)->value) {
sprintf(buffer, "%s\t<true/>\n", tabs);
} else {
sprintf(buffer, "%s\t<false/>\n", tabs);
}
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
}
}
sprintf(buffer, "%s</array>\n", tabs);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
return toReturn;
}
char* getXmlFromDictionary(Dictionary* myself, int tabsCount) {
char tabs[100];
char buffer[4096];
char* toReturn;
char* ret;
size_t toReturnSize;
int i;
DictValue* curValue;
tabs[0] = '\0';
for(i = 0; i < tabsCount; i++) {
strcat(tabs, "\t");
}
sprintf(buffer, "%s<dict>\n", tabs);
toReturnSize = sizeof(char) * (strlen(buffer) + 1);
toReturn = malloc(toReturnSize);
toReturn = strcpy(toReturn, buffer);
curValue = myself->values;
while(curValue != NULL) {
sprintf(buffer, "%s\t<key>%s</key>\n", tabs, curValue->key);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
if(curValue->type == DictionaryType) {
ret = getXmlFromDictionary((Dictionary*)curValue, tabsCount + 1);
toReturnSize += sizeof(char) * (strlen(ret) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, ret);
free(ret);
} else if(curValue->type == StringType) {
sprintf(buffer, "%s\t<string>%s</string>\n", tabs, ((StringValue*)curValue)->value);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
} else if(curValue->type == IntegerType) {
sprintf(buffer, "%s\t<integer>%d</integer>\n", tabs, ((IntegerValue*)curValue)->value);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
} else if(curValue->type == ArrayType) {
ret = getXmlFromArrayValue((ArrayValue*)curValue, tabsCount + 1);
toReturnSize += sizeof(char) * (strlen(ret) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, ret);
free(ret);
} else if(curValue->type == BoolType) {
if(((BoolValue*)curValue)->value) {
sprintf(buffer, "%s\t<true/>\n", tabs);
} else {
sprintf(buffer, "%s\t<false/>\n", tabs);
}
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
}
curValue = curValue->next;
}
sprintf(buffer, "%s</dict>\n", tabs);
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
return toReturn;
}
Dictionary* createRoot(char* xml) {
Tag* tag;
Dictionary* dict;
xml = strstr(xml, "<dict>");
tag = getNextTag(&xml);
dict = malloc(sizeof(Dictionary));
dict->dValue.next = NULL;
dict->dValue.key = malloc(sizeof("root"));
strcpy(dict->dValue.key, "root");
dict->values = NULL;
createDictionary(dict, tag->xml);
releaseTag(tag);
return dict;
}
char* getXmlFromRoot(Dictionary* root) {
char buffer[4096];
char* toReturn;
char* ret;
size_t toReturnSize;
sprintf(buffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n");
toReturnSize = sizeof(char) * (strlen(buffer) + 1);
toReturn = malloc(toReturnSize);
toReturn = strcpy(toReturn, buffer);
ret = getXmlFromDictionary(root, 0);
toReturnSize += sizeof(char) * (strlen(ret) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, ret);
free(ret);
sprintf(buffer, "</plist>\n");
toReturnSize += sizeof(char) * (strlen(buffer) + 1);
toReturn = realloc(toReturn, toReturnSize);
toReturn = strcat(toReturn, buffer);
return toReturn;
}
DictValue* getValueByKey(Dictionary* myself, const char* key) {
DictValue* next;
if(myself == NULL) {
return NULL;
}
next = myself->values;
while(next != NULL) {
if(strcmp(next->key, key) == 0)
return next;
next = next->next;
}
return NULL;
}
void addStringToArray(ArrayValue* array, char* str) {
DictValue* curValue;
array->size++;
array->values = realloc(array->values, sizeof(DictValue*) * array->size);
curValue = (DictValue*) malloc(sizeof(StringValue));
curValue->key = (char*) malloc(sizeof("arraykey"));
strcpy(curValue->key, "arraykey");
curValue->next = NULL;
curValue->prev = NULL;
curValue->type = StringType;
curValue = (DictValue*) realloc(curValue, sizeof(StringValue));
((StringValue*)curValue)->value = (char*) malloc(sizeof(char) * (strlen(str) + 1));
strcpy(((StringValue*)curValue)->value, str);
array->values[array->size - 1] = curValue;
}
void addBoolToDictionary(Dictionary* dict, const char* key, int value) {
BoolValue* dValue = malloc(sizeof(BoolValue));
dValue->dValue.type = BoolType;
dValue->value = value;
addValueToDictionary(dict, key, (DictValue*) dValue);
}
void addIntegerToDictionary(Dictionary* dict, const char* key, int value) {
IntegerValue* dValue = malloc(sizeof(IntegerValue));
dValue->dValue.type = IntegerType;
dValue->value = value;
addValueToDictionary(dict, key, (DictValue*) dValue);
}
void addValueToDictionary(Dictionary* dict, const char* key, DictValue* value) {
value->key = (char*) malloc(sizeof(char) * (strlen(key) + 1));
strcpy(value->key, key);
DictValue* curValue = dict->values;
DictValue* prevValue = NULL;
while(curValue != NULL) {
prevValue = curValue;
curValue = curValue->next;
}
value->next = NULL;
value->prev = prevValue;
if(prevValue == NULL)
dict->values = value;
else
prevValue->next = value;
}