⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcbertlv.cpp

📁 ASN.1解析解码工具,可以解析各种ASN.1格式的文件,并对相应的BER文件解码
💻 CPP
字号:
/****************************************************************************************
* Copyrights  2006,深圳天源迪科信息技术股份有限公司
*
* All rights reserved.
*
* Filename:	DCBerTlv.h		
* Indentifier:		
* Description:	
* Version:		V1.0
* Author:		wangbin
* Finished:	2007年6月18日
* History:
******************************************************************************************/
#include "dicasnutil/DCBerTlv.h"
#include "dicasnutil/DCAsnParser.h"

namespace dicasn1p
{

DCBerTlv::DCBerTlv(size_t buf_len,size_t max_len)
{
	m_read_len = 0;
	m_buf_len = buf_len;
	m_max_len = max_len;
	m_buf = (char*)malloc(m_buf_len);
	m_status = none;
	value = NULL;
	reference = NULL;
}

DCBerTlv::~DCBerTlv()
{
	release();
	if(m_buf)
	{
		free(m_buf);
		m_buf = NULL;
	}
}

ssize_t DCBerTlv::fromBuffer( const void* bufptr,size_t buflen )
{
	const char *databuf = (char*)bufptr;
	ssize_t nRet = 0;
	ssize_t lastused = 0;
	ber_tlv_tag_t tag;
	ber_tlv_len_t len;
	do 
	{
		if(none == m_status)
		{
			release();
			lastused = ber_fetch_tag(databuf,buflen,&tag);
			if (0 == lastused)
			{
				save(databuf,buflen);
				break;
			}
			else if (0 > lastused)
			{
				nRet = -1;
				break;
			}
			else
			{
				this->constructed = BER_TLV_CONSTRUCTED(databuf);
				this->tag_class = (enum asn_tag_class)BER_TAG_CLASS(tag);
				this->tag = BER_TAG_VALUE(tag);
				databuf += lastused;
				buflen -= lastused;
				clear();
				m_status = read_len;
			}
		}
		if(read_tag == m_status)
		{
			size_t reallen = save(databuf,buflen);
			lastused = ber_fetch_tag(m_buf,m_read_len ,&tag);
			if(0 == lastused)
			{
				break;
			}
			else if (0 > lastused)
			{
				nRet = -1;
				break;
			}
			else
			{
				this->constructed = BER_TLV_CONSTRUCTED(m_buf);
				this->tag_class = (enum asn_tag_class)BER_TAG_CLASS(tag);
				this->tag = BER_TAG_VALUE(tag);
				databuf += lastused + reallen - m_read_len ;
				buflen -= lastused + reallen - m_read_len ;
				clear();
				m_status = read_len;
			}
		}
		if(read_len == m_status)
		{
			size_t reallen = 0;
			if(0 == m_read_len)
			{
				lastused = ber_fetch_length(this->constructed,databuf,buflen,&len);
				if(0 == lastused)
				{
					reallen = save(databuf,buflen);
				}
			}
			else
			{
				reallen = save(databuf,buflen);
				lastused = ber_fetch_length(this->constructed,m_buf,m_read_len,&len);
			}
			if(0 == lastused)
			{
				break;
			}
			else if (0 > lastused)
			{
				nRet = -1;
				break;
			}
			else
			{
				databuf += lastused + reallen - m_read_len ;
				buflen -= lastused + reallen - m_read_len ;
				clear();
				this->length = len;
				m_status = read_value;
			}
		}
		if (read_value == m_status)
		{
			size_t reallen = DICASN_MIN(buflen,this->length - m_read_len);
			if (0 == m_read_len )
			{
				value = (char*)malloc(this->length);
			}
			memcpy(value+m_read_len,databuf,reallen);
			m_read_len += reallen;
			if(this->length == m_read_len)
			{
				finish();
				nRet = databuf - (char*)bufptr + reallen;
			}
		}
	} while(0);
	return nRet;
}

void DCBerTlv::release()
{
	if(value)
		free(value);
	value = NULL;
	m_read_len = 0;
}

size_t DCBerTlv::save( const char* bufptr,size_t buflen )
{
	size_t reallen = DICASN_MIN(buflen,m_buf_len-m_read_len);
	memcpy(m_buf + m_read_len,bufptr,reallen);
	m_read_len += reallen;
//	printf("save:[%X]\n",*(unsigned char*)bufptr);
	return reallen;
}

void DCBerTlv::finish()
{
	m_status = none;
	clear();
}

void DCBerTlv::clear()
{
	m_read_len = 0;
}

const char * DCBerTlv::getTagInfo()
{
	m_sRetValue[0] = 0;
	char tmp[64];
	switch(tag_class)
	{
	case ASN_TAG_CLASS_UNIVERSAL:
		get_universal_tag_name(tmp,64,tag);
		asn1p_expr_snprintf(m_sRetValue,DICASN1P_DCBerTlv_RETURN_BUFFER_LEN,"universal:[%s]", tmp);
		break;
	case ASN_TAG_CLASS_CONTEXT:
		if (reference && reference->Identifier)
		{
			asn1p_expr_snprintf(m_sRetValue,DICASN1P_DCBerTlv_RETURN_BUFFER_LEN,"ref:[%s]",reference->Identifier);
		}
		else
		{
			strcpy(m_sRetValue,"ASN_TAG_CLASS_CONTEXT");
		}
		break;
	}
//	ber_tlv_tag_snprint(BER_TAG_ORIGINAL(tag_class,tag),m_sRetValue,RETURN_BUFFER_LEN);
	return m_sRetValue;
}
/*------------------------------------------------------------------------------------------------*/

ssize_t buffer_to_tlv_tree( const void* bufptr,size_t buflen,DCTreeNode<DCBerTlv> **pRoot )
{
	DCBerTlv *tlv;
	DCTreeNode<DCBerTlv> * root = *pRoot;
	if (!root)
	{
		tlv = new DCBerTlv();
		root = new DCTreeNode<DCBerTlv>(tlv);
		*pRoot = root;
	}
	else
	{
		tlv = root->data;
	}
	ssize_t nRet = tlv->fromBuffer(bufptr,buflen);
	if(nRet > 0)
	{
		if (tlv->constructed)
		{
			size_t used = 0,lastused = 0,length = tlv->length;
			do 
			{
				DCBerTlv *childTlv;
				DCTreeNode<DCBerTlv> *child;
				childTlv = new DCBerTlv();
				child = root->addChild(childTlv);
				lastused = buffer_to_tlv_tree(tlv->value + used,tlv->length - used,&child);
				if(lastused <0)
				{
					nRet = -1;
					break;
				}
				used += lastused;
			} while(used < length);
		}
	}
	return nRet;
}

void tlv_tree_free( DCTreeNode<DCBerTlv> *root )
{
	if (NULL == root)
	{
		return;
	}
	DCTreeNode<DCBerTlv> *node;
	DCASN1P_NODE_FOR (node,root)
	{
		tlv_tree_free(node);
	}
	delete root->data;
}

int get_universal_tag_name( char *name,size_t namelen,asn1c_integer_t tag_value )
{
	name[0] = 0;
	switch(ASN_UNIVERSAL_TAG2TYPE(tag_value) )
	{
	case ASN_BASIC_BOOLEAN:		strncpy(name,"ASN_BASIC_BOOLEAN",namelen);		break;
	case ASN_BASIC_INTEGER:		strncpy(name,"ASN_BASIC_INTEGER",namelen);		break;
	case ASN_BASIC_BIT_STRING:		strncpy(name,"ASN_BASIC_BIT_STRING",namelen);		break;
	case ASN_BASIC_OCTET_STRING:		strncpy(name,"ASN_BASIC_OCTET_STRING",namelen);		break;
	case ASN_BASIC_NULL:		strncpy(name,"ASN_BASIC_NULL",namelen);		break;
	case ASN_BASIC_OBJECT_IDENTIFIER:		strncpy(name,"ASN_BASIC_OBJECT_IDENTIFIER",namelen);		break;
	case ASN_STRING_ObjectDescriptor:		strncpy(name,"ASN_STRING_ObjectDescriptor",namelen);		break;
	case ASN_BASIC_EXTERNAL:		strncpy(name,"ASN_BASIC_EXTERNAL",namelen);		break;
	case ASN_BASIC_REAL:		strncpy(name,"ASN_BASIC_REAL",namelen);		break;
	case ASN_BASIC_ENUMERATED:		strncpy(name,"ASN_BASIC_ENUMERATED",namelen);		break;
	case ASN_BASIC_EMBEDDED_PDV:		strncpy(name,"ASN_BASIC_EMBEDDED_PDV",namelen);		break;
	case ASN_STRING_UTF8String:		strncpy(name,"ASN_STRING_UTF8String",namelen);		break;
	case ASN_BASIC_RELATIVE_OID:		strncpy(name,"ASN_BASIC_RELATIVE_OID",namelen);		break;
	case ASN_CONSTR_SEQUENCE:		/* Or SEQUENCE OF */		strncpy(name,"ASN_CONSTR_SEQUENCE",namelen);		break;
	case ASN_CONSTR_SET:		/* Or SET OF */		strncpy(name,"ASN_CONSTR_SET",namelen);		break;
	case ASN_STRING_NumericString:	/* " "|"0".."9" */		strncpy(name,"ASN_STRING_NumericString",namelen);		break;
	case ASN_STRING_PrintableString:		strncpy(name,"ASN_STRING_PrintableString",namelen);		break;
	case ASN_STRING_TeletexString:		strncpy(name,"ASN_STRING_TeletexString",namelen);		break;
	case ASN_STRING_VideotexString:		strncpy(name,"ASN_STRING_VideotexString",namelen);		break;
	case ASN_STRING_IA5String:		strncpy(name,"ASN_STRING_IA5String",namelen);		break;
	case ASN_BASIC_UTCTime:		strncpy(name,"ASN_BASIC_UTCTime",namelen);		break;
	case ASN_BASIC_GeneralizedTime:		strncpy(name,"ASN_BASIC_GeneralizedTime",namelen);		break;
	case ASN_STRING_GraphicString:		strncpy(name,"ASN_STRING_GraphicString",namelen);		break;
	case ASN_STRING_VisibleString:		strncpy(name,"ASN_STRING_VisibleString",namelen);		break;
	case ASN_STRING_GeneralString:		strncpy(name,"ASN_STRING_GeneralString",namelen);		break;
	case ASN_STRING_UniversalString:	/* 32-bit UCS-4 */		strncpy(name,"ASN_STRING_UniversalString",namelen);		break;
	case ASN_BASIC_CHARACTER_STRING:		strncpy(name,"ASN_BASIC_CHARACTER_STRING",namelen);		break;
	case ASN_STRING_BMPString:		/* 16-bit UCS-2 */		strncpy(name,"ASN_STRING_BMPString",namelen);		break;
	}
	name[namelen-1] = 0;
	return 0;
}

/*------------------------------------------------------------------------------------------------*/


DCTlvFileBuf::DCTlvFileBuf( FILE *fp )
{
	m_fp = fp;
	m_used = 0;
	m_length = 0;
}

DCTlvFileBuf::~DCTlvFileBuf()
{
}

DCTreeNode<DCBerTlv> * DCTlvFileBuf::read_tlv_tree()
{
	ssize_t lastused = 0;
	DCTreeNode<DCBerTlv> *root = NULL;
	if (m_used >= m_length)
	{
		if (0 == read_file() )
		{
			return NULL;
		}
	}
	while ( (lastused = buffer_to_tlv_tree(m_buf + m_used,m_length - m_used,&root) ) == 0 )
	{
		if (0 == read_file() )
		{
			tlv_tree_free(root);
			return NULL;
		}
	}
	if (lastused <0)
	{
		throw DCDecodeException("decode error! [%s][%d]",__FILE__,__LINE__);
	}
	m_used += lastused;
	return root;
}

int DCTlvFileBuf::read_file()
{
	m_length = fread(m_buf,1,DICASN1P_TREE_BUF_SIZE,m_fp);
	if (0 >= m_length)
	{
		return 0;
	}
	m_used = 0;
	return m_length;
}
/*------------------------------------------------------------------------------------------------*/
DCDecodeException::DCDecodeException( const char *fmt,... )
{
	va_list vlist;
	va_start(vlist,fmt);
	vsnprintf(m_buf,512,fmt,vlist);
	m_buf[511] = 0;
	va_end(vlist);
}

const char * DCDecodeException::what()
{
	return m_buf;
}

/*------------------------------------------------------------------------------------------------*/

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -