/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <drmcommon.h>
#include <drmutilities.h>
#include <drmcrt.h>
#include <drmcontextsizes.h>
#include <drmxmlbuilder.h>
#include <drmblackbox.h>
#include <oemimpl.h>
#include <drmbase64.h>
#include <drmpkcrypto.h>
#include "tResponsegen.h"
#include "SetClientID.h"
#include "tOEMIMP.h"

#ifdef SIXTEEN_BIT_ADDRESSING
/*defining this function as it is not available on TI 16-bit platform*/
int  wcstombs (char *destination,DRM_WCHAR *source,int  length);
#endif


DRM_RESULT TestResponseInit(IN _XMBContext *pbContext, IN DRM_DWORD cbContext)
{
	DRM_RESULT dr = DRM_SUCCESS;
	ChkDR(DRM_XMB_CreateDocument(cbContext, pbContext, &g_dstrLicenseRespTag));

ErrorExit:
	return dr;
}

DRM_RESULT TestResponseAddNode(IN _XMBContext *pbContext, 
							IN const DRM_CONST_STRING *pwszNodeName,
							IN const DRM_CONST_STRING *pwszAttrName,
							IN const DRM_CONST_STRING *pwszAttrValue,
							IN const DRM_BYTE *pbData,
							IN const DRM_DWORD cbData)
{
	DRM_RESULT dr;
	DRM_CONST_STRING wszEncoded = {0};

	/*encode data*/
    dr=DRM_B64_EncodeW(pbData, cbData, NULL, &wszEncoded.cchString, 0);
	if(dr!=DRM_E_BUFFERTOOSMALL){
		ChkDR(dr);
	}
	ChkMem(wszEncoded.pwszString = (DRM_WCHAR*)OEM_malloc(wszEncoded.cchString * SIZEOF(DRM_WCHAR)));

	ChkDR(DRM_B64_EncodeW(pbData, cbData, (DRM_WCHAR*)wszEncoded.pwszString, &wszEncoded.cchString, 0));

	/*wrap the data*/
	ChkDR(DRM_XMB_OpenNode(pbContext, pwszNodeName));
	if (pwszAttrName && pwszAttrName->pwszString) {
		ChkDR(DRM_XMB_AddAttribute(pbContext, pwszAttrName, pwszAttrValue));
	}
    ChkDR(DRM_XMB_AddData(pbContext, &wszEncoded));
    ChkDR(DRM_XMB_CloseCurrNode(pbContext, NULL));

ErrorExit:
	OEM_free((DRM_WCHAR*)wszEncoded.pwszString);
	return dr;
}

DRM_RESULT TestResponseAddLicense(IN _XMBContext *pbContext, IN DRM_CONST_STRING *pwszLicense)
{
	DRM_RESULT dr;
	DRM_DWORD dwSize=0;
	DRM_BYTE *pbEncryptedBuff=NULL; 
	DRM_CRYPTO_CONTEXT *pCryptoContext = NULL;

	ChkMem(pCryptoContext = (DRM_CRYPTO_CONTEXT*)OEM_malloc(SIZEOF(DRM_CRYPTO_CONTEXT)));

	/* Encrypt the license with the blackbox public key */
	dwSize = pwszLicense->cchString * SIZEOF(DRM_WCHAR);
	
	ChkMem(pbEncryptedBuff = (DRM_BYTE*)OEM_malloc(dwSize + PK_ENC_CIPHERTEXT_LEN));
	ChkDR(DRM_PK_EncryptLarge(&(g_ClientID.pk.pk.pk), (DRM_BYTE*)(pwszLicense->pwszString),
        dwSize, pbEncryptedBuff, DRMCIPHERKEYLEN, pCryptoContext));
	 
 	dwSize += PK_ENC_CIPHERTEXT_LEN;

	ChkDR(TestResponseAddNode(pbContext, &g_dstrLicense, &g_dstrAttributeVersion, &g_dstrLicVerAttrValue, pbEncryptedBuff, dwSize));

ErrorExit:
	SAFE_OEM_FREE(pbEncryptedBuff);
	SAFE_OEM_FREE(pCryptoContext);
	return dr;
}

