[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/lib/liblpa/Makefile b/ap/lib/liblpa/Makefile
new file mode 100755
index 0000000..539f889
--- /dev/null
+++ b/ap/lib/liblpa/Makefile
@@ -0,0 +1,53 @@
+#*******************************************************************************
+# include ZTE library makefile
+#*******************************************************************************
+include $(COMMON_MK)
+
+##############USER COMIZE BEGIN################
+
+LIB_STATIC = liblpa.a
+LIB_SHARED = liblpa.so
+
+INTERFACELIB = libes10.a
+
+OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
+
+CFLAGS  += -I$(zte_lib_path)/libssl/install/include
+CFLAGS += -I$(LINUX_DIR)/include
+CFLAGS += -g
+
+#CFLAGS	+= -DWEBS_SSL_SUPPORT -DOPENSSL
+#LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lssl -lcrypto
+#LDLIBS += -ldl
+##############USER COMIZE END##################
+
+CFLAGS += -I$(zte_app_path)/include
+CFLAGS += -fPIC
+LDFLAGS += -shared
+
+
+ifneq ($(MK_SDK_VERSION),yes)
+all: $(INTERFACELIB) $(LIB_STATIC)
+else
+all: $(LIB_STATIC)
+endif
+
+$(INTERFACELIB):
+	${MAKE} -C ./es10 all
+
+$(LIB_STATIC): $(OBJS)
+	$(AR) rcs $(LIB_STATIC) $(OBJS)
+
+$(LIB_SHARED): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(INTERFACELIB)
+
+romfs:
+	@echo lpa no so
+
+clean:
+ifneq ($(MK_SDK_VERSION),yes)
+	${MAKE} -C ./es10 clean
+	-$(RM) *.o $(LIB_SHARED) $(LIB_STATIC) $(OBJS)
+else
+	-$(RM) *.o $(LIB_SHARED) $(LIB_STATIC) $(OBJS)
+endif
diff --git a/ap/lib/liblpa/cjson.c b/ap/lib/liblpa/cjson.c
new file mode 100755
index 0000000..21ac10b
--- /dev/null
+++ b/ap/lib/liblpa/cjson.c
@@ -0,0 +1,980 @@
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cjson.h"
+
+
+static const char *parse_value(cJSON *item, const char *value);
+static char *print_value(cJSON *item, int depth, int fmt);
+static const char *parse_array(cJSON *item, const char *value);
+static char *print_array(cJSON *item, int depth, int fmt);
+static const char *parse_object(cJSON *item, const char *value);
+static char *print_object(cJSON *item, int depth, int fmt);
+
+static const char *ep;
+
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+
+const char *cJSON_GetErrorPtr(void)
+{
+	return ep;
+}
+
+static int cJSON_strcasecmp(const char *s1, const char *s2)
+{
+	if (!s1) return (s1 == s2) ? 0 : 1;
+	if (!s2) return 1;
+	for (; tolower(*s1) == tolower(*s2); ++s1, ++s2)	if (*s1 == 0)	return 0;
+	return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static const char *skip(const char *in)
+{
+	while (in && *in && (unsigned char)*in <= 32) in++;
+	return in;
+}
+
+static char* cJSON_strdup(const char* str)
+{
+	size_t len;
+	char* str_cpy;
+
+	len = strlen(str) + 1;
+	if (!(str_cpy = (char*)cJSON_malloc(len))) return 0;
+	memcpy(str_cpy, str, len);
+	return str_cpy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+	if (!hooks) { /*hooks reset*/
+		cJSON_malloc = malloc;
+		cJSON_free = free;
+		return;
+	}
+
+	cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
+	cJSON_free	 = (hooks->free_fn) ? hooks->free_fn : free;
+}
+
+static cJSON *cJSON_New_Item(void)
+{
+	cJSON* inode = (cJSON*)cJSON_malloc(sizeof(cJSON));
+	if (inode) memset(inode, 0, sizeof(cJSON));
+	return inode;
+}
+
+void cJSON_Delete(cJSON *c)
+{
+	cJSON *next_node;
+	while (c) {
+		next_node = c->next;
+		if (!(c->type & cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+		if (!(c->type & cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+		if (c->string) cJSON_free(c->string);
+		cJSON_free(c);
+		c = next_node;
+	}
+}
+
+static const char *parse_number(cJSON *item, const char *num)
+{
+	int subscale = 0, signsubscale = 1;
+
+	double inum = 0, sign = 1, scale = 0;
+	
+	if (*num == '-') sign = -1, num++;
+	if (*num == '0') num++;
+	if (*num >= '1' && *num <= '9')	do	inum = (inum * 10.0) + (*num++ -'0');
+		while (*num >= '0' && *num <= '9');
+	if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
+		num++;
+		do	inum = (inum * 10.0) + (*num++ -'0'), scale--;
+		while (*num >= '0' && *num <= '9');
+	}
+	if (*num == 'e' || *num == 'E') {
+		num++;
+		if (*num == '+') num++;
+		else if (*num == '-') signsubscale = -1, num++;
+		while (*num >= '0' && *num <= '9') subscale = (subscale * 10) + (*num++ - '0');
+	}
+
+	inum = sign * inum * pow(10.0, (scale + subscale * signsubscale));
+
+	item->valuedouble = inum;
+	item->valueint = (int)inum;
+	item->type = cJSON_Number;
+	return num;
+}
+
+static char *print_number(cJSON *item)
+{
+	double d = item->valuedouble;
+
+	char *str;
+	
+	if (fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
+		str = (char*)cJSON_malloc(21);	/* 2^64+1 can be represented in 21 chars. */
+		if (str) sprintf(str, "%d", item->valueint);
+	} else {
+		str = (char*)cJSON_malloc(64);
+		if (str) {
+			if (fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60)sprintf(str, "%.0f", d);
+			else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)			sprintf(str, "%e", d);
+			else												sprintf(str, "%f", d);
+		}
+	}
+	return str;
+}
+
+static unsigned parse_hex4(const char *str)
+{
+	unsigned hex = 0;
+	if (*str >= '0' && *str <= '9') 
+		hex += (*str) - '0';
+	else if (*str >= 'A' && *str <= 'F') 
+		hex += 10 + (*str) - 'A';
+	else if (*str >= 'a' && *str <= 'f') 
+		hex += 10 + (*str) - 'a';
+	else 
+		return 0;
+	hex = hex << 4;
+	str++;
+	if (*str >= '0' && *str <= '9') 
+		hex += (*str) - '0';
+	else if (*str >= 'A' && *str <= 'F') 
+		hex += 10 + (*str) - 'A';
+	else if (*str >= 'a' && *str <= 'f') 
+		hex += 10 + (*str) - 'a';
+	else 
+		return 0;
+	hex = hex << 4;
+	str++;
+	if (*str >= '0' && *str <= '9') 
+		hex += (*str) - '0';
+	else if (*str >= 'A' && *str <= 'F') 
+		hex += 10 + (*str) - 'A';
+	else if (*str >= 'a' && *str <= 'f') 
+		hex += 10 + (*str) - 'a';
+	else 
+		return 0;
+	hex = hex << 4;
+	str++;
+	if (*str >= '0' && *str <= '9') 
+		hex += (*str) - '0';
+	else if (*str >= 'A' && *str <= 'F') 
+		hex += 10 + (*str) - 'A';
+	else if (*str >= 'a' && *str <= 'f') 
+		hex += 10 + (*str) - 'a';
+	else 
+		return 0;
+	return hex;
+}
+
+static const char *parse_string(cJSON *item, const char *str)
+{
+	const char *pstr = str + 1;
+	char *pstr2;
+	char *out;
+	int len = 0;
+	unsigned uc, uc2;
+	if (*str != '\"') {
+		ep = str;    /* not a string! */
+		return 0;
+	}
+
+	while (*pstr != '\"' && *pstr && ++len) if (*pstr++ == '\\') pstr++;	/* Skip escaped quotes. */
+
+	out = (char*)cJSON_malloc(len + 1);	/* This is how long we need for the string, roughly. */
+	if (!out) return 0;
+
+	pstr = str + 1;
+	pstr2 = out;
+	while (*pstr != '\"' && *pstr) {
+		if (*pstr != '\\') *pstr2++ = *pstr++;
+		else {
+			pstr++;
+			switch (*pstr) {
+			case 'b':
+				*pstr2++ = '\b';
+				break;
+			case 'f':
+				*pstr2++ = '\f';
+				break;
+			case 'n':
+				*pstr2++ = '\n';
+				break;
+			case 'r':
+				*pstr2++ = '\r';
+				break;
+			case 't':
+				*pstr2++ = '\t';
+				break;
+			case 'u':
+				uc = parse_hex4(pstr + 1);
+				pstr += 4;
+
+				if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0)
+					break;
+
+				if (uc >= 0xD800 && uc <= 0xDBFF) {
+					if (pstr[1] != '\\' || pstr[2] != 'u')
+						break;
+					uc2 = parse_hex4(pstr + 3);
+					pstr += 6;
+					if (uc2 < 0xDC00 || uc2 > 0xDFFF)
+						break;
+					uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
+				}
+
+				len = 4;
+				if (uc < 0x80) len = 1;
+				else if (uc < 0x800) len = 2;
+				else if (uc < 0x10000) len = 3;
+				pstr2 += len;
+
+				switch (len) {
+				case 4:
+					*--pstr2 = ((uc | 0x80) & 0xBF);
+					uc >>= 6;
+				case 3:
+					*--pstr2 = ((uc | 0x80) & 0xBF);
+					uc >>= 6;
+				case 2:
+					*--pstr2 = ((uc | 0x80) & 0xBF);
+					uc >>= 6;
+				case 1:
+					*--pstr2 = (uc | firstByteMark[len]);
+				}
+				pstr2 += len;
+				break;
+			default:
+				*pstr2++ = *pstr;
+				break;
+			}
+			pstr++;
+		}
+	}
+	*pstr2 = 0;
+	if (*pstr == '\"') pstr++;
+	item->valuestring = out;
+	item->type = cJSON_String;
+	return pstr;
+}
+
+static char *print_string_ptr(const char *str)
+{
+	const char *pstr;
+	char *pstr2, *out;
+	int len = 0;
+	unsigned char token;
+
+	if (!str) return cJSON_strdup("");
+	pstr = str;
+	while ((token = *pstr) && ++len) {
+		if (strchr("\"\\\b\f\n\r\t", token)) len++;
+		else if (token < 32) len += 5;
+		pstr++;
+	}
+
+	out = (char*)cJSON_malloc(len + 3);
+	if (!out) return 0;
+
+	pstr2 = out;
+	pstr = str;
+	*pstr2++ = '\"';
+	while (*pstr) {
+		if ((unsigned char)*pstr > 31 && *pstr != '\"' && *pstr != '\\') *pstr2++ = *pstr++;
+		else {
+			*pstr2++ = '\\';
+			switch (token = *pstr++) {
+			case '\\':
+				*pstr2++ = '\\';
+				break;
+			case '\"':
+				*pstr2++ = '\"';
+				break;
+			case '\b':
+				*pstr2++ = 'b';
+				break;
+			case '\f':
+				*pstr2++ = 'f';
+				break;
+			case '\n':
+				*pstr2++ = 'n';
+				break;
+			case '\r':
+				*pstr2++ = 'r';
+				break;
+			case '\t':
+				*pstr2++ = 't';
+				break;
+			default:
+				sprintf(pstr2, "u%04x", token);
+				pstr2 += 5;
+				break;
+			}
+		}
+	}
+	*pstr2++ = '\"';
+	*pstr2++ = 0;
+	return out;
+}
+
+static char *print_string(cJSON *item)
+{
+	return print_string_ptr(item->valuestring);
+}
+
+cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated)
+{
+	const char *str_end = 0;
+	cJSON *c = cJSON_New_Item();
+	ep = 0;
+	if (!c) 
+		return 0;
+
+	str_end = parse_value(c, skip(value));
+	if (!str_end)	{
+		cJSON_Delete(c);    
+		return 0;
+	}
+
+	if (require_null_terminated) {
+		str_end = skip(str_end);
+		if (*str_end) {
+			cJSON_Delete(c);
+			ep = str_end;
+			return 0;
+		}
+	}
+	if (return_parse_end) *return_parse_end = str_end;
+	return c;
+}
+
+cJSON *cJSON_Parse(const char *value)
+{
+	return cJSON_ParseWithOpts(value, 0, 0);
+}
+char *cJSON_Print(cJSON *item)
+{
+	return print_value(item, 0, 1);
+}
+char *cJSON_PrintUnformatted(cJSON *item)
+{
+	return print_value(item, 0, 0);
+}
+
+static const char *parse_value(cJSON *item, const char *value)
+{
+	if (!value)						
+		return 0;
+	if (!strncmp(value, "null", 4))	{
+		item->type = cJSON_NULL;
+		return value + 4;
+	}
+	if (!strncmp(value, "false", 5))	{
+		item->type = cJSON_False;
+		return value + 5;
+	}
+	if (!strncmp(value, "true", 4))	{
+		item->type = cJSON_True;
+		item->valueint = 1;
+		return value + 4;
+	}
+	if (*value == '\"')				{
+		return parse_string(item, value);
+	}
+	if (*value == '-' || (*value >= '0' && *value <= '9'))	{
+		return parse_number(item, value);
+	}
+	if (*value == '[')				{
+		return parse_array(item, value);
+	}
+	if (*value == '{')				{
+		return parse_object(item, value);
+	}
+
+	ep = value;
+	return 0;
+}
+
+static char *print_value(cJSON *item, int depth, int fmt)
+{
+	char *item_value = 0;
+	if (!item) 
+		return 0;
+	switch ((item->type) & 255) {
+	case cJSON_NULL:
+		item_value = cJSON_strdup("null");
+		break;
+	case cJSON_False:
+		item_value = cJSON_strdup("false");
+		break;
+	case cJSON_True:
+		item_value = cJSON_strdup("true");
+		break;
+	case cJSON_Number:
+		item_value = print_number(item);
+		break;
+	case cJSON_String:
+		item_value = print_string(item);
+		break;
+	case cJSON_Array:
+		item_value = print_array(item, depth, fmt);
+		break;
+	case cJSON_Object:
+		item_value = print_object(item, depth, fmt);
+		break;
+	}
+	return item_value;
+}
+
+
+static const char *parse_array(cJSON *item, const char *value)
+{
+	cJSON *child;
+	if (*value != '[')	{
+		ep = value;
+		return 0;
+	}
+
+	item->type = cJSON_Array;
+	value = skip(value + 1);
+	if (*value == ']') return value + 1;
+
+	item->child = child = cJSON_New_Item();
+	if (!item->child) return 0;
+	value = skip(parse_value(child, skip(value)));
+	if (!value) return 0;
+
+	while (*value == ',') {
+		cJSON *new_item;
+		if (!(new_item = cJSON_New_Item())) 
+			return 0;
+		child->next = new_item;
+		new_item->prev = child;
+		child = new_item;
+		value = skip(parse_value(child, skip(value + 1)));
+		if (!value) 
+			return 0;
+	}
+
+	if (*value == ']') 
+		return value + 1;
+	ep = value;
+	return 0;
+}
+
+static char *print_array(cJSON *item, int depth, int fmt)
+{
+	char *oitem = 0, *pstr, *ret;
+	char **entries;
+	int len = 5;
+	int numentries = 0, i = 0, fail = 0;
+	cJSON *child = item->child;
+
+	while (child) numentries++, child = child->next;
+	
+	if (!numentries) {
+		oitem = (char*)cJSON_malloc(3);
+		if (oitem) 
+			strcpy(oitem, "[]");
+		return oitem;
+	}
+	
+	entries = (char**)cJSON_malloc(numentries * sizeof(char*));
+	if (!entries) return 0;
+	memset(entries, 0, numentries * sizeof(char*));
+	
+	child = item->child;
+	while (child && !fail) {
+		ret = print_value(child, depth + 1, fmt);
+		entries[i++] = ret;
+		if (ret) len += strlen(ret) + 2 + (fmt ? 1 : 0);
+		else fail = 1;
+		child = child->next;
+	}
+
+	
+	if (!fail) 
+		oitem = (char*)cJSON_malloc(len);
+	
+	if (!oitem) 
+		fail = 1;
+
+	
+	if (fail) {
+		for (i = 0; i < numentries; i++) if (entries[i]) cJSON_free(entries[i]);
+		cJSON_free(entries);
+		return 0;
+	}
+
+	
+	*oitem = '[';
+	pstr = oitem + 1;
+	*pstr = 0;
+	for (i = 0; i < numentries; i++) {
+		strcpy(pstr, entries[i]);
+		pstr += strlen(entries[i]);
+		if (i != numentries - 1) {
+			*pstr++ = ',';
+			if (fmt)*pstr++ = ' ';
+			*pstr = 0;
+		}
+		cJSON_free(entries[i]);
+	}
+	cJSON_free(entries);
+	*pstr++ = ']';
+	*pstr++ = 0;
+	return oitem;
+}
+
+static const char *parse_object(cJSON *item, const char *value)
+{
+	cJSON *child;
+	if (*value != '{')	{
+		ep = value;
+		return 0;
+	}
+
+	item->type = cJSON_Object;
+	value = skip(value + 1);
+	if (*value == '}') return value + 1;
+
+	item->child = child = cJSON_New_Item();
+	if (!item->child) return 0;
+	value = skip(parse_string(child, skip(value)));
+	if (!value) return 0;
+	child->string = child->valuestring;
+	child->valuestring = 0;
+	if (*value != ':') {
+		ep = value;
+		return 0;
+	}
+	value = skip(parse_value(child, skip(value + 1)));
+	if (!value) return 0;
+
+	while (*value == ',') {
+		cJSON *new_item;
+		if (!(new_item = cJSON_New_Item()))	return 0;
+		child->next = new_item;
+		new_item->prev = child;
+		child = new_item;
+		value = skip(parse_string(child, skip(value + 1)));
+		if (!value) return 0;
+		child->string = child->valuestring;
+		child->valuestring = 0;
+		if (*value != ':') {
+			ep = value;
+			return 0;
+		}
+		value = skip(parse_value(child, skip(value + 1)));
+		if (!value) return 0;
+	}
+
+	if (*value == '}') return value + 1;
+	ep = value;
+	return 0;
+}
+
+static char *print_object(cJSON *item, int depth, int fmt)
+{
+	char *oitem = 0, *pstr, *ret, *str;
+	char **entries = 0, **names = 0;
+	int len = 7, i = 0, j;
+	int numentries = 0, fail = 0;
+	cJSON *child = item->child;
+	
+	while (child) numentries++, child = child->next;
+	
+	if (!numentries) {
+		oitem = (char*)cJSON_malloc(fmt ? depth + 4 : 3);
+		if (!oitem)	return 0;
+		pstr = oitem;
+		*pstr++ = '{';
+		if (fmt) {
+			*pstr++ = '\n';
+			for (i = 0; i < depth - 1; i++) *pstr++ = '\t';
+		}
+		*pstr++ = '}';
+		*pstr++ = 0;
+		return oitem;
+	}
+	
+	entries = (char**)cJSON_malloc(numentries * sizeof(char*));
+	if (!entries) 
+		return 0;
+	names = (char**)cJSON_malloc(numentries * sizeof(char*));
+	if (!names) {
+		cJSON_free(entries);
+		return 0;
+	}
+	memset(entries, 0, sizeof(char*)*numentries);
+	memset(names, 0, sizeof(char*)*numentries);
+
+	
+	child = item->child;
+	depth++;
+	if (fmt) len += depth;
+	while (child) {
+		names[i] = str = print_string_ptr(child->string);
+		entries[i++] = ret = print_value(child, depth, fmt);
+		if (str && ret) 
+			len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
+		else 
+			fail = 1;
+		child = child->next;
+	}
+
+	
+	if (!fail) oitem = (char*)cJSON_malloc(len);
+	if (!oitem) fail = 1;
+
+	
+	if (fail) {
+		for (i = 0; i < numentries; i++) {
+			if (names[i]) cJSON_free(names[i]);
+			if (entries[i]) cJSON_free(entries[i]);
+		}
+		cJSON_free(names);
+		cJSON_free(entries);
+		return 0;
+	}
+
+	
+	*oitem = '{';
+	pstr = oitem + 1;
+	if (fmt)*pstr++ = '\n';
+	*pstr = 0;
+	for (i = 0; i < numentries; i++) {
+		if (fmt) for (j = 0; j < depth; j++) *pstr++ = '\t';
+		strcpy(pstr, names[i]);
+		pstr += strlen(names[i]);
+		*pstr++ = ':';
+		if (fmt) *pstr++ = '\t';
+		strcpy(pstr, entries[i]);
+		pstr += strlen(entries[i]);
+		if (i != numentries - 1) *pstr++ = ',';
+		if (fmt) *pstr++ = '\n';
+		*pstr = 0;
+		cJSON_free(names[i]);
+		cJSON_free(entries[i]);
+	}
+
+	cJSON_free(names);
+	cJSON_free(entries);
+	if (fmt) for (i = 0; i < depth - 1; i++) *pstr++ = '\t';
+	*pstr++ = '}';
+	*pstr++ = 0;
+	return oitem;
+}
+
+int cJSON_GetArraySize(cJSON *array)
+{
+	int i = 0;
+	cJSON *citem = array->child;
+	
+	while (citem)i++, citem = citem->next;
+	return i;
+}
+cJSON *cJSON_GetArrayItem(cJSON *array, int item)
+{
+	cJSON *citem = array->child;
+	while (citem && item > 0) item--, citem = citem->next;
+	return citem;
+}
+cJSON *cJSON_GetObjectItem(cJSON *object, const char *string)
+{
+	cJSON *citem = object->child;
+	while (citem && cJSON_strcasecmp(citem->string, string)) citem = citem->next;
+	return citem;
+}
+
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+	prev->next = item;
+	item->prev = prev;
+}
+
+static cJSON *create_reference(cJSON *item)
+{
+	cJSON *refer = cJSON_New_Item();
+	if (!refer) 
+		return 0;
+	memcpy(refer, item, sizeof(cJSON));
+	refer->string = 0;
+	refer->type |= cJSON_IsReference;
+	refer->next = refer->prev = 0;
+	return refer;
+}
+
+void cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+	cJSON *citem = array->child;
+	if (!item) 
+		return;
+	if (!citem) {
+		array->child = item;
+	} else {
+		while (citem && citem->next) citem = citem->next;
+		suffix_object(citem, item);
+	}
+}
+void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+	if (!item) 
+		return;
+	if (item->string) cJSON_free(item->string);
+	item->string = cJSON_strdup(string);
+	cJSON_AddItemToArray(object, item);
+}
+void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+	cJSON_AddItemToArray(array, create_reference(item));
+}
+void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+	cJSON_AddItemToObject(object, string, create_reference(item));
+}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+	cJSON *citem = array->child;
+	while (citem && which > 0) citem = citem->next, which--;
+	if (!citem) 
+		return 0;
+	if (citem->prev) citem->prev->next = citem->next;
+	if (citem->next) citem->next->prev = citem->prev;
+	if (citem == array->child) array->child = citem->next;
+	citem->prev = citem->next = 0;
+	return citem;
+}
+void cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+	cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+	int i = 0;
+	cJSON *citem = object->child;
+	while (citem && cJSON_strcasecmp(citem->string, string)) i++, citem = citem->next;
+	if (citem) 
+		return cJSON_DetachItemFromArray(object, i);
+	return 0;
+}
+void   cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+	cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+void   cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+	cJSON *citem = array->child;
+	while (citem && which > 0) citem = citem->next, which--;
+	if (!citem) 
+		return;
+	newitem->next = citem->next;
+	newitem->prev = citem->prev;
+	if (newitem->next) newitem->next->prev = newitem;
+	if (citem == array->child) array->child = newitem;
+	else newitem->prev->next = newitem;
+	citem->next = citem->prev = 0;
+	cJSON_Delete(citem);
+}
+void   cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+	int i = 0;
+	cJSON *citem = object->child;
+	while (citem && cJSON_strcasecmp(citem->string, string))i++, citem = citem->next;
+	if (citem) {
+		newitem->string = cJSON_strdup(string);
+		cJSON_ReplaceItemInArray(object, i, newitem);
+	}
+}
+
+cJSON *cJSON_CreateNull(void)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item)item->type = cJSON_NULL;
+	return item;
+}
+cJSON *cJSON_CreateTrue(void)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item)item->type = cJSON_True;
+	return item;
+}
+cJSON *cJSON_CreateFalse(void)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item)item->type = cJSON_False;
+	return item;
+}
+cJSON *cJSON_CreateBool(int b)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item)item->type = b ? cJSON_True : cJSON_False;
+	return item;
+}
+cJSON *cJSON_CreateNumber(double num)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item) {
+		item->type = cJSON_Number;
+		item->valuedouble = num;
+		item->valueint = (int)num;
+	}
+	return item;
+}
+cJSON *cJSON_CreateString(const char *string)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item) {
+		item->type = cJSON_String;
+		item->valuestring = cJSON_strdup(string);
+	}
+	return item;
+}
+cJSON *cJSON_CreateArray(void)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item)item->type = cJSON_Array;
+	return item;
+}
+cJSON *cJSON_CreateObject(void)
+{
+	cJSON *item = cJSON_New_Item();
+	if (item)item->type = cJSON_Object;
+	return item;
+}
+
+cJSON *cJSON_CreateIntArray(const int *numbers, int count)
+{
+	int i;
+	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+	for (i = 0; a && i < count; i++) {
+		n = cJSON_CreateNumber(numbers[i]);
+		if (!i)a->child = n;
+		else suffix_object(p, n);
+		p = n;
+	}
+	return a;
+}
+cJSON *cJSON_CreateFloatArray(const float *numbers, int count)
+{
+	int i;
+	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+	for (i = 0; a && i < count; i++) {
+		n = cJSON_CreateNumber(numbers[i]);
+		if (!i)a->child = n;
+		else suffix_object(p, n);
+		p = n;
+	}
+	return a;
+}
+cJSON *cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+	int i;
+	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+	for (i = 0; a && i < count; i++) {
+		n = cJSON_CreateNumber(numbers[i]);
+		if (!i)a->child = n;
+		else suffix_object(p, n);
+		p = n;
+	}
+	return a;
+}
+cJSON *cJSON_CreateStringArray(const char **strings, int count)
+{
+	int i;
+	cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+	for (i = 0; a && i < count; i++) {
+		n = cJSON_CreateString(strings[i]);
+		if (!i)a->child = n;
+		else suffix_object(p, n);
+		p = n;
+	}
+	return a;
+}
+
+cJSON *cJSON_Duplicate(cJSON *item, int recurse)
+{
+	cJSON *newitem, *cptr, *nptr = 0, *newchild;
+
+	if (!item) 
+		return 0;
+
+	newitem = cJSON_New_Item();
+	if (!newitem) 
+		return 0;
+
+	newitem->type = item->type & (~cJSON_IsReference), newitem->valueint = item->valueint, newitem->valuedouble = item->valuedouble;
+	if (item->valuestring)	{
+		newitem->valuestring = cJSON_strdup(item->valuestring);
+		if (!newitem->valuestring)	{
+			cJSON_Delete(newitem);
+			return 0;
+		}
+	}
+	if (item->string)		{
+		newitem->string = cJSON_strdup(item->string);
+		if (!newitem->string)		{
+			cJSON_Delete(newitem);
+			return 0;
+		}
+	}
+
+	if (!recurse) 
+		return newitem;
+
+	cptr = item->child;
+	while (cptr) {
+		newchild = cJSON_Duplicate(cptr, 1);
+		if (!newchild) {
+			cJSON_Delete(newitem);
+			return 0;
+		}
+		if (nptr)	{
+			nptr->next = newchild, newchild->prev = nptr;
+			nptr = newchild;
+		} else		{
+			newitem->child = newchild;
+			nptr = newchild;
+		}
+		cptr = cptr->next;
+	}
+	return newitem;
+}
+
+void cJSON_Minify(char *json)
+{
+	char *cpr_str = json;
+	while (*json) {
+		if (*json == ' ') json++;
+		else if (*json == '\t') json++;
+		else if (*json == '\r') json++;
+		else if (*json == '\n') json++;
+		else if (*json == '/' && json[1] == '/')  while (*json && *json != '\n') json++;
+		else if (*json == '/' && json[1] == '*') {
+			while (*json && !(*json == '*' && json[1] == '/')) json++;
+			json += 2;
+		} else if (*json == '\"') {
+			*cpr_str++ = *json++;
+			while (*json && *json != '\"') {
+				if (*json == '\\') *cpr_str++ = *json++;
+				*cpr_str++ = *json++;
+			}
+			*cpr_str++ = *json++;
+		} else *cpr_str++ = *json++;
+	}
+	*cpr_str = 0;
+}
diff --git a/ap/lib/liblpa/cjson.h b/ap/lib/liblpa/cjson.h
new file mode 100755
index 0000000..4a86aba
--- /dev/null
+++ b/ap/lib/liblpa/cjson.h
@@ -0,0 +1,99 @@
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+
+#define cJSON_IsReference 256
+
+typedef struct cJSON_Hooks {
+	void *(*malloc_fn)(size_t sz);
+	void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef struct cJSON {
+	struct cJSON *next, *prev;
+	struct cJSON *child;
+
+	int type;
+
+	char *valuestring;
+	int valueint;
+	double valuedouble;
+
+	char *string;
+} cJSON;
+
+
+extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+
+extern cJSON *cJSON_Parse(const char *value);
+extern char  *cJSON_Print(cJSON *item);
+extern char  *cJSON_PrintUnformatted(cJSON *item);
+
+extern int	  cJSON_GetArraySize(cJSON *array);
+extern cJSON *cJSON_GetArrayItem(cJSON *array, int item);
+extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
+
+extern const char *cJSON_GetErrorPtr(void);
+
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
+
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void	cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void	cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+extern void   cJSON_Delete(cJSON *c);
+
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
+extern void   cJSON_DeleteItemFromArray(cJSON *array, int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
+extern void   cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+
+extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
+
+extern cJSON *cJSON_Duplicate(cJSON *item, int recurse);
+extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+#define cJSON_SetIntValue(object,val)			((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+
+#define cJSON_AddNullToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name)		cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b)	cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n)	cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s)	cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ap/lib/liblpa/libes10.a b/ap/lib/liblpa/libes10.a
new file mode 100644
index 0000000..5422bc4
--- /dev/null
+++ b/ap/lib/liblpa/libes10.a
Binary files differ
diff --git a/ap/lib/liblpa/lpa_api.h b/ap/lib/liblpa/lpa_api.h
new file mode 100755
index 0000000..c5adf81
--- /dev/null
+++ b/ap/lib/liblpa/lpa_api.h
@@ -0,0 +1,40 @@
+#ifndef __LPA_API_H__

+#define __LPA_API_H__

+

+

+

+

+

+//

+int lpa_init(void);

+int lpa_uninit(void);

+int lpa_select_aid(void);

+int lpa_check_status(int retry);

+int lpa_exception_process(void);

+

+

+//trigger

+char *lpa_trigger_event(int *next_step);

+int lpa_trigger_updata(void);

+

+

+//api

+int downloadProfileByAc(char *activecode, char *confirmcode);

+int downloadProfileByEid(void);

+int enableProfile(char *iccid);

+int disableProfile(char * iccid);

+int deleteProfile(char * iccid);

+int memoryReset(void);

+int getProfileList(char **info);

+

+int lpa_download_profile(char *activecode, char *confirmcode);

+int lpa_enable_profile(char *iccid);

+int lpa_disable_profile(char *iccid);

+int lpa_delete_profile(char *iccid);

+int lpa_memory_reset(void);

+

+int lpa_open_logical_channel(void);

+int lpa_close_logical_channel(int flag);

+

+

+#endif

diff --git a/ap/lib/liblpa/lpa_es9plus.c b/ap/lib/liblpa/lpa_es9plus.c
new file mode 100755
index 0000000..f30845f
--- /dev/null
+++ b/ap/lib/liblpa/lpa_es9plus.c
@@ -0,0 +1,193 @@
+/***************************************************************/

+//

+//²Î¼û LPA½Ó¿ÚÎĵµV0.1 SGP.22, ·µ»ØJSON

+//   

+/***************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <ctype.h>

+#include <sys/time.h>

+#include <termios.h>

+

+#include "lpa_inner.h"

+

+

+#define LPA_AUTH_DATA_LEN 512

+

+/***************************************************************/

+//

+//euiccChallenge:¿¨·µ»ØµÄAPDU,²»º¬9000

+//euiccInfo1: ¿¨·µ»ØµÄAPDU,²»º¬9000

+//smdpAddress:¼¤»îÂëÖÐsdmpµØÖ·

+//·µ»Øjson

+//

+/***************************************************************/

+char *InitiateAuthentication(char *euiccChallenge, char *euiccInfo1, char *smdpAddress)

+{

+	char *js_data = NULL;

+	unsigned char clg_byte[APDU_BYTE_LEN] = {0};

+	unsigned char info1_byte[APDU_BYTE_LEN] = {0};

+	int clg_len = 0;

+	int info1_len = 0;

+	char *clg_b64 = NULL;

+	char *info1_b64 = NULL;

+

+	clg_len = string2bytes(euiccChallenge, clg_byte, strlen(euiccChallenge));

+	clg_b64 = lpa_base64_encode(clg_byte, clg_len);

+	if (clg_b64 == NULL)

+		return NULL;

+

+	info1_len = string2bytes(euiccInfo1, info1_byte, strlen(euiccInfo1));

+	info1_b64 = lpa_base64_encode(info1_byte, info1_len);

+	if (info1_b64 == NULL) {

+		free(clg_b64);

+		return NULL;

+	}

+	

+	js_data = malloc(LPA_AUTH_DATA_LEN);

+	if (js_data != NULL) {

+		memset(js_data, 0, LPA_AUTH_DATA_LEN);

+		snprintf(js_data, LPA_AUTH_DATA_LEN, "{\"euiccChallenge\":\"%s\",\"euiccInfo1\":\"%s\",\"smdpAddress\":\"%s\"}", 

+    		clg_b64, info1_b64, smdpAddress);

+		//printf("js_data:-%s-\n", js_data);

+	}

+

+	free(clg_b64);

+	free(info1_b64);

+	return js_data;

+}

+

+/***************************************************************/

+//

+//transactionId: smdp InitiateAuthentication½Ó¿Ú·µ»Ø

+//authSerRespHex:¿¨·µ»ØµÄAPDU,²»º¬9000

+//

+/***************************************************************/

+char *AuthenticateClient(

+char *transactionId,

+char *authSerRespHex)

+{

+	char *ac_js = NULL;

+	unsigned char *as_byte = NULL;

+	int as_byte_len = 0;

+	int ashex_len = strlen(authSerRespHex);

+	char *as_b64 = NULL;

+	int as_b64_len = 0;

+

+	as_byte = malloc(ashex_len/2 + 1);

+	if (as_byte == NULL) {

+		return NULL;

+	}

+	memset(as_byte, 0, ashex_len/2 + 1);

+

+	as_byte_len = string2bytes(authSerRespHex, as_byte, ashex_len);

+	as_b64 = lpa_base64_encode(as_byte, as_byte_len);

+	if (as_b64 == NULL) {

+		free(as_byte);

+		return NULL;	

+	}

+	as_b64_len = strlen(as_b64);

+	

+	ac_js = malloc(as_b64_len + 100);

+	if (ac_js != NULL) {

+		memset(ac_js, 0, as_b64_len + 100);

+		snprintf(ac_js, as_b64_len + 100, "{\"transactionId\":\"%s\",\"authenticateServerResponse\":\"%s\"}", 

+			transactionId, as_b64);

+		//printf("js_data:-%s-\n", ac_js);

+	}

+

+	free(as_byte);

+	free(as_b64);

+	return ac_js;

+}

+

+

+/***************************************************************/

+//

+//transactionId: smdp AuthenticateClient½Ó¿Ú·µ»Ø

+//predlRespHex: prepareDownloadResponseHex ¿¨·µ»ØµÄAPDU,²»º¬9000

+//

+/***************************************************************/

+char *GetBoundProfilePackage (

+char *transactionId,

+char *predlRespHex)

+{

+	char *bpp_js = NULL;

+	unsigned char *pdl_byte = NULL;

+	int pdl_byte_len = 0;

+	int pdlhex_len = strlen(predlRespHex);

+	char *pdl_b64 = NULL;

+	int pdl_b64_len = 0;

+

+	pdl_byte = malloc(pdlhex_len/2 + 1);

+	if (pdl_byte == NULL) {

+		return NULL;

+	}

+	memset(pdl_byte, 0, pdlhex_len/2 + 1);

+

+	pdl_byte_len = string2bytes(predlRespHex, pdl_byte, pdlhex_len);

+	pdl_b64 = lpa_base64_encode(pdl_byte, pdl_byte_len);

+	if (pdl_b64 == NULL) {

+		free(pdl_byte);

+		return NULL;	

+	}

+	pdl_b64_len = strlen(pdl_b64);

+	

+	bpp_js = malloc(pdl_b64_len + 100);

+	if (bpp_js != NULL) {

+		memset(bpp_js, 0, pdl_b64_len + 100);

+		snprintf(bpp_js, pdl_b64_len + 100, "{\"transactionId\":\"%s\",\"prepareDownloadResponse\":\"%s\"}", 

+			transactionId, pdl_b64);

+		//printf("js_data:-%s-\n", bpp_js);

+	}

+

+	free(pdl_byte);

+	free(pdl_b64);

+	return bpp_js;

+}

+

+

+/***************************************************************/

+//

+//pnfHex: pendingNotification ¿¨·µ»ØµÄAPDU,²»º¬9000

+//

+/***************************************************************/

+char *HandleNotification(char *pnfHex)

+{

+	char *bpp_js = NULL;

+	unsigned char *pdl_byte = NULL;

+	int pdl_byte_len = 0;

+	int pdlhex_len = strlen(pnfHex);

+	char *pdl_b64 = NULL;

+	int pdl_b64_len = 0;

+

+	pdl_byte = malloc(pdlhex_len/2 + 1);

+	if (pdl_byte == NULL) {

+		return NULL;

+	}

+	memset(pdl_byte, 0, pdlhex_len/2 + 1);

+

+	pdl_byte_len = string2bytes(pnfHex, pdl_byte, pdlhex_len);

+	pdl_b64 = lpa_base64_encode(pdl_byte, pdl_byte_len);

+	if (pdl_b64 == NULL) {

+		free(pdl_byte);

+		return NULL;	

+	}

+	pdl_b64_len = strlen(pdl_b64);

+	

+	bpp_js = malloc(pdl_b64_len + 100);

+	if (bpp_js != NULL) {

+		memset(bpp_js, 0, pdl_b64_len + 100);

+		snprintf(bpp_js, pdl_b64_len + 100, 

+			"{\"header\":{\"functionExecutionStatus\":{\"status\":\"Executed-Success\"}},\"pendingNotification\":\"%s\"}", pdl_b64);

+		//printf("js_data:-%s-\n", bpp_js);

+	}

+

+	free(pdl_byte);

+	free(pdl_b64);

+	return bpp_js;

+}

+

+

diff --git a/ap/lib/liblpa/lpa_esim_api.c b/ap/lib/liblpa/lpa_esim_api.c
new file mode 100755
index 0000000..509d047
--- /dev/null
+++ b/ap/lib/liblpa/lpa_esim_api.c
@@ -0,0 +1,866 @@
+/***************************************************************/

+//

+//²Î¼û ÖйúÁªÍ¨esimÄ£×éÀ©Õ¹Ö¸Áî¼¼Êõ¹æ·¶

+//   

+/***************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <ctype.h>

+#include <sys/time.h>

+#include <termios.h>

+#include <errno.h>

+

+#include "lpa_inner.h"

+

+

+#define SMDP_PORT 443

+#define SMDP_DL_INTERVAL 95//ÏÂÔØ¼ä¸ô>90s

+

+

+//´¥·¢·þÎñÆ÷httpÇëÇó

+static char smdp_https_req[] =

+    "POST /gsma/rsp2/es9plus/%s HTTP/1.1\r\n"

+    "Host: %s\r\n"

+    "User-Agent: gsma-rsp-lpad\r\n"

+	"X-Admin-Protocol: gsma/rsp/v2.2.0\r\n"

+    "Content-Type: application/json\r\n"

+    "Content-Length: %d\r\n"

+    "\r\n%s\r\n";

+

+static https_context_t g_https_ct = {0};

+static char g_transid[MAX_TRANSID_LEN] = {0};

+char curent_iccid[ICCID_LEN+1] = {0};

+

+extern char g_imei[MAX_IMEI_LEN];

+

+//iccid from bpp install result, if null, failed

+//ISD-P AID, tag '4F';ICCID, tag '5A'. if succ, has AID

+static int lpa_parse_iccid_apdu(char *apdu, char *iccid, int size)

+{

+	int apdu_len = strlen(apdu);

+	unsigned char *apdu_byte = malloc(apdu_len/2 + 1);

+	int apdu_byte_len = 0;

+	char *tag_hex = NULL;

+	char has_iccid[ICCID_LEN+1] = {0};

+

+	if (apdu_byte == NULL) {

+		printf("lpa_parse_iccid_apdu no memory\n");

+		return -1;

+	}

+	memset(apdu_byte, 0, apdu_len/2 + 1);

+

+	apdu_byte_len = string2bytes(apdu, apdu_byte, apdu_len);

+

+	tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x4F);

+	if (tag_hex == NULL) {

+		printf("lpa_parse_iccid_apdu not find AID\n");

+		free(apdu_byte);

+		return -1;

+	}

+	printf("lpa aid:%s\n", tag_hex);

+	free(tag_hex);

+	tag_hex = NULL;

+	

+	tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x5A);

+	if (tag_hex == NULL) {

+		printf("lpa_parse_iccid_apdu not find iccid\n");

+		free(apdu_byte);

+		return -1;

+

+	}

+		

+	snprintf(iccid, size, "%s", tag_hex);

+

+	sc_cfg_get("lpa_bpp_iccid", has_iccid, sizeof(has_iccid));

+	if (strcmp(iccid, has_iccid) != 0) {

+		sc_cfg_set("lpa_bpp_iccid", iccid);

+		sc_cfg_save();

+		printf("lpa iccid not same?\n");

+	}

+

+	printf("lpa iccid:%s\n", iccid);

+

+	free(apdu_byte);

+	free(tag_hex);

+	return 0;

+}

+

+static int lpa_connect_smdp(char *host)

+{

+	SSL_library_init();

+

+	g_https_ct.port=SMDP_PORT;

+	g_https_ct.host=host;

+	g_https_ct.path=NULL;

+	return https_init(&g_https_ct);

+}

+

+static void lpa_disconn_smdp(char *host)

+{

+	https_uninit(&g_https_ct);

+}

+

+static char *lpa_smdp_session(char *path, char *req_data, int *res_len)

+{

+	int ret = -1;

+	int cont_len = 0;

+	char *https_req = NULL;

+	char *https_resp = NULL;

+	int https_req_len = strlen(smdp_https_req)+strlen(path)+strlen(g_https_ct.host)+strlen(req_data)+32;

+

+	*res_len = -1;

+

+	if (https_req_len > SMDP_HTTP_MAX_LEN)

+		return NULL;

+

+	https_req = malloc(https_req_len);

+	if (https_req == NULL)

+		return NULL;

+	

+	memset(https_req, 0, https_req_len);

+	g_https_ct.path = path;

+	ret = snprintf(https_req, https_req_len, smdp_https_req,

+		g_https_ct.path, g_https_ct.host, strlen(req_data), req_data);

+	

+	printf("[https_smdp]req[%d]:##%s##\n", strlen(https_req), https_req);

+	ret = https_write(&g_https_ct, https_req, ret);

+	if (ret == -1) {

+		//EAGAIN?

+		free(https_req);

+		printf("[https_smdp] https_write err:%d.\n", errno);

+		return NULL;

+	}

+

+	ret = https_get_status_code(&g_https_ct, &cont_len);

+	if(ret == 200) {

+	printf("[https_smdp] https_recv len:%d.\n", cont_len);

+		if (cont_len == HTTP_CHUNKED_FLAG) {

+			ret = https_read_chunked_content(&g_https_ct, &https_resp, SMDP_HTTP_MAX_LEN);

+			if(ret > 0) {

+				*res_len = ret;

+				https_resp[ret] = '\0';	//×Ö·û´®½áÊø±êʶ

+				printf("[https_smdp] https_write https_resp_content##%s##\n",https_resp);

+			}

+			printf("[https_smdp] https_resp chunk %d!!!\n", ret);

+		}

+		else {

+			if (cont_len >= SMDP_HTTP_MAX_LEN) {

+				free(https_req);

+				printf("[https_smdp] https_recv too long = %d.\n", cont_len);

+				return NULL;

+			}

+			https_resp = malloc(cont_len + 1);

+			if (https_resp == NULL) {

+				free(https_req);

+				return NULL;

+			}

+

+			memset(https_resp, 0, cont_len + 1);

+			ret = https_read_content(&g_https_ct, https_resp, cont_len);

+			if(ret > 0) {

+				*res_len = ret;

+				https_resp[ret] = '\0';	//×Ö·û´®½áÊø±êʶ

+				printf("[https_smdp] https_read_content##%s##\n",https_resp);

+			} 

+			else {

+				*res_len = -1;

+				free(https_req);

+				free(https_resp);

+				return NULL;

+			}

+		}

+	}

+	else if(ret == 204) {

+		*res_len = 0;

+	}

+	else {

+		printf("[https_smdp] https_resp code = %d.\n", ret);

+	}

+	

+	free(https_req);

+	return https_resp;

+}

+/***************************************************************/

+//

+//ÌáÈ¡stringÀàÐÍÊý¾Ý

+//

+/***************************************************************/

+static char *lpa_parse_json_str(char *srcStr, char *key)

+{

+	cJSON *root = NULL;

+	cJSON *object = NULL;

+	char *value_str = NULL;

+	int value_len = 0;

+

+	root = cJSON_Parse(srcStr);

+	if (root == NULL) {

+		printf("root == NULL\n");

+		return NULL;

+	}

+

+	object = cJSON_GetObjectItem(root, key);

+	if (object == NULL) {

+		printf("key: %s not find\n", key);

+		cJSON_Delete(root);

+		return NULL;

+	}

+	//printf("key:%s-value:%s\n", key, object->valuestring);

+	value_len = strlen(object->valuestring);

+

+	value_str = malloc(value_len + 1);

+	if (value_str == NULL) {

+		cJSON_Delete(root);

+		return NULL;

+

+	}

+	memset(value_str, 0, value_len + 1);

+	strncpy(value_str, object->valuestring, value_len);

+

+	cJSON_Delete(root);

+	return value_str;

+}

+

+/***************************************************************/

+//

+//ÌáÈ¡stringÀàÐ͵Äbase64Êý¾Ý->decode->hex string

+//

+/***************************************************************/

+static char *lpa_parse_json_decode(char *srcStr, char *key)

+{

+	cJSON *root = NULL;

+	cJSON *object = NULL;

+	char *value_byte = NULL;

+	char *value_str = NULL;

+	int value_len = 0;

+

+	root = cJSON_Parse(srcStr);

+	if (root == NULL) {

+		printf("root == NULL\n");

+		return NULL;

+	}

+

+	object = cJSON_GetObjectItem(root, key);

+	if (object == NULL) {

+		printf("key: %s not find\n", key);

+		cJSON_Delete(root);

+		return NULL;

+	}

+	

+	//printf("key:%s-value:%s\n", key, object->valuestring);

+	value_byte = lpa_base64_decode(object->valuestring, strlen(object->valuestring), &value_len);

+	if (value_byte == NULL) {

+		printf("lpa_base64_decode fail\n");

+		cJSON_Delete(root);

+		return NULL;

+	}

+

+	value_str = malloc(value_len*2 + 1);

+	if (value_str == NULL) {

+		free(value_byte);

+		cJSON_Delete(root);

+		return NULL;

+

+	}

+	

+	memset(value_str, 0, value_len*2 + 1);

+	bytes2string(value_byte, value_str, value_len);

+	*(value_str + value_len*2) = '\0';

+	//printf("key:%s(%d)-hex:%s\n", key, value_len*2, value_str);

+	free(value_byte);

+	cJSON_Delete(root);

+	return value_str;

+}

+

+/***************************************************************/

+//

+//char srcStr[] = 

+//"{"

+//	"\"header\" : {"

+//		"\"functionExecutionStatus\" : {"

+//			"\"status\" : \"Executed-Success\""

+//		"}"

+//	"},"

+//	"\"serverSigned1\": \"MEKAEAK3+mF5GUrrl+BlIUcujtSBEFK4u91WT/9GbQX+6pX/aoCDCmVzaW0ud28uY26EEEYRuTYzeka9iSyW+gSFF44=\","

+//    "\"transactionId\": \"02B7FA6179194AEB97E06521472E8ED4\","

+//    "\"serverSignature1\": \"XzdA9J6G6txPTOeOjQThaH/u/Wy/LOcZYec9reC65gjva7waj0XFBs0k551ynos1izFUpXbF8vctFw+/Enqu5aDQTA==\","

+//    "\"serverCertificate\": \"MIIC1jCCAn2gAwIBAgIDAYb6MAoGCCqGSM49BAMCMH4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQIDAVKSUxJTjESMBAGA1UEBwwJQ0hBTkdDSFVOMQ0wCwYDVQQLDARDVUNBMQswCQYDVQQKDAJDVTEvMC0GA1UEAwwmQ2hpbmEgVW5pY29tIGVTSU0gUm9vdCBDQSBOSVNUUCBCWlRFU1QwHhcNMTkxMjI1MTUyNzEyWhcNMjAxMjI0MTUyNzEyWjB5MQswCQYDVQQGEwJDTjEnMCUGA1UECwweSW5ub3ZhdGl2ZSBCdXNpbmVzcyBEZXBhcnRtZW50MQ4wDAYDVQQKDAVWc2VuczExMC8GA1UEAwwoVW5pY29tIFZzZW5zIENvbW11bmljYXRpb24gQ28uIEx0ZChUZXN0KTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABC0BAmyq7voWvhezfZnAoQyRb5CgvPjFuGr7c4arFsbBFNYcv7w5C3Tp3wHD03HkIIhPuZrkx9kWNYeBrekfBw6jge4wgeswHwYDVR0jBBgwFoAUfA5UcBQ+qJmO2d8wBXTJLlqayx8wHQYDVR0OBBYEFC2+UJhg5G9/+zlI3mqf7YMrZHPMMA4GA1UdDwEB/wQEAwIHgDAXBgNVHSABAf8EDTALMAkGB2eBEgECAQQwFQYDVR0RBA4wDIgKKwYBBAGC9UYCBDBpBgNVHR8EYjBgMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjEuY3JsMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjIuY3JsMAoGCCqGSM49BAMCA0cAMEQCIBEAZfg9hJIax/xRpVIAjjmENrPr7q97E0Hv2s+8aOPDAiBaURKuxxzZ8/P0DKE7SmW+AhbxBl1TQd09sM6+Plzu9A==\","

+//    "\"euiccCiPKIdToBeUsed\": \"BBR8DlRwFD6omY7Z3zAFdMkuWprLHw==\""

+//"}";

+//

+/***************************************************************/

+static char *lpa_parse_initauth_resp(char *srcStr)

+{

+	char *transid = NULL;

+	char *signed_hex = NULL;

+	char *signature_hex = NULL;

+	char *ciPKId_hex = NULL;

+	char *certificate_hex = NULL;

+	

+	char *authser_apdu = NULL;

+	//1 transid

+	//2 get sig...

+	//3 genaner at and send

+

+	transid = lpa_parse_json_str(srcStr, "transactionId");

+	if (transid == NULL)

+		goto parse_END;

+	snprintf(g_transid, sizeof(g_transid), "%s", transid);

+	

+	

+	signed_hex = lpa_parse_json_decode(srcStr, "serverSigned1");

+	if (signed_hex == NULL)

+		goto parse_END;

+

+	signature_hex = lpa_parse_json_decode(srcStr, "serverSignature1");

+	if (signature_hex == NULL)

+		goto parse_END;

+

+	ciPKId_hex = lpa_parse_json_decode(srcStr, "euiccCiPKIdToBeUsed");

+	if (ciPKId_hex == NULL)

+		goto parse_END;

+

+	certificate_hex = lpa_parse_json_decode(srcStr, "serverCertificate");

+	if (certificate_hex == NULL)

+		goto parse_END;

+

+//×îºóÒ»¶ÎÊÇɶ£¿ctxparams

+//80E29103£¿91±íʾ½öÒ»¶Î»òÕß×îºóÒ»¶Î

+//×î×îºóµÄ00²»ËãÔÚ³¤¶ÈÄÚ

+//	80E21100FFBF38(00 = i, ff =len)

+//	ffÖ®ºó×¶àÉÙÏß²»¹Ü

+//	ÏÈËãbf38ºó×¶àÉÙ£¬½«bf38ºóÊý¾ÝÏÈ×éºÃ£¬ÔÙ¼Ó

+//	80E2110iLLÀ´·Ö¸îat

+//	²¢ÔÚ×îºóÒ»¶ÎÏ·¢ºó¶ÁÈÏÖ¤·þÎñÆ÷µÄ²ÎÊýat

+

+    //matchingId´Ó¼¤»îÂëÖÐÈ¡£¬Ä¿Ç°Ã»ÓÃ

+	authser_apdu = AuthenticateServer(signed_hex, signature_hex, ciPKId_hex, certificate_hex, "", g_imei);

+

+

+parse_END:

+	if (transid != NULL)

+		free(transid);

+	if (signed_hex != NULL)

+		free(signed_hex);

+	if (signature_hex != NULL)

+		free(signature_hex);

+	if (ciPKId_hex != NULL)

+		free(ciPKId_hex);

+	if (certificate_hex != NULL)

+		free(certificate_hex);

+

+	return authser_apdu;

+}

+

+static char *lpa_parse_authcli_resp(char *srcStr)

+{

+	char *transid = NULL;

+	char *signed2_hex = NULL;

+	char *signature2_hex = NULL;

+	char *certi_hex = NULL;

+	//char *meta_hex = NULL;

+	

+	char *predl_apdu = NULL;

+

+	transid = lpa_parse_json_str(srcStr, "transactionId");

+	if (transid == NULL)

+		goto parse_END;

+	snprintf(g_transid, sizeof(g_transid), "%s", transid);

+	

+	

+	signed2_hex = lpa_parse_json_decode(srcStr, "smdpSigned2");

+	if (signed2_hex == NULL)

+		goto parse_END;

+

+	signature2_hex = lpa_parse_json_decode(srcStr, "smdpSignature2");

+	if (signature2_hex == NULL)

+		goto parse_END;

+

+	certi_hex = lpa_parse_json_decode(srcStr, "smdpCertificate");

+	if (certi_hex == NULL)

+		goto parse_END;

+

+	//meta_hex = lpa_parse_json_decode(srcStr, "profileMetadata");

+	//if (meta_hex == NULL)

+	//	goto parse_END;

+

+	predl_apdu = PrepareDownload(transid, signed2_hex, signature2_hex, certi_hex, "");

+

+parse_END:

+	if (transid != NULL)

+		free(transid);

+	if (signed2_hex != NULL)

+		free(signed2_hex);

+	if (signature2_hex != NULL)

+		free(signature2_hex);

+	if (certi_hex != NULL)

+		free(certi_hex);

+	//if (meta_hex != NULL)

+	//	free(meta_hex);

+

+	return predl_apdu;

+}

+

+static char *lpa_parse_getbpp_resp(char *srcStr)

+{

+	char *transid = NULL;

+	char *bpp_b64 = NULL;

+	

+	char *notify_apdu = NULL;

+

+	transid = lpa_parse_json_str(srcStr, "transactionId");

+	if (transid == NULL)

+		goto parse_END;

+	snprintf(g_transid, sizeof(g_transid), "%s", transid);

+	

+	

+	bpp_b64 = lpa_parse_json_str(srcStr, "boundProfilePackage");

+	if (bpp_b64 == NULL)

+		goto parse_END;

+

+	notify_apdu = LoadBoundProfilePackage(bpp_b64);

+

+parse_END:

+	if (transid != NULL)

+		free(transid);

+	if (bpp_b64 != NULL)

+		free(bpp_b64);

+

+	return notify_apdu;

+}

+

+

+//·µ»ØjsonÊý¾Ý¸øÏÂÒ»²½µ÷ÓÃ

+static char *lpa_initauth(void)

+{

+	int ret = -1;

+	char *euiccChallenge = NULL;

+	char *euiccInfo1 = NULL;

+	char *ia_json = NULL;

+	char *https_resp = NULL;

+	char *resp_apdu = NULL;

+

+	euiccChallenge = GetEUICCChallenge();

+	if (euiccChallenge == NULL) {

+		return NULL;

+	}

+	

+	euiccInfo1 = GetEUICCInfo(TRUE);

+	if (euiccInfo1 == NULL) {

+		free(euiccChallenge);

+		return NULL;

+	}

+	

+	ia_json = InitiateAuthentication(euiccChallenge, euiccInfo1, g_https_ct.host);

+	if (ia_json == NULL) {

+		free(euiccChallenge);

+		free(euiccInfo1);

+		return NULL;

+	}

+

+	https_resp = lpa_smdp_session("initiateAuthentication", ia_json, &ret);

+	if (https_resp != NULL) {

+		resp_apdu = lpa_parse_initauth_resp(https_resp);

+		free(https_resp);

+	}

+	

+	free(euiccChallenge);

+	free(euiccInfo1);

+	free(ia_json);

+	return resp_apdu;

+}

+

+static char *lpa_authclient(char *as_apdu)

+{

+	int ret = -1;

+

+	char *ac_json = NULL;

+	char *https_resp = NULL;

+	char *resp_apdu = NULL;

+

+	ac_json = AuthenticateClient(g_transid, as_apdu);

+	if (ac_json == NULL) {

+		return NULL;

+	}

+	

+	https_resp = lpa_smdp_session("authenticateClient", ac_json, &ret);

+	if (https_resp != NULL) {

+		resp_apdu = lpa_parse_authcli_resp(https_resp);

+		free(https_resp);

+	}

+

+	free(ac_json);

+	return resp_apdu;

+}

+

+static char *lpa_getbpp(char *pdl_apdu)

+{

+	int ret = -1;

+

+	char *bpp_json = NULL;

+	char *https_resp = NULL;

+	char *resp_apdu = NULL;

+

+	bpp_json = GetBoundProfilePackage(g_transid, pdl_apdu);

+	if (bpp_json == NULL) {

+		return NULL;

+	}

+	

+	https_resp = lpa_smdp_session("getBoundProfilePackage", bpp_json, &ret);

+	if (ret > 0) {

+		resp_apdu = lpa_parse_getbpp_resp(https_resp);

+		free(https_resp);

+	}

+

+	free(bpp_json);

+	return resp_apdu;

+}

+

+static int lpa_notification(char *notify_apdu)

+{

+	int ret = -1;

+

+	char *notify_json = NULL;

+	char *https_resp = NULL;

+

+	notify_json = HandleNotification(notify_apdu);

+	if (notify_json == NULL) {

+		return ret;

+	}

+	https_resp = lpa_smdp_session("handleNotification", notify_json, &ret);

+	if (https_resp != NULL)

+		free(https_resp);

+	//no resp?

+	

+	free(notify_json);

+	return ret;

+}

+

+/***************************************************************/

+//

+//"1$esim.wo.cn$$1.3.6.1.4.1.47814.2.4"

+//

+/***************************************************************/

+static char *parse_accode(char *activecode)

+{

+	char *save = NULL;

+	char *host = NULL;

+	char *tmp = NULL;

+	tmp = strtok_r(activecode, "$", &save);

+	if (tmp == NULL)

+		return NULL;

+	tmp = strtok_r(NULL, "$", &save);

+	if (tmp == NULL)

+		return NULL;

+

+	host = malloc(APDU_RESP_LEN);

+	if (host == NULL)

+		return NULL;

+	memset(host, 0, APDU_RESP_LEN);

+	strncpy(host, tmp, APDU_RESP_LEN-1);

+	

+	printf("server:%s\n", host);

+	return host;

+}

+

+static int downloadProfile(char *smdpAddress)

+{

+	int res = -1;

+	char *authser_apdu = NULL;//auth server apdu

+	char *predl_apdu = NULL;//prepare download apdu

+	char *notify_apdu = NULL;//Notification apdu

+	int notify_res = -1;

+	int notify_check = -1;

+	//1 creat https

+	//2 get auth, send	

+	

+	res = lpa_connect_smdp(smdpAddress);

+	if (res != 0) {

+		res = -2;

+		goto download_END;

+	}

+

+	authser_apdu = lpa_initauth();

+	if (authser_apdu == NULL || strlen(authser_apdu) == 0) {

+		res = -2;

+		goto download_END;

+	}

+	

+	predl_apdu = lpa_authclient(authser_apdu);

+	if (predl_apdu == NULL || strlen(predl_apdu) == 0) {

+		res = -2;

+		goto download_END;

+	}

+

+	notify_apdu = lpa_getbpp(predl_apdu);

+	if (notify_apdu == NULL || strlen(notify_apdu) == 0) {

+		res = -2;

+		goto download_END;

+	}

+//dtest

+#if 1

+	notify_res = lpa_notification(notify_apdu);

+	if (notify_res == -1) {

+		printf("lpa_notification fail\n");

+		//goto download_END;//skip, use updata result

+	}

+#endif

+

+	notify_check = lpa_parse_iccid_apdu(notify_apdu, curent_iccid, sizeof(curent_iccid));

+	if (notify_check == -1)

+		goto download_END;

+

+

+	res = 0;

+download_END:

+	if (authser_apdu != NULL)

+		free(authser_apdu);

+	if (predl_apdu != NULL)

+		free(predl_apdu);

+	if (notify_apdu != NULL)

+		free(notify_apdu);

+

+	lpa_disconn_smdp(smdpAddress);

+	return res;

+}

+

+/***************************************************************/

+//

+//ÊäÈ뼤»îÂ뷽ʽÏÂÔØprofile

+//È·ÈÏÂëδÓà confirmcode = NULL

+//

+/***************************************************************/

+int downloadProfileByAc(char *activecode, char *confirmcode)

+{

+	int res = -1;

+	char *smdpAddress = NULL;

+

+	char dl_retry[6] = {0};

+	int count = 0;

+	int i = 0;

+		

+	sc_cfg_get("lpa_dl_retry", dl_retry, sizeof(dl_retry));

+	count = atoi(dl_retry);

+	printf("lpa_updata_retry:%s,%d\n", dl_retry, count);

+	if (count <= 0 || count > 10) { //kw 3

+		count = 1;

+	}

+	

+	smdpAddress = parse_accode(activecode);

+	if (smdpAddress == NULL)

+		return -1;

+

+	for (i = 0; i < count; i++) {

+		res = downloadProfile(smdpAddress);

+		if (res == -2 && i < count-1) {

+			//retry

+			sleep(SMDP_DL_INTERVAL);

+			continue;

+		}

+		break;

+	}

+	

+	free(smdpAddress);

+	return res;

+}

+

+#if 0

+int downloadProfileByEid(void)

+{

+	int res = -1;

+	char *smdpAddress = "esim.wo.cn";//get from default

+

+	res = downloadProfile(smdpAddress);

+

+	return res;

+}

+#endif

+

+/***************************************************************/

+//

+//ÆôÓÃprofile

+//in: iccid 20

+//

+//parse 8001xx return xx:

+//0£ºOK

+//1£ºiccidOrAidNotFound£»

+//2£ºprofileNotInDisabledState£»

+//3£ºdisallowedByPolicy£»

+//4£ºwrongProfileReenabling£»

+//5£ºcatBusy£»

+//127£ºundefinedError

+//ÆäÓà·µ»ØÖµ²Î¿¼6.10½Ú

+//

+/***************************************************************/

+int enableProfile(char *iccid)

+{

+    char *apdu = NULL;

+	int res = 127;

+	apdu = EnableProfile(iccid);

+	if (apdu == NULL)

+		return 127;

+	errno = 0;

+	res = strtol(apdu, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	free(apdu);

+	return res;

+}

+

+/***************************************************************/

+//

+//½ûÓÃprofile

+//

+/***************************************************************/

+int disableProfile(char * iccid)

+{

+	char *apdu = NULL;

+	int res = 127;

+	apdu = DisableProfile(iccid);

+	if (apdu == NULL)

+		return 127;

+	errno = 0;

+	res = strtol(apdu, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	free(apdu);

+	return res;

+}

+

+

+/***************************************************************/

+//

+//ɾ³ýprofile

+//

+/***************************************************************/

+int deleteProfile(char * iccid)

+{

+	char *apdu = NULL;

+	int res = 127;

+	apdu = DeleteProfile(iccid);

+	if (apdu == NULL)

+		return 127;

+	errno = 0;

+	res = strtol(apdu, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	free(apdu);

+	return res;

+}

+

+

+int memoryReset(void)

+{

+	char *apdu = NULL;

+	int res = 127;

+	apdu = EUICCMemoryReset();

+	if (apdu == NULL)

+		return 127;

+	errno = 0;

+	res = strtol(apdu, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	free(apdu);

+	return res;

+}

+

+//limit 10

+static char *lap_parse_profile_list(char *pdu, int *list_n)

+{

+	char *js_list = NULL;

+

+	char *profile = NULL;

+	char *iccid = NULL;

+	char *state = NULL;

+	int status = 0;

+	int i = 0;

+	char *tmp_pdu = pdu;

+	char *offset = NULL;

+

+	js_list = malloc(APDU_RESP_LEN);

+	if (js_list == NULL)

+		return NULL;

+	memset(js_list, 0, APDU_RESP_LEN);

+

+	while(i < 10 && strlen(tmp_pdu) > 0) {

+		profile = lpa_tag_apdu_from_atresp(tmp_pdu, 0xE3);

+		if (profile == NULL)

+			break;

+		

+		iccid = lpa_tag_apdu_from_atresp(tmp_pdu, 0x5A);

+		if (iccid == NULL) {

+			free(profile);

+			break;

+		}

+		lpa_trans_iccid(iccid, strlen(iccid));

+		

+		state = lpa_tag_apdu_from_atresp(tmp_pdu, 0x9F70);

+		if (state == NULL) {

+			free(profile);

+			free(iccid);

+			break;

+		}

+		errno = 0;

+		status = strtol(state, NULL, 16);

+		if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+		{

+			printf("strtol errno %d: %s\n", errno, strerror(errno));

+		}

+		if (i == 0) {

+			snprintf(js_list, APDU_RESP_LEN, 

+				"{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);

+		}

+		else {

+			snprintf(js_list + strlen(js_list), APDU_RESP_LEN - strlen(js_list), 

+				",{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);

+		}

+		

+		offset = strstr(tmp_pdu, profile);

+		if (offset == NULL) {

+			free(profile);

+			free(iccid);

+			free(state);

+			break;

+		}

+		tmp_pdu = offset + strlen(profile);

+		free(profile);

+		free(iccid);

+		free(state);

+		i++;

+

+	}

+	*list_n = i;

+	return js_list;

+}

+

+/***************************************************************/

+//

+//·µ»Ø¸öÊý£¬ºÍjson array[iccid, state]

+//

+/***************************************************************/

+int getProfileList(char **info)

+{

+    char *apdu = NULL;

+	int prof_num = 0;

+	

+	apdu = GetProfilesInfo(NULL);

+	if (apdu == NULL)

+		return prof_num;

+

+	

+	*info = lap_parse_profile_list(apdu, &prof_num);

+

+	

+	free(apdu);

+	return prof_num;

+}

+

diff --git a/ap/lib/liblpa/lpa_https.c b/ap/lib/liblpa/lpa_https.c
new file mode 100755
index 0000000..54b549b
--- /dev/null
+++ b/ap/lib/liblpa/lpa_https.c
@@ -0,0 +1,464 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+
+#include "lpa_inner.h"
+
+
+ 
+// http ÇëÇóÍ·ÐÅÏ¢
+static char https_header[] =
+    "GET %s HTTP/1.1\r\n"
+    "Host: %s:%d\r\n"
+    "Connection: Close\r\n"
+    "Accept: */*\r\n"
+    "\r\n";
+ /*
+ HTTP POST /gsma/rsp2/es9plus/initiateAuthentication HTTP/1.1
+ Host: smdp.gsma.com
+ User-Agent: gsma-rsp-lpad
+ X-Admin-Protocol: gsma/rsp/v2.2.0
+ Content-Type: application/json
+ Content-Length: XXX
+ 
+ {
+	 "euiccChallenge" : "ZVVpY2NDaGFsbGVuZ2VFeGFtcGxlQmFzZTY0oUFZuQnNZVE5D",
+	 "euiccInfo1" : "RmVHRnRjR3hsUW1GelpUWTBvVUZadVFuTlpWRTU",
+	 "smdpAddress" : "smdp.gsma.com"
+ }
+ */
+
+static int create_request_socket(const char* host,const int port)
+{
+    int sockfd;
+    struct hostent *server;
+    struct sockaddr_in serv_addr;
+	struct timeval tv;
+ 
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd < 0)
+    {
+        printf("[http] create_request_socket create socket fail.\n");
+        return -1;
+    }
+	
+	tv.tv_sec = 90;
+	tv.tv_usec = 0;
+	if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+		printf("[http] socket option  SO_RCVTIMEO fail\n");
+		close(sockfd);
+        return -1;
+	}
+ 
+    /* lookup the ip address */
+    server = gethostbyname(host);
+    if(server == NULL)
+    {
+        printf("[http] create_request_socket gethostbyname--%s--fail.\n", host);
+        close(sockfd);
+        return -1;
+    }
+ 
+    memset(&serv_addr,0,sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(port);
+    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
+ 
+    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
+    {
+        printf("[http] create_request_socket connect fail.\n");
+        close(sockfd);
+        return -1;
+    }
+    return sockfd;
+}
+ 
+/**
+ * @brief https_parser_url  ½âÎö³öhttps ÖеÄÓòÃû¡¢¶Ë¿ÚºÍ·¾¶
+ * @param url   ÐèÒª½âÎöµÄurl
+ * @param host  ½âÎö³öÀ´µÄÓòÃû»òÕßip
+ * @param port  ¶Ë¿Ú£¬Ã»ÓÐʱĬÈÏ·µ»Ø443
+ * @param path  ·¾¶£¬Ö¸µÄÊÇÓòÃûºóÃæµÄλÖÃ
+ * @return
+ */
+int https_parser_url(const char* url,char **host,int *port,char **path)
+{
+    if(url == NULL || strlen(url) < 9 || host == NULL || path == NULL)
+    {
+         printf("url or host or path is null.\n");
+         return -1;
+    }
+ 
+    //ÅжÏÊDz»ÊÇ https://
+    int i = 0;
+    char https_prefix[] = "https://";
+    for(i=0;i<8;i++)
+    {
+        if(url[i] != https_prefix[i])
+        {
+            printf("illegal url = %s.\n",url);
+            return -1;
+        }
+    }
+ 
+    const char *temp = url+i;
+    while(*temp != '/')  //next /
+    {
+        if(*temp == '\0')  //
+        {
+            printf("illegal url = %s.\n",url);
+            return -1;
+        }
+        temp++;
+    }
+ 
+    const char *host_port = url+i;
+    while(*host_port != ':' && *host_port != '/')  //ÕÒµ½ :»òÕß / ½áÊø
+    {
+        host_port ++;
+    }
+ 
+    int host_len = host_port-url-i;  //¼õµôhttps://
+    int path_len = strlen(temp);
+    char *host_temp = (char *)malloc(host_len + 1);  //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
+    if(host_temp == NULL)
+    {
+        printf("malloc host fail.\n");
+        return -1;
+    }
+    if(*host_port++ == ':')  //url ÖÐÓж˿Ú
+    {
+        *port = 0;
+        while(*host_port !='/' && *host_port !='\0')  //Ê®½øÖÆ×Ö·û´®×ª³ÉÊý×Ö
+        {
+            *port *= 10;
+            *port += (*host_port - '0');
+            host_port ++;
+        }
+    }
+    else
+    {
+        *port = 443;
+    }
+ 
+    char *path_temp = (char *)malloc(path_len + 1);  //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
+    if(path_temp == NULL)
+    {
+        printf("malloc path fail.\n");
+        free(host_temp);
+        return -1;
+    }
+    memcpy(host_temp,url+i,host_len);
+    memcpy(path_temp,temp,path_len);
+    host_temp[host_len] = '\0';
+    path_temp[path_len] = '\0';
+    *host = host_temp;
+    *path = path_temp;
+    return 0;
+}
+ 
+int https_init(https_context_t *context)
+{
+	int ret = 0;
+    if(context == NULL)
+    {
+        printf("init https_context_t is null.\n");
+        return -1;
+    }
+ /*
+    if(https_parser_url(url,&(context->host),&(context->port),&(context->path)))
+    {
+        printf("https_parser_url fail.\n");
+        return -1;
+    }
+ */
+    context->sock_fd = create_request_socket(context->host,context->port);
+	printf("create_request_socket %d.\n",context->sock_fd);
+    if(context->sock_fd < 0)
+    {
+        goto https_init_fail;
+    }
+ 
+    context->ssl_ct = SSL_CTX_new(SSLv23_method());
+	printf("SSL_CTX_new %p.\n",context->ssl_ct); //cov m
+    if(context->ssl_ct == NULL)
+    {
+        goto https_init_fail;
+    }
+ 
+    context->ssl = SSL_new(context->ssl_ct);
+	printf("SSL_new %p.\n",context->ssl); //cov m
+    if(context->ssl == NULL)
+    {
+        goto https_init_fail;
+    }
+ 	ret = SSL_set_fd(context->ssl,context->sock_fd);
+	printf("SSL_set_fd ret %d \n",ret);
+ 	ret = SSL_connect(context->ssl);
+	printf("SSL_connect ret %d \n",ret);
+    if(ret == -1)
+    {
+        goto https_init_fail;
+    }
+    return 0;
+https_init_fail:
+    https_uninit(context);
+    return -1;
+}
+ 
+int https_read(https_context_t *context,void* buff,int len)
+{
+    if(context == NULL || context->ssl == NULL)
+    {
+        printf("read https_context_t or ssl is null.\n");
+        return -1;
+    }
+    return SSL_read(context->ssl,buff,len);
+}
+ 
+int https_write(https_context_t *context,const void* buff,int len)
+{
+    if(context == NULL || context->ssl == NULL)
+    {
+        printf("write https_context_t or ssl is null.\n");
+        return -1;
+    }
+    return SSL_write(context->ssl,buff,len);
+}
+ 
+int https_get_status_code(https_context_t *context, int *content_len)
+{
+    int ret;
+    int flag =0;
+    int recv_len = 0;
+    char res_header[1024] = {0};
+	
+	if(context == NULL || context->ssl == NULL)
+    {
+        printf("get status https_context_t or ssl is null.\n");
+        return -1;
+    }
+	
+    while(recv_len < (sizeof(res_header)-1))
+    {
+        ret = SSL_read(context->ssl, res_header+recv_len, 1);
+        if(ret<1)  // recv fail
+        {
+            break;
+        }
+        //ÕÒµ½ÏìӦͷµÄÍ·²¿ÐÅÏ¢, Á½¸ö"\r\n"Ϊ·Ö¸îµã
+        if((res_header[recv_len]=='\r'&&(flag==0||flag==2))||(res_header[recv_len]=='\n'&&(flag==1||flag==3)))
+        {
+            flag++;
+        }
+        else
+        {
+            flag = 0;
+        }
+        recv_len+=ret;
+        if(flag==4)
+        {
+            break;
+        }
+    }
+    //printf("[http] recv_len=%d res_header = %s.\n",recv_len,res_header);
+    /*»ñÈ¡ÏìӦͷµÄÐÅÏ¢*/
+    int status_code = -1;
+    char *pos = strstr(res_header, "HTTP/");
+    if(pos)
+    {
+        sscanf(pos, "%*s %d", &status_code);//·µ»Ø×´Ì¬Âë
+    }
+
+	int cont_len = 0; 
+	pos = strstr(res_header, "Content-Length:");
+    if(pos)
+    {
+        sscanf(pos, "%*s %d", &cont_len);//·µ»Ø×´Ì¬Âë
+    }
+	pos = strstr(res_header, "chunked");
+	if(pos)//Transfer-Encoding: chunked
+	{
+		cont_len = HTTP_CHUNKED_FLAG;
+	}
+	*content_len = cont_len;
+	
+	printf("res_head##%s##\n", res_header);
+	printf("status_code:%d, Content-Length:%d\n", status_code, cont_len);
+
+    return status_code;
+}
+ 
+int https_read_content(https_context_t *context,char *resp_contet,int max_len)
+{
+    if(context == NULL || context->ssl == NULL)
+    {
+        printf("read content https_context_t or ssl is null.\n");
+        return -1;
+    }
+    int ret ;
+    int recv_size = 0;
+    while(recv_size < max_len)
+    {
+       ret = SSL_read(context->ssl,resp_contet + recv_size,max_len-recv_size);
+	   if(ret < 1)
+       {
+           break;
+       }
+       recv_size += ret;
+    }
+    return recv_size;
+}
+//[Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][0][»Ø³µ][footerÄÚÈÝ£¨Óеϰ£©][»Ø³µ]
+//×¢Òâchunk-sizeÊÇÒÔÊ®Áù½øÖƵÄASCIIÂë±íʾµÄ£¬±ÈÈç86AE£¨Êµ¼ÊµÄÊ®Áù½øÖÆÓ¦¸ÃÊÇ£º38366165£©£¬¼ÆËã³É³¤¶ÈÓ¦¸ÃÊÇ£º34478£¬±íʾ´Ó»Ø³µÖ®ºóÓÐÁ¬ÐøµÄ34478×Ö½ÚµÄÊý¾Ý
+int https_read_chunked_content(https_context_t *context,char **resp_contet,int max_len)
+{   
+    int ret = 0;
+	int flag = 0;
+    int recv_size = 0;
+	
+	int recv_len = 0;
+    char chunk_header[1024] = {0};
+	
+	int read_flag = 0;
+	int read_len = 1;
+		
+	if(context == NULL || context->ssl == NULL)
+    {
+        printf("read content https_context_t or ssl is null.\n");
+        return -1;
+    }
+	
+    while(recv_size < max_len)
+    {		
+		if (read_flag == 0) {
+			ret = SSL_read(context->ssl, chunk_header+recv_len, read_len);
+			if(ret < 1)  // recv fail
+			{
+				break;
+			}
+			printf("chunk_header##%s##\n", chunk_header+recv_len);
+			//Ò»¸ö"\r\n"Ϊ·Ö¸îµã
+			if((chunk_header[recv_len]=='\r'&&flag==0)||(chunk_header[recv_len]=='\n'&&flag==1))
+			{
+				flag++;
+			}
+			else
+			{
+				flag = 0;
+			}
+			recv_len += ret;
+			if(flag == 2)
+			{
+				if (strlen(chunk_header) > 2) {
+					//Ìø¹ý·Ç0~9£¬A~F???
+					errno = 0;
+					int size =strtol(chunk_header, NULL, 16);
+					if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+					{
+						printf("strtol errno %d: %s\n", errno, strerror(errno));
+					}
+					//sscanf(pos, "%X", &cont_len);//X???
+					if (size <= 0 || size >= max_len) {
+						read_flag = 2;
+						read_len = sizeof(chunk_header)-1;
+					}
+					else {
+						read_flag = 1;
+						read_len = size;
+					}
+				}
+				memset(chunk_header, 0, sizeof(chunk_header));
+				recv_len = 0;
+			}
+			if (recv_len >= (sizeof(chunk_header)-1))
+				break;
+		} 
+		else if(read_flag == 1) {
+			if(recv_size == 0) {
+				char *resp_tmp = malloc(read_len + 1);;
+				if (resp_tmp == NULL) {
+					printf("resp_tmp is null\n");
+					return -1;
+				}
+				memset(resp_tmp, 0, read_len + 1);
+				*resp_contet = resp_tmp;
+			}
+			else {
+				char *resp_tmp = NULL;
+				resp_tmp = realloc(*resp_contet, recv_size + read_len + 1);
+				if (resp_tmp == NULL) {
+					free(*resp_contet);
+					printf("resp_tmp realloc null\n");
+					return -1;
+				}
+				*resp_contet = resp_tmp;
+			}
+			//read Ö±µ½³¤¶È
+			ret = https_read_content(context, (*resp_contet)+recv_size, read_len);
+			if(ret<1)  // recv fail
+			{
+				break;
+			}
+			read_len = 1;
+			read_flag = 0;
+			recv_size += ret;
+		} 
+		else {
+			ret = SSL_read(context->ssl, chunk_header, read_len);
+			printf("chunk_header##%s##\n", chunk_header);
+			break;
+		}
+
+    }
+    return recv_size;
+}
+
+ 
+int https_uninit(https_context_t *context)
+{
+    if(context == NULL)
+    {
+        printf("uninit https_context_t is null.\n");
+        return -1;
+    }
+
+    if(context->host != NULL)
+    {
+        //free(context->host);
+        context->host = NULL;
+    }
+	
+    if(context->path != NULL)
+    {
+        //free(context->path);
+        context->path = NULL;
+    }
+
+    if(context->ssl != NULL)
+    {
+        SSL_shutdown(context->ssl);
+        //SSl_free(context->ssl);
+        context->ssl = NULL;
+    }
+    if(context->ssl_ct != NULL)
+    {
+        SSL_CTX_free(context->ssl_ct);
+        context->ssl_ct = NULL;
+    }
+    if(context->sock_fd > 0)
+    {
+        close(context->sock_fd);
+        context->sock_fd = -1;
+    }
+    return 0;
+}
+
diff --git a/ap/lib/liblpa/lpa_inner.h b/ap/lib/liblpa/lpa_inner.h
new file mode 100755
index 0000000..d77bd68
--- /dev/null
+++ b/ap/lib/liblpa/lpa_inner.h
@@ -0,0 +1,107 @@
+#ifndef __LPA_INNER_H__

+#define __LPA_INNER_H__

+

+#include <openssl/ssl.h>

+#include <openssl/bio.h>

+

+#include "lpa_api.h"

+

+#include "cjson.h"

+#include "md5.h"

+#include "errno.h"

+

+#define MAX_IMEI_LEN 17

+#define MAX_TRANSID_LEN 41

+

+#define CSIM_REQ_LEN 600 

+#define CSIM_RESP_LEN 600 

+#define APDU_REQ_LEN 520 //tag10+255*2+00

+#define APDU_RESP_LEN 520 //0xFF*2+sw1+sw2=514

+#define APDU_BYTE_LEN 261 //csimЭÒéÕ»·µ»Ø×î´ó³¤¶È255 APDU_RESP_LEN/2+1

+#define MIN_APDU_LEN 16 //80E2910004TG01XX

+

+#define SMDP_HTTP_MAX_LEN 0x20000 //128K

+#define TRIG_HTTP_MAX_LEN 0x2000 //8K

+#define HTTP_CHUNKED_FLAG 0x7FFFFFFF

+

+

+

+

+#define ICCID_LEN 20

+

+//#define CSIM_APDU_LEN 511  //csimЭÒéÕ»·µ»Ø×î´ó³¤¶È255

+

+#ifndef BOOL

+#define BOOL 	  	unsigned char

+#endif

+#ifndef TRUE

+#define	TRUE	1

+#endif

+#ifndef FALSE

+#define	FALSE	0

+#endif

+

+

+typedef struct

+{

+    int sock_fd;

+    SSL_CTX *ssl_ct;

+    SSL *ssl;

+ 

+    //url ½âÎö³öÀ´µÄÐÅÏ¢

+    char *host;

+    char *path;

+    int port;

+} https_context_t;

+

+//https

+int https_init(https_context_t *context);

+int https_uninit(https_context_t *context);

+int https_read(https_context_t *context,void* buff,int len);

+int https_write(https_context_t *context,const void* buff,int len);

+int https_get_status_code(https_context_t *context, int *content_len);

+int https_read_content(https_context_t *context,char *resp_contet,int max_len);

+

+//es10b

+char *GetEUICCChallenge(void);

+char *GetEUICCInfo(BOOL flag);

+char *AuthenticateServer(char *signd1Hex, char *signature1Hex, char *ciPKIdHex, char *certificateHex, char *matchingId, char *imeiHex);

+char *PrepareDownload(char *transId ,char *signed2Hex,char *signature2Hex,char *certiHex,char *confirmCode);

+char *LoadBoundProfilePackage(char * bppHex);

+

+

+//es10c

+char *EnableProfile(char *iccidHex);

+char *EUICCMemoryReset(void);

+char *GetProfilesInfo(char *iccidHex);

+char *DisableProfile(char *iccidHex);

+char *DeleteProfile  (char *iccidHex);

+char *GetEID(void);

+

+//es9+

+char *InitiateAuthentication(char *euiccChallenge, char *euiccInfo1, char *smdpAddress);

+char *AuthenticateClient(char *transactionId,char *authSerRespHex);

+char *GetBoundProfilePackage (char *transactionId, char *predlRespHex);

+char *HandleNotification(char *pnfHex);

+

+//channel

+char *OpenLogicalChannel(void);

+int CloseLogicalChannel(int chan_id);

+

+

+//edcode

+char *lpa_tlv_get_val_by_tag(unsigned char *apdu_byte, int apdu_len, unsigned int tag);

+char *lpa_tag_apdu_from_atresp(char *atres_apdu, unsigned int tag);

+char *lpa_get_apdu_from_atresp(char *atres_apdu);

+int lpa_csim_resp_code(char *atres_apdu, int *second_len);

+int lpa_csim_resp_normal(char *atres_apdu);

+

+int string2bytes(const char* pSrc, unsigned char* pDst, int nSrcLength);

+int bytes2string(const unsigned char* pSrc, char* pDst, int nSrcLength);

+

+char *lpa_base64_encode(const char*data, int data_len);

+unsigned char *lpa_base64_decode(const unsigned char *src, int len, int *out_len);

+

+void lpa_trans_iccid(char *iccid, int len);

+

+#endif

diff --git a/ap/lib/liblpa/lpa_tool.c b/ap/lib/liblpa/lpa_tool.c
new file mode 100755
index 0000000..a13fbe9
--- /dev/null
+++ b/ap/lib/liblpa/lpa_tool.c
@@ -0,0 +1,424 @@
+/***************************************************************/

+//

+//²Î¼û LPA½Ó¿ÚÎĵµV0.1 SGP.22, ·µ»ØAPDU

+//   

+/***************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <ctype.h>

+#include <sys/time.h>

+#include <termios.h>

+

+#include "lpa_inner.h"

+

+

+static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

+

+/**

+ * @brief ¿É´òÓ¡×Ö·û´®×ª»»Îª×Ö½ÚÊý¾Ý £¬È磺

+                "C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}

+ * @param pSrc Ô´×Ö·û´®Ö¸Õë

+ * @param pDst Ä¿±êÊý¾ÝÖ¸Õë

+ * @param nSrcLength Ô´×Ö·û´®³¤¶È

+ * @return Ä¿±êÊý¾Ý³¤¶È

+ * @note   

+ * @warning 

+ */

+int string2bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)

+{

+    int i=0;

+

+    //УÑé²ÎÊý

+    if(pSrc ==  NULL || pDst == NULL || nSrcLength < 0)

+    {

+        return -1;

+    }

+

+    for(i = 0; i < nSrcLength; i += 2)

+    {

+        // Êä³ö¸ß4λ

+        if(*pSrc >= '0' && *pSrc <= '9')

+        {

+            *pDst = (*pSrc - '0') << 4;

+        }

+        else

+        {

+            *pDst = ((toupper(*pSrc) - 'A') + 10) << 4;

+        }

+

+        pSrc++;

+

+        // Êä³öµÍ4λ

+        if(*pSrc >= '0' && *pSrc <= '9')

+        {

+            *pDst |= *pSrc - '0';

+        }

+        else

+        {

+            *pDst |= (toupper(*pSrc) - 'A') + 10;

+        }

+

+        pSrc++;

+        pDst++;

+    }

+

+    // ·µ»ØÄ¿±êÊý¾Ý³¤¶È

+    return nSrcLength / 2;

+}

+

+/**

+ * @brief ×Ö½ÚÊý¾Ýת»»Îª¿É´òÓ¡×Ö·û´® £¬È磺

+                     {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"

+ * @param pSrc Ô´Êý¾ÝÖ¸Õë

+ * @param pDst Ä¿±ê×Ö·û´®Ö¸Õë

+ * @param nSrcLength Ô´Êý¾Ý³¤¶È

+ * @return Ä¿±êÊý¾Ý³¤¶È£»

+ * @note   

+ * @warning 

+ */

+int bytes2string(const unsigned char* pSrc, char* pDst, int nSrcLength)

+{

+    const char tab[]="0123456789ABCDEF";	// 0x0-0xfµÄ×Ö·û²éÕÒ±í

+    int i = 0;

+

+    //УÑé²ÎÊý

+    if(pSrc ==  NULL || pDst == NULL || nSrcLength < 0)

+    {

+        return -1;

+    }

+

+    for(i=0; i<nSrcLength; i++)

+    {

+        *pDst++ = tab[*pSrc >> 4];		// Êä³öµÍ4λ

+        *pDst++ = tab[*pSrc & 0x0f];	// Êä³ö¸ß4λ

+        pSrc++;

+    }

+

+    // ·µ»ØÄ¿±ê×Ö·û´®³¤¶È

+    return nSrcLength * 2;

+}

+

+//lower case

+int bytes2string_lower(const unsigned char* pSrc, char* pDst, int nSrcLength)

+{

+    const char tab[]="0123456789abcdef";	// 0x0-0xfµÄ×Ö·û²éÕÒ±í

+    int i = 0;

+

+    //УÑé²ÎÊý

+    if(pSrc ==  NULL || pDst == NULL || nSrcLength < 0)

+    {

+        return -1;

+    }

+

+    for(i=0; i<nSrcLength; i++)

+    {

+        *pDst++ = tab[*pSrc >> 4];		// Êä³öµÍ4λ

+        *pDst++ = tab[*pSrc & 0x0f];	// Êä³ö¸ß4λ

+        pSrc++;

+    }

+

+    // ·µ»ØÄ¿±ê×Ö·û´®³¤¶È

+    return nSrcLength * 2;

+}

+

+

+char *lpa_base64_encode(const char*data, int data_len)

+{ 

+    //int data_len = strlen(data); 

+    int prepare = 0; 

+    int ret_len; 

+    int temp = 0; 

+    char *ret = NULL; 

+    char *f = NULL; 

+    int tmp = 0; 

+    char changed[4]; 

+    int i = 0; 

+	const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 

+

+	if(data == NULL)

+	{

+		return NULL;

+	}

+	if(data_len == 0)

+	{

+		return NULL;

+	}

+    ret_len = data_len / 3; 

+    temp = data_len % 3; 

+    if (temp > 0) 

+    { 

+        ret_len += 1; 

+    } 

+    ret_len = ret_len*4 + 1; 

+    ret = (char *)malloc(ret_len); 

+      

+    if (ret == NULL) 

+    { 

+        printf("No enough memory.\n"); 

+        return NULL;

+    } 

+    memset(ret, 0, ret_len); 

+    f = ret; 

+    while (tmp < data_len) 

+    { 

+        temp = 0; 

+        prepare = 0; 

+        memset(changed, '\0', 4); 

+        while (temp < 3) 

+        { 

+            //printf("tmp = %d\n", tmp); 

+            if (tmp >= data_len) 

+            { 

+                break; 

+            } 

+            prepare = ((prepare << 8) | (data[tmp] & 0xFF)); 

+            tmp++; 

+            temp++; 

+        } 

+        prepare = (prepare<<((3-temp)*8)); 

+        //printf("before for : temp = %d, prepare = %d\n", temp, prepare); 

+        for (i = 0; i < 4 ;i++ ) 

+        { 

+            if (temp < i) 

+            { 

+                changed[i] = 0x40; 

+            } 

+            else 

+            { 

+                changed[i] = (prepare>>((3-i)*6)) & 0x3F; 

+            } 

+            *f = base[changed[i]]; 

+            //printf("%.2X", changed[i]); 

+            f++; 

+        } 

+    } 

+    *f = '\0'; 

+    return ret; 

+} 

+

+unsigned char *lpa_base64_decode(const unsigned char *src, int len, int *out_len)

+{

+	unsigned char dtable[256] = {0};//kw

+	unsigned char *out = NULL;

+	unsigned char *pos = NULL;

+	unsigned char in[4] = {0};

+	unsigned char block[4] = {0};

+	unsigned char tmp = 0;

+	int i = 0;

+	int count = 0;

+	int olen = 0;

+

+	memset(dtable, 0x80, 256);

+	for (i = 0; i < sizeof(base64_table) - 1; i++)

+		dtable[base64_table[i]] = (unsigned char) i;

+	dtable['='] = 0;

+

+	count = 0;

+	for (i = 0; i < len; i++) {

+		if (dtable[src[i]] != 0x80)

+			count++;

+	}

+

+	if (count == 0 || count % 4)

+		return NULL;

+

+	olen = count / 4 * 3;

+	pos = out = malloc(olen);

+	if (out == NULL)

+		return NULL;

+	memset(pos, 0, olen);

+

+	count = 0;

+	for (i = 0; i < len; i++) {

+		tmp = dtable[src[i]];

+		if (tmp == 0x80)

+			continue;

+

+		in[count] = src[i];

+		block[count] = tmp;

+		count++;

+		if (count == 4) {

+			*pos++ = (block[0] << 2) | (block[1] >> 4);

+			*pos++ = (block[1] << 4) | (block[2] >> 2);

+			*pos++ = (block[2] << 6) | block[3];

+			count = 0;

+		}

+	}

+

+	if (pos > out) {

+		if (in[2] == '=')

+			pos -= 2;

+		else if (in[3] == '=')

+			pos--;

+	}

+

+	*out_len = pos - out;

+	return out;

+}

+

+//lpa code

+//0 ok, -1 error, 9000 91XX 92XX and 61XX

+int lpa_csim_resp_code(char *atres_apdu, int *second_len)

+{

+	int pdu_len = 0;

+	char sw1_s[3] = {0};

+	char sw2_s[3] = {0};

+	int sw1 = 0;

+	int sw2 = 0;

+	int res = -1;

+

+	pdu_len = strlen(atres_apdu);//kw 1

+	if (pdu_len < 4) {

+		printf("lpa_csim_resp_code len err:%d\n", pdu_len);

+		return res;

+	}

+	

+	strncpy(sw1_s, atres_apdu + pdu_len - 4, sizeof(sw1_s) - 1);

+	strncpy(sw2_s, atres_apdu + pdu_len - 2, sizeof(sw2_s) - 1);

+	errno = 0;

+	sw1 =strtol(sw1_s, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	errno = 0;

+	sw2 =strtol(sw2_s, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	if ((sw1 == 0x90 && sw2 == 0x00) || (sw1 == 0x91) || (sw1 == 0x92)) {

+		*second_len = 0;

+		res = 0;

+	}

+	else if(sw1 == 0x61) {

+		*second_len = sw2;

+		if (sw2 == 0x00) {//tianyu: bigger than 256, use 00c0000000

+			*second_len = 0xFF;

+		}

+		res = 0;

+	}

+	

+	return res;

+}

+

+

+//0 ok, -1 error, 9000 91XX 92XX

+int lpa_csim_resp_normal(char *atres_apdu)

+{

+	int pdu_len = 0;

+	char sw1_s[3] = {0};

+	char sw2_s[3] = {0};

+	int sw1 = 0;

+	int sw2 = 0;

+

+	pdu_len = strlen(atres_apdu);//kw 1

+	if (pdu_len < 4) {

+		printf("lpa_csim_resp_normal len err:%d\n", pdu_len);

+		return -1;

+	}

+	

+	strncpy(sw1_s, atres_apdu + pdu_len - 4, sizeof(sw1_s) - 1);

+	strncpy(sw2_s, atres_apdu + pdu_len - 2, sizeof(sw2_s) - 1);

+	errno = 0;

+	sw1 =strtol(sw1_s, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	errno = 0;

+	sw2 =strtol(sw2_s, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	//normal processing: 9000 91XX 92XX

+	if ((sw1 == 0x90 && sw2 == 0x00) || (sw1 == 0x91) || (sw1 == 0x92)) {

+		return 0;

+	}

+	

+	return -1;

+}

+

+//delete sw1 sw2

+char *lpa_get_apdu_from_atresp(char *atres_apdu)

+{

+	int pdu_len = 0;

+	char *apdu = NULL;

+

+	pdu_len = strlen(atres_apdu);//kw

+	if (pdu_len < 4 || pdu_len >= APDU_RESP_LEN)

+		return NULL;

+	

+	apdu = malloc(APDU_RESP_LEN);

+	if (apdu == NULL)

+		return NULL;

+	memset(apdu, 0, APDU_RESP_LEN);

+	strncpy(apdu, atres_apdu, pdu_len - 4);//len = 4 -> "\0"

+	printf("get apdu: %s\n", apdu);

+	return apdu;

+}

+

+

+//´ÓcsimµÄapduÖнâ³öÖ¸¶¨µÄtagµÄvalue(hexstring)

+//Èç¹ûÓжà×éͬÃûtag£¬Ö»Äܽâ³öµÚÒ»×é

+char *lpa_tag_apdu_from_atresp(char *atres_apdu, unsigned int tag)

+{

+	int pdu_len = 0;

+	char *apdu = NULL;

+	unsigned char *pdu_byte = NULL;

+	int nt_byte_len = 0;

+

+	pdu_len = strlen(atres_apdu);//kw

+	if (pdu_len <= 0) {

+		printf("atres_apdu len err:%d\n", pdu_len);

+		return NULL;

+	}

+	

+	pdu_byte = malloc(pdu_len/2 + 1);

+	if (pdu_byte == NULL) {

+		printf("atres_apdu malloc fail\n");

+		return NULL;

+	}

+

+	memset(pdu_byte, 0, pdu_len/2 + 1);

+	nt_byte_len = string2bytes(atres_apdu, pdu_byte, pdu_len);

+	if (nt_byte_len < 2) {

+		free(pdu_byte);

+		printf("atres_apdu to byte err\n");

+		return NULL;

+	}

+	

+	apdu = lpa_tlv_get_val_by_tag(pdu_byte, nt_byte_len, tag);

+	

+	free(pdu_byte);

+	

+	return apdu;

+}

+

+

+//9812.... to 8921

+void lpa_trans_iccid(char *iccid, int len)

+{

+	char low = 0;

+	char high = 0;

+	int i = 0;

+

+    if (iccid == NULL || len != ICCID_LEN) {

+		printf("iccid check fail\n");

+		return;

+    }

+

+	for(i = 0; i < len; i += 2)

+	{

+		low = *(iccid);

+		high = *(iccid + 1);

+		*(iccid) = high;

+		*(iccid + 1) = low;

+

+		iccid = iccid + 2;

+	}

+}

+

diff --git a/ap/lib/liblpa/lpa_user.c b/ap/lib/liblpa/lpa_user.c
new file mode 100755
index 0000000..da2f16f
--- /dev/null
+++ b/ap/lib/liblpa/lpa_user.c
@@ -0,0 +1,935 @@
+/***************************************************************/

+//

+//²Î¼û LPA½Ó¿ÚÎĵµV0.1 SGP.22, ·µ»ØAPDU

+//   

+/***************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <ctype.h>

+#include <sys/time.h>

+#include <time.h>

+#include <termios.h>

+

+#include "lpa_inner.h"

+

+#define LPA_TRIGGER_DATA_LEN 512

+#define TRIGGER_HTTP_REQ_LEN 512

+#define TRIGGER_HTTP_RESP_LEN 512

+

+#define HASH_SIZE 16

+#define HASH_HEX_SIZE 33

+

+#define MAX_TIME_LEN 24

+

+#define MAX_APPID_LEN 65

+#define MAX_URL_LEN 129

+

+int g_chan_id = 0; //logical channel

+static int g_open_channel_flag = 0;

+

+extern char curent_iccid[ICCID_LEN+1];

+

+//use nv

+//#define APPID "O8XTcVkZ8L4RDv1V"

+//#define APPSECRET "WNbHQlRV9JKeqpVWSurQWZLXwDs5T9Dl"

+//#define TRIGGER_PORT 61622

+//#define TRIGGER_HOST "serviceplatformt.esim.chinaunicom.cn"

+//#define TRIGGER_EVENT_URL "/esim_uni_plus_server/api/event"

+//#define TRIGGER_UPDATA_URL "/esim_uni_plus_server/api/updata"

+

+

+//´¥·¢·þÎñÆ÷httpÇëÇó

+static char trigger_https_req[] =

+    "POST %s HTTP/1.1\r\n"

+    "Host: %s\r\n"

+    "Content-Type: application/json\r\n"

+    "Content-Length: %d\r\n"

+    "Accept: */*\r\n"

+    "\r\n%s\r\n";

+

+static char trigger_https_event[] =

+"{"

+	"\"HEAD\": {"

+		"\"APPID\": \"%s\","

+		"\"TIME\": \"%s\","

+		"\"TRANSID\": \"%s\","

+		"\"TOKEN\": \"%s\""

+	"},"

+	"\"BODY\": {"

+		"\"EID\": \"%s\","

+		"\"IMEI\": \"%s\""

+	"}"

+"}";

+

+static char trigger_https_updata[] =

+"{"

+	"\"HEAD\": {"

+		"\"APPID\": \"%s\","

+		"\"TIME\": \"%s\","

+		"\"TRANSID\": \"%s\","

+		"\"TOKEN\": \"%s\""

+	"},"

+	"\"BODY\": {"

+		"\"EID\": \"%s\","

+		"\"IMEI\": \"%s\","

+		"\"EXEC_RESULT\": %d,"

+		"\"EXEC_REASON\": \"%s\","

+		"\"DATA_INFO\": [%s]"

+	"}"

+"}";

+

+

+char g_imei[MAX_IMEI_LEN] = {0};

+

+/***************************************************************/

+//

+//imei

+//

+/***************************************************************/

+static int lpa_get_imei(char *imei, int size)

+{

+	int ret = -1;

+	char t_imei[MAX_IMEI_LEN] = {0};

+	void *p2[] = {t_imei};

+

+	sc_cfg_get ("imei", imei, size);

+	if (strlen(imei) < 15) {

+		ret = get_modem_info("AT+CGSN\r\n", "%s", p2);

+		if(ret == 0) {

+			snprintf(imei, size, "%s", t_imei);

+		}

+		return ret;

+	}

+

+	return 0;

+}

+

+static int lpa_get_iccid(char *iccid, int size)

+{

+	int ret = -1;

+	char t_iccid[ICCID_LEN+1] = {0};

+	void *p2[] = {t_iccid};

+

+

+	ret = get_modem_info("AT+ZICCID?\r\n", "%s", p2);

+	if(ret == 0) {

+		snprintf(iccid, size, "%s", t_iccid);

+	}

+	return ret;

+

+}

+

+/***************************************************************/

+//

+//time

+//

+/***************************************************************/

+static int lpa_get_time(char *time, int size)

+{

+	struct tm ptm = {0};	

+	struct timeval now_time = {0};

+	

+	gettimeofday(&now_time, NULL);

+	localtime_r(&now_time.tv_sec, &ptm);

+

+	snprintf(time, size, "%d-%02d-%02d %02d:%02d:%02d %03d", 

+		ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, now_time.tv_usec/1000);

+	

+	//printf("lpa_get_time: %s\n", time);

+	return 0;

+}

+

+static int lpa_get_transid(char *transid, int size, char *imei)

+{

+	struct tm ptm = {0};	

+	struct timeval now_time = {0};

+	

+	gettimeofday(&now_time, NULL);

+	localtime_r(&now_time.tv_sec, &ptm);

+

+	snprintf(transid, size, "%s%04d%02d%02d%02d%02d%02d%03d", 

+		imei, ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, now_time.tv_usec/1000);

+	

+	//printf("lpa_get_transid: %s\n", transid);

+	return 0;

+}

+

+//0 fail 1 succ

+static int lpa_get_exeres(char *exe_reason, int len)

+{	

+	sc_cfg_get("lpa_last_res", exe_reason, len);

+	if (0 == strcmp(exe_reason,"success"))

+		return 1;

+

+	return 0;

+}

+

+/***************************************************************/

+//

+//

+//

+/***************************************************************/

+static char *lpa_get_trigger_data(void)

+{

+	int ret = -1;

+	//char imei[MAX_IMEI_LEN] = {0};

+	char time[MAX_TIME_LEN] = {0};

+	char transid[MAX_TRANSID_LEN] = {0};

+	char *eid = NULL;

+	lpa_MD5_CTX md5ctx = {0};

+	unsigned char hash[HASH_SIZE] = {0};

+	char token[HASH_HEX_SIZE] = {0};

+	char *js_data = NULL;

+	char appid[MAX_APPID_LEN] = {0};

+	char appsecret[MAX_APPID_LEN] = {0};

+

+	sc_cfg_get("lpa_appid", appid, sizeof(appid));

+	sc_cfg_get("lpa_appsecret", appsecret, sizeof(appsecret));

+

+	lpa_get_time(time, sizeof(time));

+	lpa_get_transid(transid, sizeof(transid), g_imei);

+

+	lpa_MD5_Init(&md5ctx);

+	lpa_MD5_Update(&md5ctx, appid, strlen(appid));	

+	lpa_MD5_Update(&md5ctx, transid, strlen(transid));

+	lpa_MD5_Update(&md5ctx, time, strlen(time));

+	lpa_MD5_Update(&md5ctx, appsecret, strlen(appsecret));

+	lpa_MD5_Final(hash, &md5ctx);

+	//token lower case

+	bytes2string_lower(hash, token, sizeof(hash));

+

+	eid = GetEID();

+	if (eid == NULL) {

+		return NULL;

+	}

+	js_data = malloc(LPA_TRIGGER_DATA_LEN);

+	if (js_data != NULL) {

+		memset(js_data, 0, LPA_TRIGGER_DATA_LEN);

+		snprintf(js_data, LPA_TRIGGER_DATA_LEN, trigger_https_event, 

+			appid, time, transid, token, eid, g_imei);

+		//printf("trigger json:-%s-\n", js_data);

+	}

+

+	free(eid);

+	return js_data;

+}

+

+static char *lpa_get_updata_data(void)

+{

+	int ret = -1;

+	//char imei[MAX_IMEI_LEN] = {0};

+	char time[MAX_TIME_LEN] = {0};

+	char transid[MAX_TRANSID_LEN] = {0};

+	char *eid = NULL;

+	lpa_MD5_CTX md5ctx = {0};

+	unsigned char hash[HASH_SIZE] = {0};

+	char token[HASH_HEX_SIZE] = {0};

+	char *js_data = NULL;

+	char exe_reason[200] = {0};

+	int exe_res = 0;

+	char *pro_list = NULL;

+	char appid[MAX_APPID_LEN] = {0};

+	char appsecret[MAX_APPID_LEN] = {0};

+	

+	sc_cfg_get("lpa_appid", appid, sizeof(appid));

+	sc_cfg_get("lpa_appsecret", appsecret, sizeof(appsecret));

+

+	lpa_get_time(time, sizeof(time));

+	lpa_get_transid(transid, sizeof(transid), g_imei);

+

+	lpa_MD5_Init(&md5ctx);

+	lpa_MD5_Update(&md5ctx, appid, strlen(appid));	

+	lpa_MD5_Update(&md5ctx, transid, strlen(transid));

+	lpa_MD5_Update(&md5ctx, time, strlen(time));

+	lpa_MD5_Update(&md5ctx, appsecret, strlen(appsecret));

+	lpa_MD5_Final(hash, &md5ctx);

+	//token lower case

+	bytes2string_lower(hash, token, sizeof(hash));

+

+	eid = GetEID();

+	if (eid == NULL) {

+		return NULL;

+	}

+	

+	exe_res = lpa_get_exeres(exe_reason, sizeof(exe_reason));

+	

+	getProfileList(&pro_list);

+

+	js_data = malloc(LPA_TRIGGER_DATA_LEN);

+	if (js_data != NULL) {

+		memset(js_data, 0, LPA_TRIGGER_DATA_LEN);

+		if (pro_list != NULL) {

+			snprintf(js_data, LPA_TRIGGER_DATA_LEN, trigger_https_updata, 

+				appid, time, transid, token, eid, g_imei, exe_res, exe_reason, pro_list);

+		}

+		else  {

+			snprintf(js_data, LPA_TRIGGER_DATA_LEN, trigger_https_updata, 

+				appid, time, transid, token, eid, g_imei, exe_res, exe_reason, "");

+		}

+		//printf("trigger json:-%s-\n", js_data);

+	}

+

+	if (pro_list != NULL)

+		free(pro_list);

+	free(eid);

+	return js_data;

+}

+

+static int lpa_get_profile_state(char *iccid)

+{

+    char *apdu = NULL;

+	char *state = NULL;

+	int status = 0;

+	

+	apdu = GetProfilesInfo(iccid);

+	if (apdu == NULL)

+		return -1;

+

+	

+	state = lpa_tag_apdu_from_atresp(apdu, 0x9F70);

+	if (state == NULL) {

+		free(apdu);

+		return -1;

+	}

+	errno = 0;

+	status = strtol(state, NULL, 16);

+	if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+	{

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+	free(state);

+	free(apdu);

+	return status;

+}

+

+//µ±Ç°iccidÊÇ·ñΪ¼¤»î״̬µÄprofile

+static int lpa_get_cur_iccid_state(void)

+{

+	char cur_iccid[ICCID_LEN+1] = {0};

+	

+	lpa_get_iccid(cur_iccid, sizeof(cur_iccid));

+	lpa_trans_iccid(cur_iccid, strlen(cur_iccid));

+	if (strlen(cur_iccid) == ICCID_LEN) {

+		return lpa_get_profile_state(cur_iccid);

+	}

+

+	return -1;

+}

+

+/***************************************************************/

+//

+//

+//

+/***************************************************************/

+static char *lpa_parse_trigger_resp(char *srcStr, int *next_step)

+{

+	cJSON *root = NULL;

+	cJSON *object = NULL;

+	cJSON *object2 = NULL;

+	cJSON *array = NULL;

+	char *accode_apdu = NULL;

+

+	root = cJSON_Parse(srcStr);

+	if (root == NULL) {

+		printf("root == NULL\n");

+		return NULL;

+	}

+

+	object = cJSON_GetObjectItem(root, "BODY");

+	if (object == NULL) {

+		printf("BODY not find\n");

+		cJSON_Delete(root);

+		return NULL;

+	}

+

+	object2 = cJSON_GetObjectItem(object, "NEXT_STEP");

+	if (object2 == NULL) {

+		printf("NEXT_STEP not find\n");

+		cJSON_Delete(root);

+		return NULL;

+	}

+	printf("NEXT_STEP:%d\n", object2->valueint);

+	*next_step = object2->valueint;

+	if (object2->valueint == 2 || object2->valueint == 3

+		|| object2->valueint == 4) {

+		object2 = cJSON_GetObjectItem(object, "ICCID");

+		if (object2 == NULL) {

+			printf("ICCID not find\n");

+			cJSON_Delete(root);

+			return NULL;

+		}

+		printf("ICCID:%s\n", object2->valuestring);

+

+		accode_apdu = malloc(APDU_RESP_LEN);

+		if (accode_apdu != NULL) {

+			memset(accode_apdu, 0, APDU_RESP_LEN);

+			strncpy(accode_apdu, object2->valuestring, APDU_RESP_LEN-1);

+			lpa_trans_iccid(accode_apdu, strlen(accode_apdu));

+			printf("ICCID-Trans:-%s-\n", accode_apdu);

+		}	

+	}

+	else if (object2->valueint == 1) {

+		object2 = cJSON_GetObjectItem(object, "COMMAND");

+		if (object2 == NULL) {

+			printf("COMMAND not find\n");

+			cJSON_Delete(root);

+			return NULL;

+		}

+		array = cJSON_GetArrayItem(object2, 0);

+		if (array == NULL) {

+			printf("COMMAND no item\n");

+			cJSON_Delete(root);

+			return NULL;

+		}

+		printf("COMMAND:%s\n", array->valuestring);

+

+		accode_apdu = malloc(APDU_RESP_LEN);

+		if (accode_apdu != NULL) {

+			memset(accode_apdu, 0, APDU_RESP_LEN);

+			strncpy(accode_apdu, array->valuestring, APDU_RESP_LEN-1);

+			printf("accode or apdu:-%s-\n", accode_apdu);

+		}

+	}

+	cJSON_Delete(root);

+	return accode_apdu;

+}

+

+static char *lpa_parse_updata_resp(char *srcStr)

+{

+	cJSON *root = NULL;

+	cJSON *object = NULL;

+	cJSON *object2 = NULL;

+	cJSON *array = NULL;

+	char *code = NULL;

+

+	root = cJSON_Parse(srcStr);

+	if (root == NULL) {

+		printf("root == NULL\n");

+		return NULL;

+	}

+

+	object = cJSON_GetObjectItem(root, "HEAD");

+	if (object == NULL) {

+		printf("HEAD not find\n");

+		cJSON_Delete(root);

+		return NULL;

+	}

+

+	object2 = cJSON_GetObjectItem(object, "CODE");

+	if (object2 == NULL) {

+		printf("CODE not find\n");

+		cJSON_Delete(root);

+		return NULL;

+	}

+	printf("CODE:%s\n", object2->valuestring);

+	

+	code = malloc(APDU_RESP_LEN);

+	if (code != NULL) {

+		memset(code, 0, APDU_RESP_LEN);

+		strncpy(code, object2->valuestring, APDU_RESP_LEN-1);

+	}

+	cJSON_Delete(root);

+	return code;

+}

+

+static void lpa_open_cfun(void)

+{

+	int cfun_stat = -1;

+	void *p2[] = {&cfun_stat};

+	

+	get_modem_info("AT+CFUN?\r\n", "%d", p2);

+	if (cfun_stat != 1) {

+		get_modem_info("AT+CFUN=0\r\n", NULL, NULL);

+		get_modem_info("AT+CFUN=1\r\n", NULL, NULL);

+		lpa_close_logical_channel(0);

+	}

+}

+

+//wifiʱ·ÀÖ¹ËÑÍøµÄsim¿¨²Ù×÷´ò¶Ïesim·Ö¶Îд¿¨

+static void lpa_close_cfun(void)

+{

+	char ps_wan[20] = {0};

+	char def_wan[20] = {0};

+	int cfun_stat = -1;

+	void *p2[] = {&cfun_stat};

+

+	sc_cfg_get("pswan", ps_wan, sizeof(ps_wan));

+	sc_cfg_get("default_wan_name", def_wan, sizeof(def_wan));

+	if (strncmp(def_wan, ps_wan, strlen(ps_wan)) != 0) {

+		get_modem_info("AT+CFUN?\r\n", "%d", p2);

+		if (cfun_stat == 1) {

+			get_modem_info("AT+CFUN=4\r\n", NULL, NULL);

+		}

+	}

+}

+

+static int lpa_exe_updata(void)

+{

+	int code = -1;

+	int i = 0;

+	char updata_retry[6] = {0};

+	int count = 0;

+//dtest

+#if 1

+	sc_cfg_get("lpa_updata_retry", updata_retry, sizeof(updata_retry));

+	count = atoi(updata_retry);

+	if (count <= 0 || count > 10) { //kw 3

+		count = 1;

+	}

+	

+	if (0 == lpa_check_status(60)) {

+		printf("lpa_exe_updata not ready\n");

+		return -1;

+	}

+

+	for (i = 0; i < count; i++) {

+		code = lpa_trigger_updata();

+		if (code == 0 || i == count-1)

+			break;

+		//retry

+		sleep(30);

+	}

+	

+	if (code != 0) {

+		printf("lpa_exe_updata updata fail\n");

+		return -1;

+	}

+#endif											

+	return 0;

+}

+//check sim && net && sntp ready

+int lpa_check_status(int retry)

+{

+	int i = 0;

+	int res = -1;

+

+	//+ZPBIC

+	for(i = 0; i < retry; i++) {	

+		char sntp_res[20] = {0};

+		sc_cfg_get("zpbic_pb", sntp_res, sizeof(sntp_res));

+		if (strcmp(sntp_res, "ready") == 0) {

+			res = 1;

+			break;

+		}

+		printf("lpa zpbic_pb: %s\n", sntp_res);

+		sleep(6);

+	}

+	if (res != 1) {

+		printf("lpa sim not ready\n");

+		return 0;

+	}

+

+	//net

+	res = -1;

+	for(i = 0; i < retry; i++) {

+		res = default_route_check();

+		if (res == 1)

+			break;

+		printf("lpa default_route_check: %d\n", res);

+		sleep(6);

+	}

+	if (res != 1) {

+		printf("lpa check net timeout\n");

+		return 0;

+	}

+

+	//sntp, no +zmmi

+	res = -1;

+	for(i = 0; i < retry; i++) {	

+		char sntp_res[20] = {0};

+		sc_cfg_get("sntp_process_result", sntp_res, sizeof(sntp_res));

+		if (strcmp(sntp_res, "success") == 0) {

+			res = 1;

+			break;

+		}

+		printf("lpa sntp_process_result: %s\n", sntp_res);

+		sleep(6);

+	}

+	if (res != 1) {

+		printf("lpa check sntp timeout\n");

+		return 0;

+	}

+

+	//open channel

+	res = -1;

+	for(i = 0; i < 4; i++) {	

+		res = lpa_open_logical_channel();

+		if (res == 0)

+			break;

+		printf("lpa lpa_open_logical_channel: %d\n", res);

+		sleep(2);

+	}

+	if (res != 0) {

+		printf("lpa open channel fail\n");

+		return 0;

+	}

+

+	////select app id

+	res = -1;

+	for(i = 0; i < 4; i++) {	

+		res = lpa_select_aid();

+		if (res == 0)

+			break;

+		printf("lpa lpa_select_aid: %d\n", res);

+		sleep(2);

+	}

+	if (res != 0) {

+		printf("lpa select fail\n");

+		return 0;

+	}

+	return 1;

+}

+

+//²éѯһЩ¹Ì¶¨²ÎÊý

+int lpa_init(void)

+{

+	//zpbic && sntp && net ok, if use wlan close modem, open channel select isdr

+	if (0 == lpa_check_status(60)) {

+		printf("lpa not ready\n");

+		return -1;

+	}

+

+	if(0 != lpa_get_imei(g_imei, sizeof(g_imei))) {

+		printf("lpa no imei\n");

+		return -1;

+	}

+

+	return 0;

+}

+int lpa_uninit(void)

+{

+	lpa_close_logical_channel(1);

+

+	return 0;

+}

+

+static char *lpa_tigger_session(char *path, char *req_data)

+{

+	int ret = -1;

+	int cont_len = 0;

+	https_context_t https_ct = {0};

+	char trigger_port[6] = {0};

+	char trigger_host[MAX_URL_LEN] = {0};

+	char *https_req = NULL;

+	char *https_resp = NULL;

+	int https_req_len = 0;

+	//kw 3

+	//if (https_req_len > TRIG_HTTP_MAX_LEN)

+	//	return NULL;

+	

+	sc_cfg_get("lpa_trigger_port", trigger_port, sizeof(trigger_port));

+	sc_cfg_get("lpa_trigger_host", trigger_host, sizeof(trigger_host));

+

+	SSL_library_init();

+	https_ct.port = atoi(trigger_port);

+	https_ct.host = trigger_host;

+	https_ct.path = path;

+	ret = https_init(&https_ct);

+	if (ret != 0) {

+		printf("[trigger] https_init fail\n");

+		return NULL;

+	}

+

+	https_req_len = strlen(trigger_https_req)+strlen(https_ct.path)+strlen(https_ct.host)+strlen(req_data)+32;

+	https_req = malloc(https_req_len);

+	if (https_req == NULL) {

+		https_uninit(&https_ct);

+		return NULL;

+	}

+	memset(https_req, 0, https_req_len);

+	ret = snprintf(https_req, https_req_len, trigger_https_req,

+		https_ct.path, https_ct.host, strlen(req_data), req_data);

+	

+	printf("[trigger] request##%s##\n", https_req);

+	ret = https_write(&https_ct, https_req, ret);

+	printf("[trigger] https_write ret = %d.\n", ret);

+

+	ret = https_get_status_code(&https_ct, &cont_len);

+	printf("[trigger] https_recv code = %d.\n", ret);

+	if(ret == 200 && (cont_len > 0 && cont_len < TRIG_HTTP_MAX_LEN))

+	{

+		https_resp = malloc(cont_len + 1);

+		if (https_resp == NULL) {

+			https_uninit(&https_ct);

+			free(https_req);

+			printf("[trigger] https_resp_cont NULL.\n");

+			return NULL;

+		}

+

+		memset(https_resp, 0, cont_len + 1);

+		ret = https_read_content(&https_ct, https_resp, cont_len);

+		if(cont_len == ret)

+		{

+			https_resp[ret] = '\0';	//×Ö·û´®½áÊø±êʶ

+			printf("[trigger] https_write https_resp_content = \n %s.\n", https_resp);

+		}

+	}

+	

+	https_uninit(&https_ct);

+	free(https_req);

+	return https_resp;

+}

+

+/***************************************************************/

+//

+//´Ó´¥·¢·þÎñÆ÷²éѯָÁî

+//

+/***************************************************************/

+char *lpa_trigger_event(int *next_step)

+{

+	char *trigger_data = NULL;

+	char *https_resp_cont = NULL;

+	char *command = NULL;

+	char trigger_event[MAX_URL_LEN] = {0};

+

+	trigger_data = lpa_get_trigger_data();

+	if (trigger_data == NULL) {

+		printf("[trigger] request data NULL.\n");

+		return NULL;

+	}

+

+	sc_cfg_get("lpa_trigger_event_url", trigger_event, sizeof(trigger_event));

+	https_resp_cont = lpa_tigger_session(trigger_event, trigger_data);

+	if (https_resp_cont != NULL) {

+		command = lpa_parse_trigger_resp(https_resp_cont, next_step);

+		free(https_resp_cont);

+	}

+	

+	free(trigger_data);

+	return command;

+}

+

+/***************************************************************/

+//

+//Ïò´¥·¢·þÎñÆ÷Éϱ¨Êý¾Ý

+//

+/***************************************************************/

+int lpa_trigger_updata(void)

+{

+	char *trigger_data = NULL;

+	char *https_resp_cont = NULL;

+	char *code = NULL;

+	int res_code = -1;

+	char trigger_updata[MAX_URL_LEN] = {0};

+

+	trigger_data = lpa_get_updata_data();

+	if (trigger_data == NULL) {

+		printf("[trigger] request data NULL.\n");

+		return NULL;

+	}

+	

+	sc_cfg_get("lpa_trigger_updata_url", trigger_updata, sizeof(trigger_updata));

+	https_resp_cont = lpa_tigger_session(trigger_updata, trigger_data);

+	if (https_resp_cont != NULL) {

+		code = lpa_parse_updata_resp(https_resp_cont);

+		if (code != NULL) {

+			errno = 0;

+			res_code = strtol(code, NULL, 10);

+			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+			{

+				printf("strtol errno %d: %s\n", errno, strerror(errno));

+			}

+			free(code);

+		}

+		free(https_resp_cont);

+	}

+	

+	free(trigger_data);

+	return res_code;

+}

+

+//µôµçµÈ³¡¾°£¬Èç´æÔÚiccid¼¤»î²¢Éϱ¨£¬²»´æÔÚÖ±½Ó×ßevent£¬ÖØÐ´¥·¢ÏÂÔØµÈ²Ù×÷

+int lpa_exception_process(void)

+{

+	char has_iccid[ICCID_LEN+1] = {0};

+	int status = 0;

+	int res = 0;

+	

+	sc_cfg_get("lpa_bpp_iccid", has_iccid, sizeof(has_iccid));

+	if (strlen(has_iccid) == ICCID_LEN) {

+		status = lpa_get_profile_state(has_iccid);

+		if (status == 1 || status == 0) {

+			res = lpa_enable_profile(has_iccid);

+			if (res == 0) {

+				sc_cfg_set("lpa_bpp_iccid", "");

+				sc_cfg_save();

+				return 0;

+			}

+			return -1;

+		}

+	}

+

+	return 0;

+}

+

+int lpa_download_profile(char *activecode, char *confirmcode)

+{

+	int res = -1;

+

+	lpa_close_cfun();

+

+	memset(curent_iccid, 0, sizeof(curent_iccid));

+	res = downloadProfileByAc(activecode, confirmcode);

+

+	//²»¹Ü³É¹¦Óë·ñ£¬¶¼ÒªÉϱ¨

+	res = lpa_enable_profile(curent_iccid);

+	if (res == 0) {

+		sc_cfg_set("lpa_bpp_iccid", "");

+		sc_cfg_save();

+	}

+

+	lpa_open_cfun();

+	

+	return res;

+}

+

+int lpa_enable_profile(char *iccid)

+{

+	int res = 0;

+	int code = 0;

+	

+	res = enableProfile(iccid);

+	if (res == 0) {

+		sc_cfg_set("zpbic_pb", "");//wait sim ready

+		sc_cfg_set("lpa_last_res", "success");

+		lpa_close_logical_channel(0);

+		sleep(2);

+	}

+	else if (res == 2) {

+		sc_cfg_set("lpa_last_res", "success");

+	}

+	else {

+		sc_cfg_set("lpa_last_res", "fail");

+	}

+

+	code = lpa_exe_updata();

+ 	if (code != 0) {

+		printf("lpa_enable_profile updata fail\n");

+		return -1;

+	}

+ 	return 0;

+}

+

+int lpa_disable_profile(char *iccid)

+{

+	int res = 0;

+	int code = 0;

+	

+	res = disableProfile(iccid);

+	if (res == 0) {

+		sc_cfg_set("zpbic_pb", "");//wait sim ready

+		sc_cfg_set("lpa_last_res", "success");

+		lpa_close_logical_channel(0);

+		sleep(2);

+	}

+	else if (res == 2) {

+		sc_cfg_set("lpa_last_res", "success");

+	}

+	else {

+		sc_cfg_set("lpa_last_res", "fail");

+	}

+	

+	code = lpa_exe_updata();

+ 	if (code != 0) {

+		printf("lpa_disable_profile updata fail\n");

+		return -1;

+	}

+ 	return 0;

+}

+

+int lpa_delete_profile(char *iccid)

+{

+	int res = 0;

+	int code = 0;

+	

+	res = deleteProfile(iccid);

+	if (res == 0) {

+		sc_cfg_set("lpa_last_res", "success");

+		sleep(2);

+	}

+	else if (res == 1) {

+		sc_cfg_set("lpa_last_res", "success");

+	}

+	else {

+		sc_cfg_set("lpa_last_res", "fail");

+	}

+	

+	code = lpa_exe_updata();

+ 	if (code != 0) {

+		printf("lpa_disable_profile updata fail\n");

+		return -1;

+	}

+ 	return 0;

+}

+

+int lpa_memory_reset(void)

+{

+	int res = 0;

+	int state = 0;

+	int code = 0;

+

+	state = lpa_get_cur_iccid_state();

+	res = memoryReset();

+	if (res == 0) {

+		if(state == 1) {

+			sc_cfg_set("zpbic_pb", "");//wait sim ready

+			lpa_close_logical_channel(0);

+			printf("lpa zpbic_pb reset\n");

+		}

+		sc_cfg_set("lpa_last_res", "success");

+		sleep(2);//wait sim ready

+	}

+	else if (res == 1) {

+		sc_cfg_set("lpa_last_res", "success");

+	}

+	else {

+		sc_cfg_set("lpa_last_res", "fail");

+	}

+	

+	code = lpa_exe_updata();

+ 	if (code != 0) {

+		printf("lpa_disable_profile updata fail\n");

+		return -1;

+	}

+ 	return 0;

+}

+

+int lpa_open_logical_channel(void)

+{

+    char *apdu = NULL;

+	int chan = 0;

+	if (g_open_channel_flag == 0) {

+		apdu = OpenLogicalChannel();

+		if (apdu == NULL)

+			return -1;

+		errno = 0;

+		chan = strtol(apdu, NULL, 16);

+		if (errno == ERANGE)// kw ERRNO.NOT_CHECKED

+		{

+			printf("strtol errno %d: %s\n", errno, strerror(errno));

+		}

+		free(apdu);

+		if (chan < 0 || chan > 3)

+			return -1;

+		g_open_channel_flag = 1;

+		g_chan_id = chan;

+	} 

+	return 0;

+}

+//flag = 0, when refresh not need close

+int lpa_close_logical_channel(int flag)

+{

+    char *apdu = NULL;

+	int res = 0;

+	if (flag == 1 && g_open_channel_flag == 1) {

+		res = CloseLogicalChannel(g_chan_id);

+		printf("lpa_close_logical_channel:%d, res:%d\n", g_chan_id, res);

+	}

+	g_chan_id = 0;

+	g_open_channel_flag = 0;

+	

+	return res;

+}

+

diff --git a/ap/lib/liblpa/md5.c b/ap/lib/liblpa/md5.c
new file mode 100755
index 0000000..da96c3a
--- /dev/null
+++ b/ap/lib/liblpa/md5.c
@@ -0,0 +1,307 @@
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines                         **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+#include <string.h>
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ **  Message-digest routines:                                         **
+ **  To form the message digest for a message M                       **
+ **    (1) Initialize a context buffer mdContext using MD5_Init       **
+ **    (2) Call MD5_Update on mdContext and M                         **
+ **    (3) Call MD5_Final on mdContext                                **
+ **  The message digest is now in mdContext->digest[0...15]           **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform (UINT4 *buf, UINT4 *in);
+
+static unsigned char PADDING[64] = {
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+  {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) \
+  {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) \
+  {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) \
+  {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+
+#ifdef __STDC__
+#define UL(x)	x##U
+#else
+#define UL(x)	x
+#endif
+
+/* The routine MD5_Init initializes the message-digest context
+   mdContext. All fields are set to zero.
+ */
+void lpa_MD5_Init (mdContext)
+lpa_MD5_CTX *mdContext;
+{
+  mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+  /* Load magic initialization constants.
+   */
+  mdContext->buf[0] = (UINT4)0x67452301;
+  mdContext->buf[1] = (UINT4)0xefcdab89;
+  mdContext->buf[2] = (UINT4)0x98badcfe;
+  mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+   account for the presence of each of the characters inBuf[0..inLen-1]
+   in the message whose digest is being computed.
+ */
+void lpa_MD5_Update (mdContext, inBuf, inLen)
+lpa_MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+  UINT4 in[16];
+  int mdi;
+  unsigned int i, ii;
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* update number of bits */
+  if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+    mdContext->i[1]++;
+  mdContext->i[0] += ((UINT4)inLen << 3);
+  mdContext->i[1] += ((UINT4)inLen >> 29);
+
+  while (inLen--) {
+    /* add new character to buffer, increment mdi */
+    mdContext->in[mdi++] = *inBuf++;
+
+    /* transform if necessary */
+    if (mdi == 0x40) {
+      for (i = 0, ii = 0; i < 16; i++, ii += 4)
+        in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+                (((UINT4)mdContext->in[ii+2]) << 16) |
+                (((UINT4)mdContext->in[ii+1]) << 8) |
+                ((UINT4)mdContext->in[ii]);
+      Transform (mdContext->buf, in);
+      mdi = 0;
+    }
+  }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+   ends with the desired message digest in mdContext->digest[0...15].
+ */
+void lpa_MD5_Final (hash, mdContext)
+unsigned char hash[];
+lpa_MD5_CTX *mdContext;
+{
+  UINT4 in[16];
+  int mdi;
+  unsigned int i, ii;
+  unsigned int padLen;
+
+  /* save number of bits */
+  in[14] = mdContext->i[0];
+  in[15] = mdContext->i[1];
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+  /* pad out to 56 mod 64 */
+  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+  lpa_MD5_Update (mdContext, PADDING, padLen);
+
+  /* append length in bits and transform */
+  for (i = 0, ii = 0; i < 14; i++, ii += 4)
+    in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+            (((UINT4)mdContext->in[ii+2]) << 16) |
+            (((UINT4)mdContext->in[ii+1]) << 8) |
+            ((UINT4)mdContext->in[ii]);
+  Transform (mdContext->buf, in);
+
+  /* store buffer in digest */
+  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+    mdContext->digest[ii+1] =
+      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+    mdContext->digest[ii+2] =
+      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+    mdContext->digest[ii+3] =
+      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+  }
+  memcpy(hash, mdContext->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+  /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+  FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+  FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+  FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+  FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+  FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+  FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+  FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+  FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+  FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+  FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+  FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+  FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+  FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+  FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+  FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+  FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+  /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+  GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+  GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+  GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+  GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+  GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+  GG ( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
+  GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+  GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+  GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+  GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+  GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+  GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+  GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+  GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+  GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+  GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+  /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+  HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+  HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+  HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+  HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+  HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+  HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+  HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+  HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+  HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+  HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+  HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+  HH ( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
+  HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+  HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+  HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+  HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+  /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+  II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+  II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+  II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+  II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+  II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+  II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+  II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+  II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+  II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+  II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+  II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+  II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+  II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+  II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+  II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+  II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c                                                      **
+ ******************************** (cut) ********************************
+ */
diff --git a/ap/lib/liblpa/md5.h b/ap/lib/liblpa/md5.h
new file mode 100755
index 0000000..b231d34
--- /dev/null
+++ b/ap/lib/liblpa/md5.h
@@ -0,0 +1,65 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5                    **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
+ ** Created: 2/17/90 RLR                                              **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version               **
+ ** Revised (for MD5): RLR 4/27/91                                    **
+ **   -- G modified to have y&~z instead of y&z                       **
+ **   -- FF, GG, HH modified to add in last register done             **
+ **   -- Access pattern: round 2 works mod 5, round 3 works mod 3     **
+ **   -- distinct additive constant for each step                     **
+ **   -- round 4 added, working mod 7                                 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
+ **                                                                   **
+ ** License to copy and use this software is granted provided that    **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
+ ** Digest Algorithm" in all material mentioning or referencing this  **
+ ** software or this function.                                        **
+ **                                                                   **
+ ** License is also granted to make and use derivative works          **
+ ** provided that such works are identified as "derived from the RSA  **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
+ ** material mentioning or referencing the derived work.              **
+ **                                                                   **
+ ** RSA Data Security, Inc. makes no representations concerning       **
+ ** either the merchantability of this software or the suitability    **
+ ** of this software for any particular purpose.  It is provided "as  **
+ ** is" without express or implied warranty of any kind.              **
+ **                                                                   **
+ ** These notices must be retained in any copies of any part of this  **
+ ** documentation and/or software.                                    **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+/* typedef a 32-bit type */
+#ifdef _LP64
+typedef unsigned int UINT4;
+typedef int          INT4;
+#else
+typedef unsigned long UINT4;
+typedef long          INT4;
+#endif
+#define _UINT4_T
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+  UINT4 i[2];                   /* number of _bits_ handled mod 2^64 */
+  UINT4 buf[4];                                    /* scratch buffer */
+  unsigned char in[64];                              /* input buffer */
+  unsigned char digest[16];     /* actual digest after MD5Final call */
+} lpa_MD5_CTX;
+
+void lpa_MD5_Init (lpa_MD5_CTX *mdContext);
+void lpa_MD5_Update (lpa_MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen);
+void lpa_MD5_Final (unsigned char hash[], lpa_MD5_CTX *mdContext);
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */