コード例 #1
0
ファイル: PlistMngr.cpp プロジェクト: azerg/NppBplistPlugin
  //
  // If plist_from_bin will fail, xmlBuff_ will remain unchanged, pointing to PREVIOUS-SAVED xml buffer.
  //
  const CharVt& PlistEntry::GetXML(CharVt&& BplistBuff)
  {
    GuardedPlist plist;
    try
    {
      plist_from_bin(BplistBuff.data(), BplistBuff.size(), plist.get_ptr());
    }
    catch (...)
    {
      // catch SEH exceptions (/withSEH)
      throw std::system_error(std::error_code(EFAULT, std::generic_category()), "Invalid bplist file! Cant parse it");
    }

    uint32_t cbXML = 0;
    char* pXML_{};
    plist_to_xml( plist, &pXML_, &cbXML );

    if ( cbXML > 0 )
    {
      xmlBuff_.assign( pXML_, pXML_ + cbXML );
      // free mem allocated by plist_to_xml
      free( pXML_ );
    }

    if ( xmlBuff_.empty() )
    {
      contentType_ = ContentType::corrupted;
      throw std::runtime_error( "error converting bplist to xml" );
    }

    contentType_ = ContentType::xml;

    return xmlBuff_;
  }
コード例 #2
0
ファイル: MobileSync.c プロジェクト: ingmarv/libiphone
/** Polls the iPhone for MobileSync data.
 *
 * @param client The MobileSync client
 * @param plist A pointer to the location where the plist should be stored
 *
 * @return an error code
 */
mobilesync_error_t mobilesync_recv(mobilesync_client_t client, plist_t * plist)
{
	if (!client || !plist || (plist && *plist))
		return MOBILESYNC_E_INVALID_ARG;
	mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR;
	char *receive = NULL;
	uint32_t datalen = 0, bytes = 0, received_bytes = 0;

	ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
	datalen = ntohl(datalen);

	receive = (char *) malloc(sizeof(char) * datalen);

	/* fill buffer and request more packets if needed */
	while ((received_bytes < datalen) && (ret == MOBILESYNC_E_SUCCESS)) {
		ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes);
		received_bytes += bytes;
	}

	if (ret != MOBILESYNC_E_SUCCESS) {
		free(receive);
		return MOBILESYNC_E_MUX_ERROR;
	}

	plist_from_bin(receive, received_bytes, plist);
	free(receive);

	char *XMLContent = NULL;
	uint32_t length = 0;
	plist_to_xml(*plist, &XMLContent, &length);
	log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent);
	free(XMLContent);

	return ret;
}
コード例 #3
0
ファイル: MobileSync.c プロジェクト: ingmarv/libiphone
/** Sends MobileSync data to the iPhone
 * 
 * @note This function is low-level and should only be used if you need to send
 *        a new type of message.
 *
 * @param client The MobileSync client
 * @param plist The location of the plist to send
 *
 * @return an error code
 */
mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist)
{
	if (!client || !plist)
		return MOBILESYNC_E_INVALID_ARG;

	char *XMLContent = NULL;
	uint32_t length = 0;
	plist_to_xml(plist, &XMLContent, &length);
	log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent);
	free(XMLContent);

	char *content = NULL;
	length = 0;

	plist_to_bin(plist, &content, &length);

	char *real_query;
	int bytes;
	mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR;

	real_query = (char *) malloc(sizeof(char) * (length + 4));
	length = htonl(length);
	memcpy(real_query, &length, sizeof(length));
	memcpy(real_query + 4, content, ntohl(length));

	ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
	free(real_query);
	return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR);
}
コード例 #4
0
ファイル: ibrowserAPI.cpp プロジェクト: Y1Fo/ibrowser_plugin
FB::variant ibrowserAPI::getAppList(F_ADD)
{
    THREAD(&ibrowserAPI::getAppList);
    
    char *xml_doc=NULL;
    uint32_t xml_length=0;
    plist_t node = NULL;
    
    plist_t client_opts = instproxy_client_options_new();
    instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL);
    
    if(INSTPROXY_E_SUCCESS != instproxy_browse(instproxy_client,client_opts,&node))
    {
        ERRO("instproxy_browse");
    }
    
    instproxy_client_options_free(client_opts);
    
    plist_to_xml(node, &xml_doc, &xml_length);
    plist_free(node);
    
    SUCC(xml_doc);
    
    return xml_doc;
}
コード例 #5
0
ファイル: ibrowserAPI.cpp プロジェクト: Y1Fo/ibrowser_plugin
FB::variant ibrowserAPI::getDeviceInfo(const std::vector<std::string>& domains,F_ADD)
{
    
    THREAD(&ibrowserAPI::getDeviceInfo, domains);
    
    std::vector<std::string> result;
    
    for(int i=0;i<domains.size();i++)
    {
        std::string domain = domains[i];
        plist_t node = NULL;
        int ret = 0;
        if(LOCKDOWN_E_SUCCESS != (ret = lockdownd_get_value(lockdownd_client, domain.empty()?NULL:domain.c_str(), NULL, &node)) ) {
            ERRO("lockdownd_get_value");
        }
        
        char *xml_doc=NULL;
        uint32_t xml_length;
        plist_to_xml(node, &xml_doc, &xml_length);
        plist_free(node);
        
        result.insert(result.end(),std::string(xml_doc));
        free(xml_doc);
    }

    SUCC(result);
    
    return result;
}
コード例 #6
0
ファイル: common.c プロジェクト: MephistoLa/bootsigned
void debug_plist(plist_t plist) {
	int size = 0;
	char* data = NULL;
	plist_to_xml(plist, &data, &size);
	info("%s", data);
	free(data);
}
コード例 #7
0
dl_status dl_start(dl_t self) {
  // Assume usbmuxd supports proto_version 1.  If not then we'd need to
  // send a binary listen request, check for failure, then retry this:
  plist_t dict = plist_new_dict();
  plist_dict_insert_item(dict, "ClientVersionString", plist_new_string(
        "device_listener"));
  plist_dict_insert_item(dict, "MessageType", plist_new_string("Listen"));
  plist_dict_insert_item(dict, "ProgName", plist_new_string("libusbmuxd"));
  char *xml = NULL;
  uint32_t xml_length = 0;
  plist_to_xml(dict, &xml, &xml_length);
  plist_free(dict);

  size_t length = 16 + xml_length;
  char *packet = (char *)calloc(length, sizeof(char));
  if (!packet) {
    return DL_ERROR;
  }
  char *tail = packet;
  tail = dl_sprintf_uint32(tail, length);
  tail = dl_sprintf_uint32(tail, 1); // version: 1
  tail = dl_sprintf_uint32(tail, TYPE_PLIST); // type: plist
  tail = dl_sprintf_uint32(tail, 1); // tag: 1
  tail = stpncpy(tail, xml, xml_length);
  free(xml);

  dl_status ret = self->send_packet(self, packet, length);
  free(packet);
  return ret;
}
コード例 #8
0
wi_status recv_plist(wi_t wi, const plist_t rpc_dict) {
  char *xml = NULL;
  uint32_t length = 0;
  plist_to_xml(rpc_dict, &xml, &length);
  puts(xml);
  free(xml);
  return WI_SUCCESS;
}
コード例 #9
0
static void print_xml(plist_t node)
{
	char *xml = NULL;
	uint32_t len = 0;
	plist_to_xml(node, &xml, &len);
	if (xml)
		puts(xml);
}
コード例 #10
0
ファイル: common.c プロジェクト: tihmstar/idevicerestore
void debug_plist(plist_t plist) {
	uint32_t size = 0;
	char* data = NULL;
	plist_to_xml(plist, &data, &size);
	if (size <= MAX_PRINT_LEN)
		info("%s:printing %i bytes plist:\n%s", __FILE__, size, data);
	else
		info("%s:supressed printing %i bytes plist...\n", __FILE__, size);
	free(data);
}
コード例 #11
0
static plist_t plist_data_from_plist(plist_t plist)
{
	if (plist && plist_get_node_type(plist) == PLIST_DATA) {
		return plist_copy(plist);
	}
	plist_t result = NULL;
	char *xml = NULL;
	uint32_t xml_len = 0;
	plist_to_xml(plist, &xml, &xml_len);
	result = plist_new_data(xml, xml_len);
	free(xml);
	return result;
}
コード例 #12
0
ファイル: client.c プロジェクト: badania/usbmuxd
static int send_plist_pkt(struct mux_client *client, uint32_t tag, plist_t plist)
{
	int res = -1;
	char *xml = NULL;
	uint32_t xmlsize = 0;
	plist_to_xml(plist, &xml, &xmlsize);
	if (xml) {
		res = send_pkt(client, tag, MESSAGE_PLIST, xml, xmlsize);
		free(xml);
	} else {
		usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
	}
	return res;
}
コード例 #13
0
ファイル: ibrowserAPI.cpp プロジェクト: Y1Fo/ibrowser_plugin
void ibrowserAPI::installCallback(const char *operation, plist_t status, void *user_data) {
    char *xml_doc=NULL;
    uint32_t xml_length;
    
    Callback *cb = (Callback *)user_data;
    
    FB::JSObjectPtr pcb = cb->get("pcb");
    FB::JSObjectPtr scb = cb->get("scb");
    FB::JSObjectPtr ecb = cb->get("ecb");
    
    if(pcb)
    {
        plist_to_xml(status, &xml_doc, &xml_length);
        pcb->InvokeAsync("", FB::variant_list_of(xml_doc));
        free(xml_doc);
    }
    
    plist_dict_iter it = NULL;
	char* key = NULL;
    char*   s = NULL;
	plist_t subnode = NULL;
	plist_dict_new_iter(status, &it);
	plist_dict_next_item(status, it, &key, &subnode);
	while (subnode)
	{
		if(strcmp(key, "Error") == 0)
        {
            plist_get_string_val(subnode, &s);
            if(ecb)
                ecb->InvokeAsync("", FB::variant_list_of(s));
            
        }else if(strcmp(key, "Status") == 0){
            plist_get_string_val(subnode, &s);
            if(strcmp(s, "Complete") == 0){
                if(scb)
                    scb->InvokeAsync("", FB::variant_list_of(NULL));
            }
        }
		plist_dict_next_item(status, it, &key, &subnode);
        
	}

    if(key)
        free(key);
    if(s)
        free(s);
	free(it);
    return;
}
コード例 #14
0
ファイル: asr.c プロジェクト: Blackmamba0/idevicerestore
int asr_send(asr_client_t asr, plist_t data) {
	uint32_t size = 0;
	char* buffer = NULL;

	plist_to_xml(data, &buffer, &size);
	if (asr_send_buffer(asr, buffer, size) < 0) {
		error("ERROR: Unable to send plist to ASR\n");
		free(buffer);
		return -1;
	}

	if (buffer)
		free(buffer);
	return 0;
}
コード例 #15
0
ファイル: asr.c プロジェクト: rcg4u/idevicerestore
int asr_send(idevice_connection_t asr, plist_t* data) {
	uint32_t size = 0;
	char* buffer = NULL;

	plist_to_xml(data, &buffer, &size);
	if (asr_send_buffer(asr, buffer, size) < 0) {
		error("ERROR: Unable to send plist to ASR\n");
		free(buffer);
		return -1;
	}

	debug("Sent %d bytes:\n", size);
	debug_plist(data);
	free(buffer);
	return 0;
}
コード例 #16
0
ファイル: cache.c プロジェクト: boxingcow/ideviceactivate
int cache_plist(const char *fname, plist_t plist)
{
	if (backup_to_cache==1)
	{
		uint32_t len=0;
		char *xml=NULL;

		plist_to_xml(plist, &xml, &len);

		return cache(fname, (const char *)xml);
	}

	else {
		return -1;
	}
}
コード例 #17
0
/**
 * Sends a plist using the given property list service client.
 * Internally used generic plist send function.
 *
 * @param client The property list service client to use for sending.
 * @param plist plist to send
 * @param binary 1 = send binary plist, 0 = send xml plist
 *
 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
 *      PROPERTY_LIST_SERVICE_E_INVALID_ARG when one or more parameters are
 *      invalid, PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid
 *      plist, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified
 *      error occurs.
 */
static property_list_service_error_t internal_plist_send(property_list_service_client_t client, plist_t plist, int binary)
{
	property_list_service_error_t res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR;
	char *content = NULL;
	uint32_t length = 0;
	uint32_t nlen = 0;
	int bytes = 0;

	if (!client || (client && !client->parent) || !plist) {
		return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
	}

	if (binary) {
		plist_to_bin(plist, &content, &length);
	} else {
		plist_to_xml(plist, &content, &length);
	}

	if (!content || length == 0) {
		return PROPERTY_LIST_SERVICE_E_PLIST_ERROR;
	}

	nlen = htobe32(length);
	debug_info("sending %d bytes", length);
	service_send(client->parent, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
	if (bytes == sizeof(nlen)) {
		service_send(client->parent, content, length, (uint32_t*)&bytes);
		if (bytes > 0) {
			debug_info("sent %d bytes", bytes);
			debug_plist(plist);
			if ((uint32_t)bytes == length) {
				res = PROPERTY_LIST_SERVICE_E_SUCCESS;
			} else {
				debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length);
			}
		}
	}
	if (bytes <= 0) {
		debug_info("ERROR: sending to device failed.");
	}

	free(content);

	return res;
}
コード例 #18
0
ファイル: debug.c プロジェクト: Cunzhang/libimobiledevice-1
inline void debug_plist_real(const char *func, const char *file, int line, plist_t plist)
{
#ifndef STRIP_DEBUG_CODE
	if (!plist)
		return;

	char *buffer = NULL;
	uint32_t length = 0;
	plist_to_xml(plist, &buffer, &length);

	/* get rid of ending newline as one is already added in the debug line */
	if (buffer[length-1] == '\n')
		buffer[length-1] = '\0';

	debug_info_real(func, file, line, "printing %i bytes plist:\n%s", length, buffer);
	free(buffer);
#endif
}
コード例 #19
0
ファイル: asr.c プロジェクト: Aphelion01/signedtetherboot
int asr_send(idevice_connection_t asr, plist_t* data) {
	uint32_t size = 0;
	char* buffer = NULL;

	plist_to_xml(data, &buffer, &size);
	if (asr_send_buffer(asr, buffer, size) < 0) {
		error("ERROR: Unable to send plist to ASR\n");
		free(buffer);
		return -1;
	}

	debug("Sent %d bytes:\n", size);

	// TODO: Actually figure out the problem with the commented out code below, instead of just ditching it...
	/*if (idevicerestore_debug)
		debug_plist(*data);
	free(buffer);*/
	return 0;
}
コード例 #20
0
ファイル: utils.c プロジェクト: JeremyAgost/usbmuxd
int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format)
{
	char *buffer = NULL;
	uint32_t length;

	if (!plist || !filename)
		return 0;

	if (format == PLIST_FORMAT_XML)
		plist_to_xml(plist, &buffer, &length);
	else if (format == PLIST_FORMAT_BINARY)
		plist_to_bin(plist, &buffer, &length);
	else
		return 0;

	buffer_write_to_filename(filename, buffer, length);

	free(buffer);

	return 1;
}
コード例 #21
0
ファイル: NotificationProxy.c プロジェクト: ingmarv/libiphone
/**
 * Sends an xml plist to the device using the connection specified in client.
 * This function is only used internally.
 *
 * @param client NP to send data to
 * @param dict plist to send
 *
 * @return NP_E_SUCCESS or an error code.
 */