#if DRM_SUPPORT_REVOCATION
DRM_RESULT TestResponseAddRevocationInfo(IN  _XMBContext *pbContext, IN  DRM_CONST_STRING *pwszRevocationInfo)
{
	DRM_RESULT dr = DRM_SUCCESS;

	ChkDR(DRM_XMB_OpenNode(pbContext, &g_dstrTagRevocationInfo));
	ChkDR(DRM_XMB_AddData(pbContext, pwszRevocationInfo));
	ChkDR(DRM_XMB_CloseCurrNode(pbContext, NULL));

ErrorExit:
	return dr;
}

DRM_RESULT TestResponseAddRevocation(IN  _XMBContext *pbContext, IN  DRM_CONST_STRING *pwszGUID, IN  DRM_CONST_STRING *pwszRevocation)
{
	DRM_RESULT dr = DRM_SUCCESS;

	ChkDR(DRM_XMB_OpenNode(pbContext, &g_dstrTagRevocation));
	ChkDR(DRM_XMB_AddAttribute(pbContext, &g_dstrAttributeType, pwszGUID));
	ChkDR(DRM_XMB_AddData(pbContext, pwszRevocation));
	ChkDR(DRM_XMB_CloseCurrNode(pbContext, NULL));

ErrorExit:
	return dr;
}
#endif /* DRM_SUPPORT_REVOCATION */

/*The caller is responsible to SAFE_OEM_FREE ppbResponse*/
DRM_RESULT TestResponseGetResponse(IN _XMBContext *pbContext, OUT DRM_BYTE **ppbResponse, OUT DRM_DWORD *pcbResponse)
{
 	DRM_RESULT dr = DRM_SUCCESS;
	DRM_STRING pwszString;
	DRM_DWORD cbResponse;
	
	ChkArg(ppbResponse);
	ChkDR(DRM_XMB_CloseDocument(pbContext,&pwszString));
	cbResponse = 1 + (DRM_DWORD)OEM_wcstombs(NULL,pwszString.pwszString,pwszString.cchString);
	ChkMem(*ppbResponse = OEM_malloc(cbResponse));

	/*convert wide char to ansi*/
	DRM_UTL_DemoteUNICODEtoANSI((const DRM_WCHAR *)pwszString.pwszString,(DRM_CHAR*)*ppbResponse,pwszString.cchString);

	
	if (pcbResponse)
		*pcbResponse = cbResponse;
ErrorExit:
	return dr;
}
  
#ifdef SIXTEEN_BIT_ADDRESSING
/*
//------------------------------------------------------------------------------
// Name: wcstombs
// Desc:This function is implemented here since it is not available on TI 16-bit platform. The
//implementation is specific to its use. it converts wide char to native multi byte represenation
//Parameters:
//	source        wide char source string
//    destination  char string
//    length         number of input elements to be converted
//
//Return Val : returns the number of elements converted. 
// Copyright (c) 1999-2000, Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------*/

int wcstombs (char *destination,DRM_WCHAR *source,int  length){

	DRM_WCHAR buffer[2] = {0};
	int returnval=0;

	if(source == NULL)
		return (-1);

	/*We have to do the conversion only if destination is not NULL, else we just get the memory required*/
	if(destination !=NULL)
	{
		while(*source != NULL && length > 0)
		{
			buffer[0] = *source;
			*destination = buffer[0] >> 8;
				
			destination++;
			source++;
			length--;
			returnval++;
		}
		*destination = NULL; /*terminate the string with a NULL*/
	}
	else
	{
		while(*source !=NULL && length > 0)
		{
			source++;
			returnval++;
			length--;
		}
	}
	
	
	return (returnval);
}
#endif
