#include<stdio.h>
#include<stdlib.h>
#include "com_example_demoactivity_BookActivity.h"
#include <Library/UniMate_Android.h>
#include <openssl/x509.h>

/*
 * Class:     com_example_demoactivity_BookActivity
 * Method:    getCertInfor
 * Signature: ([I[J[B[B[B[B[B[B[B[B)J
 */
JNIEXPORT jlong JNICALL Java_com_example_demoactivity_BookActivity_getCertInfor
  (JNIEnv *env, jclass cls, jintArray jcertCount, jlongArray jcertLen, 
	jbyteArray jcert1, jbyteArray jIssuedBy1, jbyteArray jIssuedTo1, jbyteArray jExpiration1,
	jbyteArray jcert2, jbyteArray jIssuedBy2, jbyteArray jIssuedTo2, jbyteArray jExpiration2,
	jintArray jIssuedByLen, jintArray jIssuedToLen, jintArray jExpirationLen)
{
	jboolean result;
	int* certCount;
	long* certLen;
	unsigned char* cert1, *cert2;
	int i, ret;

	int ipCertificates;
	ret = GetX509Certificates(&ipCertificates, NULL, NULL);
	if (ret != 0)
	{
		//DB_ERROR("JNI:GetX509Cert count failed!");
		env->ReleaseIntArrayElements(jcertCount, (jint*)certCount, 0);
		return ret;
	}

	certCount = env->GetIntArrayElements(jcertCount, &result);
	certCount[0] = ipCertificates;
	env->ReleaseIntArrayElements(jcertCount, (jint*)certCount, 0);

	if (ipCertificates <= 0) 
	{
		//DB_WARNING("JNI:no cert!");
		return 0;
	}

	long* lppCertificateLen = (long*)malloc(ipCertificates*sizeof(long));
	ret = GetX509Certificates(&ipCertificates, lppCertificateLen, NULL);
	if (ret != 0)
	{
		//DB_ERROR("JNI:GetX509Cert length failed!");
		return ret;
	}

	certLen = (long*)env->GetLongArrayElements(jcertLen, &result);
	for (i=0; i<ipCertificates; ++i)
	{
		certLen[i] = lppCertificateLen[i];
	}
	env->ReleaseLongArrayElements(jcertLen, (jlong*)certLen, 0);


	pbyte* ppCertificates = (pbyte*)malloc(ipCertificates*sizeof(pbyte));
	for (i=0; i<ipCertificates; ++i)
	{
		ppCertificates[i] = (pbyte)malloc(lppCertificateLen[i]);
	}
	ret = GetX509Certificates(&ipCertificates, lppCertificateLen, ppCertificates);
	if (ret != 0)
	{
		//DB_ERROR("JNI:GetX509Certificates failed!");
		return ret;
	}

	

	cert1=(unsigned char *)env->GetByteArrayElements(jcert1, &result);
	memcpy(cert1, ppCertificates[0], lppCertificateLen[0]);
	env->ReleaseByteArrayElements(jcert1, (jbyte*)cert1, 0);

	
	unsigned char *Issued_By, *Issued_To, *Expiration_Date;
	unsigned int *Issued_By_Len, *Issued_To_Len, *Expiration_Date_Len;

	unsigned char cbuf[3000];
	unsigned long clen = 0;
	const unsigned char *lpcbuf = cbuf;
	unsigned char issuer_name_char[100] = {0};
	unsigned char *lpissuer_name_char = issuer_name_char;
	unsigned char subject_name_char[100] = {0};
	unsigned char *lpsubject_name_char = subject_name_char;
	unsigned char notBefore_char[100] = {0};
	unsigned char issuerbuf[100]={0};
	unsigned char subjectbuf[100]={0};
	unsigned char timebuf[100]={0};
	int entriesNum;
	int len;
	unsigned char name_num = 0;

	Issued_By_Len=(unsigned int *)env->GetIntArrayElements(jIssuedByLen, &result);
	Issued_To_Len=(unsigned int *)env->GetIntArrayElements(jIssuedToLen, &result);
	Expiration_Date_Len=(unsigned int *)env->GetIntArrayElements(jExpirationLen, &result);
	
	//---------------------------cert 1------------------------------------

	Issued_By=(unsigned char *)env->GetByteArrayElements(jIssuedBy1, &result);
	Issued_To=(unsigned char *)env->GetByteArrayElements(jIssuedTo1, &result);
	Expiration_Date=(unsigned char *)env->GetByteArrayElements(jExpiration1, &result);


	memcpy(cbuf, ppCertificates[0], lppCertificateLen[0]);
	clen = lppCertificateLen[0];
	//DB_TRACE("GetX509Certificates : success. length=%d", clen);

	X509* userCert = NULL;
	X509* x = d2i_X509(NULL, &lpcbuf, clen);
	if (NULL == x)
	{
		//DB_ERROR("JNI:d2i_X509 cert1 failed!");
		return 1;
	}
	
	X509_NAME* issuer_name;
	issuer_name = X509_get_issuer_name(x);
	entriesNum = sk_X509_NAME_ENTRY_num(issuer_name->entries);
	for (i=0;i<entriesNum;i++)
	{
		X509_NAME_ENTRY* name_entry = sk_X509_NAME_ENTRY_value(issuer_name->entries,i);
		int Nid = OBJ_obj2nid(name_entry->object);
		if (Nid==NID_commonName)
		{
			lpissuer_name_char = NULL;
			if((len = ASN1_STRING_to_UTF8(&lpissuer_name_char,name_entry->value))<0)
				continue;
			if (name_num==0)
			{
				name_num++;
			}
			else
			{
				strcat((char*)issuerbuf, " ");
			}

			strcat((char*)issuerbuf, (char*)lpissuer_name_char);
			
		}
	}

	name_num = 0;
	X509_NAME *	subject_name = X509_get_subject_name(x);
	entriesNum = sk_X509_NAME_ENTRY_num(subject_name->entries);
	for (i=0;i<entriesNum;i++)
	{
		X509_NAME_ENTRY* name_entry = sk_X509_NAME_ENTRY_value(subject_name->entries,i);
		int Nid = OBJ_obj2nid(name_entry->object);
		if (Nid==NID_commonName)
		{
			lpsubject_name_char = NULL;
			if((len = ASN1_STRING_to_UTF8(&lpsubject_name_char,name_entry->value))<0)
				continue;
			if (name_num==0)
			{
				name_num++;
			}
			else
			{
				strcat((char*)subjectbuf, " ");
			}
			strcat((char*)subjectbuf, (char*)lpsubject_name_char);
			
		}
	}

	ASN1_TIME * notAfter = X509_get_notAfter(x);

	unsigned char time[64] = {0};
	unsigned char* lptime = time;
	ASN1_GENERALIZEDTIME* gen_time = 0;

	ASN1_STRING_to_UTF8(&lptime, notAfter);

	sprintf((char*)timebuf, "20%c%c-%c%c-%c%c\0",
			lptime[0], lptime[1], lptime[2], lptime[3], lptime[4],
			lptime[5]);

	Issued_By_Len[0] = strlen((char*)issuerbuf);
	Issued_To_Len[0] = strlen((char*)subjectbuf);
	Expiration_Date_Len[0] = strlen((char*)timebuf);

	memcpy(Issued_By, issuerbuf, Issued_By_Len[0]+1);
	memcpy(Issued_To, subjectbuf, Issued_To_Len[0]+1);
	memcpy(Expiration_Date, timebuf, Expiration_Date_Len[0]+1);

	//DB_WARNING("JNI: cert 1: Issued_By = %s, Issued_To = %s, Expiration_Date = %s", Issued_By, Issued_To, Expiration_Date);

	env->ReleaseByteArrayElements(jIssuedBy1, (jbyte*)Issued_By, 0);
	env->ReleaseByteArrayElements(jIssuedTo1, (jbyte*)Issued_To, 0);
	env->ReleaseByteArrayElements(jExpiration1, (jbyte*)Expiration_Date, 0);

	env->ReleaseIntArrayElements(jIssuedByLen, (jint*)Issued_By_Len, 0);
	env->ReleaseIntArrayElements(jIssuedToLen, (jint*)Issued_To_Len, 0);
	env->ReleaseIntArrayElements(jExpirationLen, (jint*)Expiration_Date_Len, 0);


	return 0;
}