static np_error_t np_plist_send(np_client_t client, plist_t dict)
{
	char *XML_content = NULL;
	uint32_t length = 0;
	uint32_t nlen = 0;
	int bytes = 0;
	np_error_t res = NP_E_UNKNOWN_ERROR;

	if (!client || !dict) {
		return NP_E_INVALID_ARG;
	}

	plist_to_xml(dict, &XML_content, &length);

	if (!XML_content || length == 0) {
		return NP_E_PLIST_ERROR;
	}

	nlen = htonl(length);
	iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
	if (bytes == sizeof(nlen)) {
		iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes);
		if (bytes > 0) {
			if ((uint32_t)bytes == length) {
				res = NP_E_SUCCESS;
			} else {
				log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length);
			}
		}
	}
	if (bytes <= 0) {
		log_debug_msg("%s: ERROR: sending to device failed.\n", __func__);
	}

	free(XML_content);

	return res;
}
コード例 #22
0
ファイル: tss.c プロジェクト: MephistoLa/bootsigned
plist_t tss_send_request(plist_t tss_request) {
	curl_global_init(CURL_GLOBAL_ALL);

	int status_code = -1;
	char* request = NULL;
	int retry = 0;
	int max_retries = 15;
	unsigned int size = 0;
	plist_to_xml(tss_request, &request, &size);

	tss_response* response = NULL;

	while (retry++ < max_retries) {
		response = NULL;
		CURL* handle = curl_easy_init();
		if (handle == NULL) {
			break;
		}
		struct curl_slist* header = NULL;
		header = curl_slist_append(header, "Cache-Control: no-cache");
		header = curl_slist_append(header, "Content-type: text/xml; charset=\"utf-8\"");
		header = curl_slist_append(header, "Expect:");

		response = malloc(sizeof(tss_response));
		if (response == NULL) {
			fprintf(stderr, "Unable to allocate sufficent memory\n");
			return NULL;
		}

		response->length = 0;
		response->content = malloc(1);
		response->content[0] = '\0';

		curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&tss_write_callback);
		curl_easy_setopt(handle, CURLOPT_WRITEDATA, response);
		curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header);
		curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request);
		curl_easy_setopt(handle, CURLOPT_USERAGENT, "InetURL/1.0");
		curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(request));
		if (use_apple_server==0) {
			curl_easy_setopt(handle, CURLOPT_URL, "http://cydia.saurik.com/TSS/controller?action=2");
		} else {
			curl_easy_setopt(handle, CURLOPT_URL, "http://gs.apple.com/TSS/controller?action=2");
		}

		curl_easy_perform(handle);
		curl_slist_free_all(header);
		curl_easy_cleanup(handle);
	
		if (strstr(response->content, "MESSAGE=SUCCESS")) {
			status_code = 0;
			break;
		}

		if (response->length > 0) {
			error("TSS server returned: %s\n", response->content);
		}

		char* status = strstr(response->content, "STATUS=");
		if (status) {
			sscanf(status+7, "%d&%*s", &status_code);
		}
		if (status_code == -1) {
			// no status code in response. retry
			free(response->content);
			free(response);
			sleep(2);
			continue;
		} else if (status_code == 94) {
			// This device isn't eligible for the requested build.
			break;
		} else if (status_code == 100) {
			// server error, most likely the request was malformed
			break;
		} else {
			error("ERROR: tss_send_request: Unhandled status code %d\n", status_code);
		}
	}

	if (status_code != 0) {
		error("ERROR: TSS request failed (status=%d)\n", status_code);
		free(response->content);
		free(response);
		free(request);
		return NULL;
	}

	char* tss_data = strstr(response->content, "<?xml");
	if (tss_data == NULL) {
		error("ERROR: Incorrectly formatted TSS response\n");
		free(response->content);
		free(response);
		free(request);
		return NULL;
	}

	uint32_t tss_size = 0;
	plist_t tss_response = NULL;
	tss_size = response->length - (tss_data - response->content);
	plist_from_xml(tss_data, tss_size, &tss_response);
	free(response->content);
	free(response);

	if (idevicerestore_debug) {
		debug_plist(tss_response);
	}

	free(request);
	curl_global_cleanup();

	return tss_response;
}
コード例 #23
0
ファイル: ideviceinfo.c プロジェクト: awadaolqi/irestore
int main(int argc, char *argv[])
{
	lockdownd_client_t client = NULL;
	idevice_t phone = NULL;
	idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
	int i;
	int simple = 0;
	int format = FORMAT_KEY_VALUE;
	char uuid[41];
	char *domain = NULL;
	char *key = NULL;
	char *xml_doc = NULL;
	uint32_t xml_length;
	plist_t node = NULL;
	plist_type node_type;
	uuid[0] = 0;

	/* parse cmdline args */
	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
			idevice_set_debug_level(1);
			continue;
		}
		else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--uuid")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) != 40)) {
				print_usage(argc, argv);
				return 0;
			}
			strcpy(uuid, argv[i]);
			continue;
		}
		else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--domain")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) < 4)) {
				print_usage(argc, argv);
				return 0;
			}
			if (!is_domain_known(argv[i])) {
				fprintf(stderr, "WARNING: Sending query with unknown domain \"%s\".\n", argv[i]);
			}
			domain = strdup(argv[i]);
			continue;
		}
		else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--key")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) <= 1)) {
				print_usage(argc, argv);
				return 0;
			}
			key = strdup(argv[i]);
			continue;
		}
		else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) {
			format = FORMAT_XML;
			continue;
		}
		else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--simple")) {
			simple = 1;
			continue;
		}
		else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
			print_usage(argc, argv);
			return 0;
		}
		else {
			print_usage(argc, argv);
			return 0;
		}
	}

	if (uuid[0] != 0) {
		ret = idevice_new(&phone, uuid);
		if (ret != IDEVICE_E_SUCCESS) {
			printf("No device found with uuid %s, is it plugged in?\n", uuid);
			return -1;
		}
	}
	else
	{
		ret = idevice_new(&phone, NULL);
		if (ret != IDEVICE_E_SUCCESS) {
			printf("No device found, is it plugged in?\n");
			return -1;
		}
	}

	if (LOCKDOWN_E_SUCCESS != (simple ?
			lockdownd_client_new(phone, &client, "ideviceinfo"):
			lockdownd_client_new_with_handshake(phone, &client, "ideviceinfo"))) {
		idevice_free(phone);
		return -1;
	}

	/* run query and output information */
	if(lockdownd_get_value(client, domain, key, &node) == LOCKDOWN_E_SUCCESS) {
		if (node) {
			switch (format) {
			case FORMAT_XML:
				plist_to_xml(node, &xml_doc, &xml_length);
				printf("%s", xml_doc);
				free(xml_doc);
				break;
			case FORMAT_KEY_VALUE:
				node_type = plist_get_node_type(node);
				if (node_type == PLIST_DICT) {
					plist_dict_to_string(node);
				} else if (node_type == PLIST_ARRAY) {
					plist_array_to_string(node);
					break;
				}
			default:
				if (key != NULL)
					plist_node_to_string(node);
			break;
			}
			plist_free(node);
			node = NULL;
		}
	}

	if (domain != NULL)
		free(domain);
	lockdownd_client_free(client);
	idevice_free(phone);

	return 0;
}
コード例 #24
0
ファイル: ipod-lockdown.c プロジェクト: Babl0lka/libgpod
G_GNUC_INTERNAL char *
read_sysinfo_extended_by_uuid (const char *uuid)
{
	lockdownd_client_t client = NULL;
	idevice_t device = NULL;
	idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
	char *xml = NULL; char *str = NULL;
	char *gxml;
	uint32_t xml_length = 0;
	plist_t value = NULL;
	plist_t global = NULL;
	plist_t ptr = NULL;
	int cnt = 0;

	/* usbmuxd needs some time to start up so we try several times
	 * to open the device before finally returning with an error */ 
	while (cnt++ < 20) {
		ret = idevice_new(&device, uuid);
		if (ret == IDEVICE_E_SUCCESS) {
			break;
		}
		if (ret != IDEVICE_E_NO_DEVICE) {
			break;
		}
		g_usleep (G_USEC_PER_SEC / 2);
	}
	if (ret != IDEVICE_E_SUCCESS) {
		printf("No device found with uuid %s, is it plugged in?\n", uuid);
		return NULL;
	}

	if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &client, "libgpod")) {
		idevice_free(device);
		return NULL;
	}

	/* run query and get format plist */
	lockdownd_get_value(client, NULL, NULL, &global);
	lockdownd_get_value(client, "com.apple.mobile.iTunes", NULL, &value);
	
	/* add some required values manually to emulate old plist format */
	ptr = plist_dict_get_item(global, "SerialNumber");
	plist_get_string_val(ptr, &str);
	if (str != NULL) {
	    ptr = plist_new_string(str);
	    plist_dict_insert_item(value, "SerialNumber", ptr);
	    free(str);
	}

	ptr = plist_dict_get_item(global, "ProductVersion");
	plist_get_string_val(ptr, &str);
	if (str != NULL) {
	    ptr = plist_new_string(str);
	    plist_dict_insert_item(value, "VisibleBuildID", ptr);
	    free(str);
	}

	ptr = plist_new_string(uuid);
	plist_dict_insert_item(value, "FireWireGUID", ptr);

	ptr = plist_new_string(uuid);
	plist_dict_insert_item(value, "UniqueDeviceID", ptr);

	plist_to_xml(value, &xml, &xml_length);

	ptr = NULL;
	if (value)
		plist_free(value);
	value = NULL;
	if (global)
		plist_free(global);
	global = NULL;

	lockdownd_client_free(client);
	idevice_free(device);

	/* Jump through hoops since libxml will say to free mem it allocated
	 * with xmlFree while memory freed with g_free has to be allocated
	 * by glib.
	 */
	if (xml != NULL) {
		gxml = g_strdup(xml);
		xmlFree(xml);
	} else {
		gxml = NULL;
	}
	return gxml;
}
コード例 #25
0
ファイル: iphoneinfo.c プロジェクト: sladen/libiphone
void print_lckd_request_result(iphone_lckd_client_t control, const char *domain, const char *request, const char *key, int format) {
	char *xml_doc = NULL;
	char *s = NULL;
	uint32_t xml_length = 0;
	iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
	
	plist_t node = plist_new_dict();
	if (domain) {
		plist_add_sub_key_el(node, "Domain");
		plist_add_sub_string_el(node, domain);
	}
	if (key) {
		plist_add_sub_key_el(node, "Key");
		plist_add_sub_string_el(node, key);
	}
	plist_add_sub_key_el(node, "Request");
	plist_add_sub_string_el(node, request);

	ret = iphone_lckd_send(control, node);
	if (ret == IPHONE_E_SUCCESS) {
		plist_free(node);
		node = NULL;
		ret = iphone_lckd_recv(control, &node);
		if (ret == IPHONE_E_SUCCESS) {
			/* seek to value node */
			for (
				node = plist_get_first_child(node);
				node != NULL;
				node = plist_get_next_sibling(node)
			) {
				if(plist_get_node_type(node) == PLIST_KEY)
				{
					plist_get_key_val(node, &s);

					if (strcmp("Value", s))
						continue;

					node = plist_get_next_sibling(node);

					if (plist_get_node_type(node) == PLIST_DICT) {
						if (plist_get_first_child(node))
						{
							switch (format) {
							case FORMAT_XML:
								plist_to_xml(node, &xml_doc, &xml_length);
								printf(xml_doc);
								free(xml_doc);
								break;
							case FORMAT_KEY_VALUE:
							default:
								plist_children_to_string(node);
								break;
							}
						}
					}
					else if(node && (key != NULL))
						plist_node_to_string(node);
				}
			}
		}
	}
	if (node)
		plist_free(node);
	node = NULL;
}
コード例 #26
0
int main(int argc, char *argv[])
{
	lockdownd_client_t client = NULL;
	lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
	lockdownd_service_descriptor_t service = NULL;
	idevice_t device = NULL;
	idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
	int i;
	int op = -1;
	int output_xml = 0;
	const char* udid = NULL;
	const char* param = NULL;

	/* parse cmdline args */
	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) {
			idevice_set_debug_level(1);
			continue;
		}
		else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) != 40)) {
				print_usage(argc, argv);
				return 0;
			}
			udid = argv[i];
			continue;
		}
		else if (!strcmp(argv[i], "install")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) < 1)) {
				print_usage(argc, argv);
				return 0;
			}
			param = argv[i];
			op = OP_INSTALL;
			continue;
		}
		else if (!strcmp(argv[i], "list")) {
			op = OP_LIST;
		}
		else if (!strcmp(argv[i], "copy")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) < 1)) {
				print_usage(argc, argv);
				return 0;
			}
			param = argv[i];
			op = OP_COPY;
			continue;
		}
		else if (!strcmp(argv[i], "remove")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) < 1)) {
				print_usage(argc, argv);
				return 0;
			}
			param = argv[i];
			op = OP_REMOVE;
			continue;
		}
		else if (!strcmp(argv[i], "dump")) {
			i++;
			if (!argv[i] || (strlen(argv[i]) < 1)) {
				print_usage(argc, argv);
				return 0;
			}
			param = argv[i];
			op = OP_DUMP;
			continue;
		}
		else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) {
			output_xml = 1;
			continue;
		}
		else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
			print_usage(argc, argv);
			return 0;
		}
		else {
			print_usage(argc, argv);
			return 0;
		}
	}

	if ((op == -1) || (op >= NUM_OPS)) {
		print_usage(argc, argv);
		return 0;
	}

	if (op == OP_DUMP) {
		int res = 0;
		unsigned char* profile_data = NULL;
		unsigned int profile_size = 0;
		if (profile_read_from_file(param, &profile_data, &profile_size) != 0) {
			return -1;
		}
		plist_t pdata = plist_new_data((char*)profile_data, profile_size);
		plist_t pl = profile_get_embedded_plist(pdata);
		plist_free(pdata);
		free(profile_data);

		if (pl) {
			if (output_xml) {
				char* xml = NULL;
				uint32_t xlen = 0;
				plist_to_xml(pl, &xml, &xlen);
				if (xml) {
					printf("%s\n", xml);
					free(xml);
				}
			} else {
				if (pl && (plist_get_node_type(pl) == PLIST_DICT)) {
					plist_print_to_stream(pl, stdout);
				} else {
					fprintf(stderr, "ERROR: unexpected node type in profile plist (not PLIST_DICT)\n");
					res = -1;
				}
			}
		} else {
			fprintf(stderr, "ERROR: could not extract embedded plist from profile!\n");
		}
		plist_free(pl);

		return res;
	}

	ret = idevice_new(&device, udid);
	if (ret != IDEVICE_E_SUCCESS) {
		if (udid) {
			printf("No device found with udid %s, is it plugged in?\n", udid);
		} else {
			printf("No device found, is it plugged in?\n");
		}
		return -1;
	}

	if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(device, &client, "ideviceprovision"))) {
		fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret);
		idevice_free(device);
		return -1;
	}

	if (LOCKDOWN_E_SUCCESS != lockdownd_start_service(client, "com.apple.misagent", &service)) {
		fprintf(stderr, "Could not start service \"com.apple.misagent\"\n");
		lockdownd_client_free(client);
		idevice_free(device);
		return -1;
	}
	lockdownd_client_free(client);
	client = NULL;

	misagent_client_t mis = NULL;
	if (misagent_client_new(device, service, &mis) != MISAGENT_E_SUCCESS) {
		fprintf(stderr, "Could not connect to \"com.apple.misagent\" on device\n");
		if (service)
			lockdownd_service_descriptor_free(service);
		lockdownd_client_free(client);
		idevice_free(device);
		return -1;
	}

	if (service)
		lockdownd_service_descriptor_free(service);

	switch (op) {
		case OP_INSTALL:
		{
			unsigned char* profile_data = NULL;
			unsigned int profile_size = 0;
			if (profile_read_from_file(param, &profile_data, &profile_size) != 0) {
				break;
			}

			uint64_t psize = profile_size;
			plist_t pdata = plist_new_data((const char*)profile_data, psize);
			free(profile_data);

			if (misagent_install(mis, pdata) == MISAGENT_E_SUCCESS) {
				printf("Profile '%s' installed successfully.\n", param);
			} else {
				int sc = misagent_get_status_code(mis);
				fprintf(stderr, "Could not install profile '%s', status code: 0x%x\n", param, sc);
			}
		}
			break;
		case OP_LIST:
		case OP_COPY:
		{
			plist_t profiles = NULL;
			if (misagent_copy(mis, &profiles) == MISAGENT_E_SUCCESS) {
				uint32_t num_profiles = plist_array_get_size(profiles);
				printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles");
				uint32_t j;
				for (j = 0; j < num_profiles; j++) {
					char* p_name = NULL;
					char* p_uuid = NULL;
					plist_t profile = plist_array_get_item(profiles, j);
					plist_t pl = profile_get_embedded_plist(profile);
					if (pl && (plist_get_node_type(pl) == PLIST_DICT)) {
						plist_t node;
						node = plist_dict_get_item(pl, "Name");
						if (node && (plist_get_node_type(node) == PLIST_STRING)) {
							plist_get_string_val(node, &p_name);
						}
						node = plist_dict_get_item(pl, "UUID");
						if (node && (plist_get_node_type(node) == PLIST_STRING)) {
							plist_get_string_val(node, &p_uuid);
						}
					}
					printf("%s - %s\n", (p_uuid) ? p_uuid : "(unknown id)", (p_name) ? p_name : "(no name)");
					if (op == OP_COPY) {
						char pfname[512];
						if (p_uuid) {
							sprintf(pfname, "%s/%s.mobileprovision", param, p_uuid);
						} else {
							sprintf(pfname, "%s/profile%d.mobileprovision", param, j);
						}
						FILE* f = fopen(pfname, "wb");
						if (f) {
							char* dt = NULL;
							uint64_t ds = 0;
							plist_get_data_val(profile, &dt, &ds);
							fwrite(dt, 1, ds, f);
							fclose(f);
							printf(" => %s\n", pfname);
						} else {
							fprintf(stderr, "Could not open '%s' for writing\n", pfname);
						}
					}
					if (p_uuid) {
						free(p_uuid);
					}
					if (p_name) {
						free(p_name);
					}
				}
			} else {
				int sc = misagent_get_status_code(mis);
				fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc);
			}
		}
			break;
		case OP_REMOVE:
			if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) {
				printf("Profile '%s' removed.\n", param);
			} else {
				int sc = misagent_get_status_code(mis);
				fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc);
			}
			break;
		default:
			break;
	}

	misagent_client_free(mis);

	idevice_free(device);

	return 0;
}
コード例 #27
0
ファイル: lckdclient.c プロジェクト: ax003d/libimobiledevice
int main(int argc, char *argv[])
{
	lockdownd_client_t client = NULL;
	idevice_t phone = NULL;

	idevice_set_debug_level(1);

	if (IDEVICE_E_SUCCESS != idevice_new(&phone, NULL)) {
		printf("No device found, is it plugged in?\n");
		return -1;
	}

	char *udid = NULL;
	if (IDEVICE_E_SUCCESS == idevice_get_udid(phone, &udid)) {
		printf("DeviceUniqueID : %s\n", udid);
	}
	if (udid)
		free(udid);

	if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "lckdclient")) {
		idevice_free(phone);
		return -1;
	}

	using_history();
	int loop = 1;
	while (loop) {
		char *cmd = readline("> ");
		if (cmd) {

			char **args = get_tokens(cmd);

			int len = 0;
			while (args && args[len]) {
				len++;
			}

			if (len > 0) {
				add_history(cmd);
				if (!strcmp(*args, "quit"))
					loop = 0;

				if (!strcmp(*args, "get") && len >= 2) {
					plist_t value = NULL;
					if (LOCKDOWN_E_SUCCESS == lockdownd_get_value(client, len == 3 ? *(args + 1):NULL,  len == 3 ? *(args + 2):*(args + 1), &value))
					{
						char *xml = NULL;
						uint32_t length;
						plist_to_xml(value, &xml, &length);
						printf("Success : value = %s\n", xml);
						free(xml);
					}
					else
						printf("Error\n");

					if (value)
						plist_free(value);
				}

				if (!strcmp(*args, "start") && len == 2) {
					uint16_t port = 0;
					if(LOCKDOWN_E_SUCCESS == lockdownd_start_service(client, *(args + 1), &port)) {
						printf("started service %s on port %i\n", *(args + 1), port);
					}
					else
					{
						printf("failed to start service %s on device.\n", *(args + 1));
					}
				}
			}
			strfreev(args);
		}
		free(cmd);
		cmd = NULL;
	}
	clear_history();
	lockdownd_client_free(client);
	idevice_free(phone);

	return 0;
}
コード例 #28
0
ファイル: plist_test.c プロジェクト: EchoLiao/libplist
int main(int argc, char *argv[])
{
    FILE *iplist = NULL;
    plist_t root_node1 = NULL;
    plist_t root_node2 = NULL;
    char *plist_xml = NULL;
    char *plist_xml2 = NULL;
    char *plist_bin = NULL;
    int size_in = 0;
    uint32_t size_out = 0;
    uint32_t size_out2 = 0;
    char *file_in = NULL;
    char *file_out = NULL;
    struct stat *filestats = (struct stat *) malloc(sizeof(struct stat));
    if (argc != 3)
    {
        printf("Wrong input\n");
        return 1;
    }

    file_in = argv[1];
    file_out = argv[2];
    //read input file
    iplist = fopen(file_in, "rb");

    if (!iplist)
    {
        printf("File does not exists\n");
        return 2;
    }
    printf("File %s is open\n", file_in);
    stat(file_in, filestats);
    size_in = filestats->st_size;
    plist_xml = (char *) malloc(sizeof(char) * (size_in + 1));
    fread(plist_xml, sizeof(char), size_in, iplist);
    fclose(iplist);


    //convert one format to another
    plist_from_xml(plist_xml, size_in, &root_node1);
    if (!root_node1)
    {
        printf("PList XML parsing failed\n");
        return 3;
    }
    else
        printf("PList XML parsing succeeded\n");

    plist_to_bin(root_node1, &plist_bin, &size_out);
    if (!plist_bin)
    {
        printf("PList BIN writing failed\n");
        return 4;
    }
    else
        printf("PList BIN writing succeeded\n");

    plist_from_bin(plist_bin, size_out, &root_node2);
    if (!root_node2)
    {
        printf("PList BIN parsing failed\n");
        return 5;
    }
    else
        printf("PList BIN parsing succeeded\n");

    plist_to_xml(root_node2, &plist_xml2, &size_out2);
    if (!plist_xml2)
    {
        printf("PList XML writing failed\n");
        return 8;
    }
    else
        printf("PList XML writing succeeded\n");

    if (plist_xml2)
    {
        FILE *oplist = NULL;
        oplist = fopen(file_out, "wb");
        fwrite(plist_xml2, size_out2, sizeof(char), oplist);
        fclose(oplist);
    }

    plist_free(root_node1);
    plist_free(root_node2);
    free(plist_bin);
    free(plist_xml);
    free(plist_xml2);
    free(filestats);

    if ((uint32_t)size_in != size_out2)
    {
        printf("Size of input and output is different\n");
        printf("Input size : %i\n", size_in);
        printf("Output size : %i\n", size_out2);
    }

    //success
    return 0;
}
コード例 #29
0
ファイル: tss.c プロジェクト: zweed4u/idevicerestore
plist_t tss_request_send(plist_t tss_request, const char* server_url_string) {

	if (idevicerestore_debug) {
		debug_plist(tss_request);
	}

	char* request = NULL;
	int status_code = -1;
	int retry = 0;
	int max_retries = 15;
	unsigned int size = 0;
	char curl_error_message[CURL_ERROR_SIZE];

	const char* urls[6] = {
		"https://gs.apple.com/TSS/controller?action=2",
		"https://17.171.36.30/TSS/controller?action=2",
		"https://17.151.36.30/TSS/controller?action=2",
		"http://gs.apple.com/TSS/controller?action=2",
		"http://17.171.36.30/TSS/controller?action=2",
		"http://17.151.36.30/TSS/controller?action=2"
	};

	plist_to_xml(tss_request, &request, &size);

	tss_response* response = NULL;
	memset(curl_error_message, '\0', CURL_ERROR_SIZE);

	while (retry++ < max_retries) {
		response = NULL;
		CURL* handle = curl_easy_init();
		if (handle == NULL) {
			break;
		}
		struct curl_slist* header = NULL;
		header = curl_slist_append(header, "Cache-Control: no-cache");
		header = curl_slist_append(header, "Content-type: text/xml; charset=\"utf-8\"");
		header = curl_slist_append(header, "Expect:");

		response = malloc(sizeof(tss_response));
		if (response == NULL) {
			fprintf(stderr, "Unable to allocate sufficent memory\n");
			return NULL;
		}

		response->length = 0;
		response->content = malloc(1);
		response->content[0] = '\0';

		/* disable SSL verification to allow download from untrusted https locations */
		curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);

		curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_error_message);
		curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, (curl_write_callback)&tss_write_callback);
		curl_easy_setopt(handle, CURLOPT_WRITEDATA, response);
		curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header);
		curl_easy_setopt(handle, CURLOPT_POSTFIELDS, request);
		curl_easy_setopt(handle, CURLOPT_USERAGENT, "InetURL/1.0");
		curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, strlen(request));
		if (server_url_string) {
			curl_easy_setopt(handle, CURLOPT_URL, server_url_string);
		} else {
			int url_index = (retry - 1) % 6;
			curl_easy_setopt(handle, CURLOPT_URL, urls[url_index]);
			info("Request URL set to %s\n", urls[url_index]);
		}

		info("Sending TSS request attempt %d... ", retry);

		curl_easy_perform(handle);
		curl_slist_free_all(header);
		curl_easy_cleanup(handle);
	
		if (strstr(response->content, "MESSAGE=SUCCESS")) {
			status_code = 0;
			info("response successfully received\n");
			break;
		}

		if (response->length > 0) {
			error("TSS server returned: %s\n", response->content);
		}

		char* status = strstr(response->content, "STATUS=");
		if (status) {
			sscanf(status+7, "%d&%*s", &status_code);
		}
		if (status_code == -1) {
			error("%s\n", curl_error_message);
			// no status code in response. retry
			free(response->content);
			free(response);
			sleep(2);
			continue;
		} else if (status_code == 8) {
			// server error (invalid bb request?)
			break;
		} else if (status_code == 49) {
			// server error (invalid bb data, e.g. BbSNUM?)
			break;
		} else if (status_code == 69 || status_code == 94) {
			// This device isn't eligible for the requested build.
			break;
		} else if (status_code == 100) {
			// server error, most likely the request was malformed
			break;
		} else if (status_code == 126) {
			// An internal error occured, most likely the request was malformed
			break;
		} else {
			error("ERROR: tss_send_request: Unhandled status code %d\n", status_code);
		}
	}

	if (status_code != 0) {
		if (strstr(response->content, "MESSAGE=") != NULL) {
			char* message = strstr(response->content, "MESSAGE=") + strlen("MESSAGE=");
			error("ERROR: TSS request failed (status=%d, message=%s)\n", status_code, message);
		} else {
			error("ERROR: TSS request failed: %s (status=%d)\n", curl_error_message, status_code);
		}
		free(request);
		free(response->content);
		free(response);
		return NULL;
	}

	char* tss_data = strstr(response->content, "<?xml");
	if (tss_data == NULL) {
		error("ERROR: Incorrectly formatted TSS response\n");
		free(request);
		free(response->content);
		free(response);
		return NULL;
	}

	uint32_t tss_size = 0;
	plist_t tss_response = NULL;
	tss_size = response->length - (tss_data - response->content);
	plist_from_xml(tss_data, tss_size, &tss_response);
	free(response->content);
	free(response);

	if (idevicerestore_debug) {
		debug_plist(tss_response);
	}

	free(request);

	return tss_response;
}
コード例 #30
0
int activate_fetch_record(lockdownd_client_t client, plist_t* record) {
	int size = 0;
	char* request = NULL;
	struct curl_httppost* post = NULL;
	struct curl_httppost* last = NULL;
	activate_response* response = NULL;

	char* imei = NULL;
	char* imsi = NULL;
	char* iccid = NULL;
	char* serial_number = NULL;
	char* activation_info = NULL;

	plist_t imei_node = NULL;
	plist_t imsi_node = NULL;
	plist_t iccid_node = NULL;
	plist_t serial_number_node = NULL;
	plist_t activation_info_node = NULL;

	char* device_class = NULL;
	plist_t device_class_node = NULL;
	lockdownd_get_value(client, NULL, "DeviceClass", &device_class_node);
	if (!device_class_node || plist_get_node_type(device_class_node) != PLIST_STRING) {
		fprintf(stderr, "Unable to get DeviceClass from lockdownd\n");
		return -1;
	}
	plist_get_string_val(device_class_node, &device_class);
	plist_free(device_class_node);

	if (!strcmp(device_class, "iPhone")) {
		lockdownd_get_value(client, NULL, "IntegratedCircuitCardIdentity", &iccid_node);
		if (!iccid_node || plist_get_node_type(iccid_node) != PLIST_STRING) {
			fprintf(stderr, "Unable to get ICCID from lockdownd\n");
			return -1;
		}
		plist_get_string_val(iccid_node, &iccid);
		plist_free(iccid_node);

		lockdownd_get_value(client, NULL, "InternationalMobileEquipmentIdentity", &imei_node);
		if (!imei_node || plist_get_node_type(imei_node) != PLIST_STRING) {
			fprintf(stderr, "Unable to get IMEI from lockdownd\n");
			return -1;
		}
		plist_get_string_val(imei_node, &imei);
		plist_free(imei_node);

		lockdownd_get_value(client, NULL, "InternationalMobileSubscriberIdentity", &imsi_node);
		if (!imsi_node || plist_get_node_type(imsi_node) != PLIST_STRING) {
			fprintf(stderr, "Unable to get IMSI from lockdownd\n");
			return -1;
		}
		plist_get_string_val(imsi_node, &imsi);
		plist_free(imsi_node);
	}

	lockdownd_get_value(client, NULL, "SerialNumber", &serial_number_node);
	if (!serial_number_node || plist_get_node_type(serial_number_node) != PLIST_STRING) {
		fprintf(stderr, "Unable to get SerialNumber from lockdownd\n");
		return -1;
	}
	plist_get_string_val(serial_number_node, &serial_number);
	plist_free(serial_number_node);

	lockdownd_get_value(client, NULL, "ActivationInfo", &activation_info_node);
	int type = plist_get_node_type(activation_info_node);
	if (!activation_info_node || plist_get_node_type(activation_info_node) != PLIST_DICT) {
		fprintf(stderr, "Unable to get ActivationInfo from lockdownd\n");
		return -1;
	}
	//plist_get_string_val(activation_info_node, &activation_info);

	uint32_t activation_info_size = 0;
	char* activation_info_data = NULL;
	plist_to_xml(activation_info_node, &activation_info_data, &activation_info_size);
	plist_free(activation_info_node);
	printf("%s\n\n", activation_info_data);

	char* activation_info_start = strstr(activation_info_data, "<dict>");
	if (activation_info_start == NULL) {
		fprintf(stderr, "Unable to locate beginning of ActivationInfo\n");
		return -1;
	}

	char* activation_info_stop = strstr(activation_info_data, "</dict>");
	if (activation_info_stop == NULL) {
		fprintf(stderr, "Unable to locate end of ActivationInfo\n");
		return -1;
	}

	activation_info_stop += strlen("</dict>");
	activation_info_size = activation_info_stop - activation_info_start;
	activation_info = malloc(activation_info_size + 1);
	memset(activation_info, '\0', activation_info_size + 1);
	memcpy(activation_info, activation_info_start, activation_info_size);
	free(activation_info_data);

	curl_global_init(CURL_GLOBAL_ALL);
	CURL* handle = curl_easy_init();
	if (handle == NULL) {
		fprintf(stderr, "Unable to initialize libcurl\n");
		curl_global_cleanup();
		return -1;
	}

	curl_formadd(&post, &last, CURLFORM_COPYNAME, "machineName", CURLFORM_COPYCONTENTS, "linux", CURLFORM_END);
	curl_formadd(&post, &last, CURLFORM_COPYNAME, "InStoreActivation", CURLFORM_COPYCONTENTS, "false", CURLFORM_END);
	if (imei != NULL) {
		curl_formadd(&post, &last, CURLFORM_COPYNAME, "IMEI", CURLFORM_COPYCONTENTS, imei, CURLFORM_END);
		free(imei);
	}

	if (imsi != NULL) {
		curl_formadd(&post, &last, CURLFORM_COPYNAME, "IMSI", CURLFORM_COPYCONTENTS, imsi, CURLFORM_END);
		free(imsi);
	}

	if (iccid != NULL) {
		curl_formadd(&post, &last, CURLFORM_COPYNAME, "ICCID", CURLFORM_COPYCONTENTS, iccid, CURLFORM_END);
		free(iccid);
	}

	if (serial_number != NULL) {
		curl_formadd(&post, &last, CURLFORM_COPYNAME, "AppleSerialNumber", CURLFORM_COPYCONTENTS, serial_number, CURLFORM_END);
		free(serial_number);
	}

	if (activation_info != NULL) {
		curl_formadd(&post, &last, CURLFORM_COPYNAME, "activation-info", CURLFORM_COPYCONTENTS, activation_info, CURLFORM_END);
		free(activation_info);
	}

	struct curl_slist* header = NULL;
	header = curl_slist_append(header, "X-Apple-Tz: -14400");
	header = curl_slist_append(header, "X-Apple-Store-Front: 143441-1");

	response = malloc(sizeof(activate_response));
	if (response == NULL) {
		fprintf(stderr, "Unable to allocate sufficent memory\n");
		return -1;
	}

	response->length = 0;
	response->content = malloc(1);

	curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
	curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header);
	curl_easy_setopt(handle, CURLOPT_WRITEDATA, response);
	curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, &activate_write_callback);
	curl_easy_setopt(handle, CURLOPT_USERAGENT, "iTunes/9.1 (Macintosh; U; Intel Mac OS X 10.5.6)");
	curl_easy_setopt(handle, CURLOPT_URL, "https://albert.apple.com/WebObjects/ALUnbrick.woa/wa/deviceActivation");

	curl_easy_perform(handle);
	curl_slist_free_all(header);
	curl_easy_cleanup(handle);
	curl_global_cleanup();

	uint32_t ticket_size = response->length;
	char* ticket_data = response->content;

	char* ticket_start = strstr(ticket_data, "<plist");
	if (ticket_start == NULL) {
		fprintf(stderr, "Unable to locate beginning of ActivationInfo\n");
		return -1;
	}

	char* ticket_stop = strstr(ticket_data, "</plist>");
	if (ticket_stop == NULL) {
		fprintf(stderr, "Unable to locate end of ActivationInfo\n");
		return -1;
	}

	ticket_stop += strlen("</plist>");
	ticket_size = ticket_stop - ticket_start;
	char* ticket = malloc(ticket_size + 1);
	memset(ticket, '\0', ticket_size + 1);
	memcpy(ticket, ticket_start, ticket_size);
	//free(ticket_data);

	printf("%s\n\n", ticket);

	plist_t ticket_dict = NULL;
	plist_from_xml(ticket, ticket_size, &ticket_dict);
	if (ticket_dict == NULL) {
		printf("Unable to convert activation ticket into plist\n");
		return -1;
	}

	plist_t iphone_activation_node = plist_dict_get_item(ticket_dict, "iphone-activation");
	if (!iphone_activation_node) {
		iphone_activation_node = plist_dict_get_item(ticket_dict, "device-activation");
		if (!iphone_activation_node) {
			printf("Unable to find device activation node\n");
			return -1;
		}
	}

	plist_t activation_record = plist_dict_get_item(iphone_activation_node, "activation-record");
	if (!activation_record) {
		printf("Unable to find activation record node");
		return -1;
	}

	*record = plist_copy(activation_record);

	//free(response->content);
	//free(response);
	//free(request);
	return 0;
}