📄 asnper.cxx
字号:
/*
* asnper.cxx
*
* Abstract Syntax Notation 1 Encoding Rules
*
* Portable Windows Library
*
* $Log: asnper.cxx,v $
* Revision 1.10 2004/07/11 12:33:47 csoutheren
* Added guards against illegal PDU values causing crashes
*
* Revision 1.9 2004/03/23 04:53:57 csoutheren
* Fixed problem with incorrect encoding of ASN NULL under some circumstances
* Thanks to Ed Day of Objective Systems
*
* Revision 1.8 2004/01/17 17:43:42 csoutheren
* Fixed problem with the upper limit on various constrained types not being correctly enforced
*
* Revision 1.7 2004/01/17 09:23:43 csoutheren
* Fixed problem with the upper limit on constrained unsigned integers not being correctly enforced
*
* Revision 1.6 2003/12/14 10:21:29 rjongbloed
* Fixed bug in length incorrectlty decoded from ASN and (apparently) rare circumstances. Thanks pangxg@hotmail.com.
* Cleaned up return values to be BOOL rather than int for some functions.
*
* Revision 1.5 2003/12/03 03:50:03 csoutheren
* Reversed last change as it broke decoding in some circumstances
*
*
*/
///////////////////////////////////////////////////////////////////////
BOOL PPER_Stream::NullDecode(PASN_Null &)
{
return TRUE;
}
void PPER_Stream::NullEncode(const PASN_Null &)
{
}
///////////////////////////////////////////////////////////////////////
BOOL PASN_ConstrainedObject::ConstrainedLengthDecode(PPER_Stream & strm, unsigned & length)
{
// The execution order is important in the following. The SingleBitDecode() function
// must be called if extendable is TRUE, no matter what.
if ((extendable && strm.SingleBitDecode()) || constraint == Unconstrained)
return strm.LengthDecode(0, INT_MAX, length);
else
return strm.LengthDecode(lowerLimit, upperLimit, length);
}
void PASN_ConstrainedObject::ConstrainedLengthEncode(PPER_Stream & strm, unsigned length) const
{
if (ConstraintEncode(strm, length)) // 26.4
strm.LengthEncode(length, 0, INT_MAX);
else
strm.LengthEncode(length, lowerLimit, upperLimit);
}
BOOL PASN_ConstrainedObject::ConstraintEncode(PPER_Stream & strm, unsigned value) const
{
if (!extendable)
return constraint != FixedConstraint;
BOOL needsExtending = value > upperLimit;
if (!needsExtending) {
if (lowerLimit < 0) {
if ((int)value < lowerLimit)
needsExtending = TRUE;
}
else {
if (value < (unsigned)lowerLimit)
needsExtending = TRUE;
}
}
strm.SingleBitEncode(needsExtending);
return needsExtending;
}
///////////////////////////////////////////////////////////////////////
BOOL PPER_Stream::BooleanDecode(PASN_Boolean & value)
{
if (IsAtEnd())
return FALSE;
// X.691 Section 11
value = (BOOL)SingleBitDecode();
return TRUE;
}
void PPER_Stream::BooleanEncode(const PASN_Boolean & value)
{
// X.691 Section 11
SingleBitEncode((BOOL)value);
}
BOOL PPER_Stream::IntegerDecode(PASN_Integer & value)
{
return value.DecodePER(*this);
}
void PPER_Stream::IntegerEncode(const PASN_Integer & value)
{
value.EncodePER(*this);
}
///////////////////////////////////////////////////////////////////////
BOOL PASN_Integer::DecodePER(PPER_Stream & strm)
{
// X.691 Sections 12
switch (constraint) {
case FixedConstraint : // 12.2.1 & 12.2.2
break;
case ExtendableConstraint :
if (!strm.SingleBitDecode()) // 12.1
break;
// Fall into default case for unconstrained or partially constrained
default : // 12.2.6
unsigned len;
if (!strm.LengthDecode(0, INT_MAX, len))
return FALSE;
len *= 8;
if (!strm.MultiBitDecode(len, value))
return FALSE;
if (IsUnsigned())
value += lowerLimit;
else if ((value&(1<<(len-1))) != 0) // Negative
value |= UINT_MAX << len; // Sign extend
return TRUE;
}
if ((unsigned)lowerLimit != upperLimit) // 12.2.2
return strm.UnsignedDecode(lowerLimit, upperLimit, value); // which devolves to 10.5
// 12.2.1
value = lowerLimit;
return TRUE;
}
void PASN_Integer::EncodePER(PPER_Stream & strm) const
{
// X.691 Sections 12
// 12.1
if (ConstraintEncode(strm, (int)value)) {
// 12.2.6
unsigned adjusted_value = value - lowerLimit;
PINDEX nBits = 1; // Allow for sign bit
if (IsUnsigned())
nBits = CountBits(adjusted_value+1);
else if ((int)adjusted_value > 0)
nBits += CountBits(adjusted_value+1);
else
nBits += CountBits(-(int)adjusted_value+1);
// Round up to nearest number of whole octets
PINDEX nBytes = (nBits+7)/8;
strm.LengthEncode(nBytes, 0, INT_MAX);
strm.MultiBitEncode(adjusted_value, nBytes*8);
return;
}
if ((unsigned)lowerLimit == upperLimit) // 12.2.1
return;
// 12.2.2 which devolves to 10.5
strm.UnsignedEncode(value, lowerLimit, upperLimit);
}
///////////////////////////////////////////////////////////////////////
BOOL PPER_Stream::EnumerationDecode(PASN_Enumeration & value)
{
return value.DecodePER(*this);
}
void PPER_Stream::EnumerationEncode(const PASN_Enumeration & value)
{
value.EncodePER(*this);
}
BOOL PASN_Enumeration::DecodePER(PPER_Stream & strm)
{
// X.691 Section 13
if (extendable) { // 13.3
if (strm.SingleBitDecode()) {
unsigned len = 0;
return strm.SmallUnsignedDecode(len) &&
len > 0 &&
strm.UnsignedDecode(0, len-1, value);
}
}
return strm.UnsignedDecode(0, maxEnumValue, value); // 13.2
}
void PASN_Enumeration::EncodePER(PPER_Stream & strm) const
{
// X.691 Section 13
if (extendable) { // 13.3
BOOL extended = value > maxEnumValue;
strm.SingleBitEncode(extended);
if (extended) {
strm.SmallUnsignedEncode(1+value);
strm.UnsignedEncode(value, 0, value);
return;
}
}
strm.UnsignedEncode(value, 0, maxEnumValue); // 13.2
}
///////////////////////////////////////////////////////////////////////
BOOL PPER_Stream::RealDecode(PASN_Real &)
{
// X.691 Section 14
if (IsAtEnd())
return FALSE;
unsigned len;
if (!MultiBitDecode(8, len))
return FALSE;
PAssertAlways(PUnimplementedFunction);
byteOffset += len+1;
return TRUE;
}
void PPER_Stream::RealEncode(const PASN_Real &)
{
// X.691 Section 14
MultiBitEncode(0, 8);
PAssertAlways(PUnimplementedFunction);
MultiBitEncode(0, 8);
}
///////////////////////////////////////////////////////////////////////
BOOL PPER_Stream::ObjectIdDecode(PASN_ObjectId & value)
{
// X.691 Section 23
unsigned dataLen;
if (!LengthDecode(0, 255, dataLen))
return FALSE;
ByteAlign();
return value.CommonDecode(*this, dataLen);
}
void PPER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
{
// X.691 Section 23
PBYTEArray eObjId;
value.CommonEncode(eObjId);
LengthEncode(eObjId.GetSize(), 0, 255);
BlockEncode(eObjId, eObjId.GetSize());
}
///////////////////////////////////////////////////////////////////////
BOOL PASN_BitString::DecodeSequenceExtensionBitmap(PPER_Stream & strm)
{
if (!strm.SmallUnsignedDecode(totalBits))
return FALSE;
totalBits++;
if (!SetSize(totalBits))
return FALSE;
if (totalBits > strm.GetBitsLeft())
return FALSE;
unsigned theBits;
PINDEX idx = 0;
unsigned bitsLeft = totalBits;
while (bitsLeft >= 8) {
if (!strm.MultiBitDecode(8, theBits))
return FALSE;
bitData[idx++] = (BYTE)theBits;
bitsLeft -= 8;
}
if (bitsLeft > 0) {
if (!strm.MultiBitDecode(bitsLeft, theBits))
return FALSE;
bitData[idx] = (BYTE)(theBits << (8-bitsLeft));
}
return TRUE;
}
void PASN_BitString::EncodeSequenceExtensionBitmap(PPER_Stream & strm) const
{
PAssert(totalBits > 0, PLogicError);
unsigned bitsLeft = totalBits;
while (bitsLeft > 1 && !(*this)[bitsLeft-1])
bitsLeft--;
strm.SmallUnsignedEncode(bitsLeft-1);
PINDEX idx = 0;
while (bitsLeft >= 8) {
strm.MultiBitEncode(bitData[idx++], 8);
bitsLeft -= 8;
}
if (bitsLeft > 0)
strm.MultiBitEncode(bitData[idx] >> (8 - bitsLeft), bitsLeft);
}
BOOL PASN_BitString::DecodePER(PPER_Stream & strm)
{
// X.691 Section 15
if (!ConstrainedLengthDecode(strm, totalBits))
return FALSE;
if (!SetSize(totalBits))
return FALSE;
if (totalBits == 0)
return TRUE; // 15.7
if (totalBits > strm.GetBitsLeft())
return FALSE;
if (totalBits > 16) {
unsigned nBytes = (totalBits+7)/8;
return strm.BlockDecode(bitData.GetPointer(), nBytes) == nBytes; // 15.9
}
unsigned theBits;
if (totalBits <= 8) {
if (!strm.MultiBitDecode(totalBits, theBits))
return FALSE;
bitData[0] = (BYTE)(theBits << (8-totalBits));
}
else { // 15.8
if (!strm.MultiBitDecode(8, theBits))
return FALSE;
bitData[0] = (BYTE)theBits;
if (!strm.MultiBitDecode(totalBits-8, theBits))
return FALSE;
bitData[1] = (BYTE)(theBits << (16-totalBits));
}
return TRUE;
}
void PASN_BitString::EncodePER(PPER_Stream & strm) const
{
// X.691 Section 15
ConstrainedLengthEncode(strm, totalBits);
if (totalBits == 0)
return;
if (totalBits > 16)
strm.BlockEncode(bitData, (totalBits+7)/8); // 15.9
else if (totalBits <= 8) // 15.8
strm.MultiBitEncode(bitData[0] >> (8 - totalBits), totalBits);
else {
strm.MultiBitEncode(bitData[0], 8);
strm.MultiBitEncode(bitData[1] >> (16 - totalBits), totalBits-8);
}
}
///////////////////////////////////////////////////////////////////////
BOOL PPER_Stream::BitStringDecode(PASN_BitString & value)
{
return value.DecodePER(*this);
}
void PPER_Stream::BitStringEncode(const PASN_BitString & value)
{
value.EncodePER(*this);
}
///////////////////////////////////////////////////////////////////////
BOOL PASN_OctetString::DecodeSubType(PASN_Object & obj) const
{
PPER_Stream stream = GetValue();
return obj.Decode(stream);
}
void PASN_OctetString::EncodeSubType(const PASN_Object & obj)
{
PPER_Stream stream;
obj.Encode(stream);
stream.CompleteEncoding();
SetValue(stream);
}
BOOL PASN_OctetString::DecodePER(PPER_Stream & strm)
{
// X.691 Section 16
unsigned nBytes;
if (!ConstrainedLengthDecode(strm, nBytes))
return FALSE;
if (!SetSize(nBytes)) // 16.5
return FALSE;
if ((int)upperLimit != lowerLimit)
return strm.BlockDecode(value.GetPointer(), nBytes) == nBytes;
unsigned theBits;
switch (nBytes) {
case 0 :
break;
case 1 : // 16.6
if (!strm.MultiBitDecode(8, theBits))
return FALSE;
value[0] = (BYTE)theBits;
break;
case 2 : // 16.6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -