📄 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 if (!strm.MultiBitDecode(8, theBits)) return FALSE; value[0] = (BYTE)theBits; if (!strm.MultiBitDecode(8, theBits)) return FALSE; value[1] = (BYTE)theBits; break; default: // 16.7 return strm.BlockDecode(value.GetPointer(), nBytes) == nBytes; } return TRUE;}void PASN_OctetString::EncodePER(PPER_Stream & strm) const{ // X.691 Section 16 PINDEX nBytes = value.GetSize(); ConstrainedLengthEncode(strm, nBytes); if ((int)upperLimit != lowerLimit) { strm.BlockEncode(value, nBytes); return; } switch (nBytes) { case 0 : // 16.5 break; case 1 : // 16.6 strm.MultiBitEncode(value[0], 8); break; case 2 : // 16.6 strm.MultiBitEncode(value[0], 8); strm.MultiBitEncode(value[1], 8); break; default: // 16.7 strm.BlockEncode(value, nBytes); }}BOOL PPER_Stream::OctetStringDecode(PASN_OctetString & value){ return value.DecodePER(*this);}void PPER_Stream::OctetStringEncode(const PASN_OctetString & value){ value.EncodePER(*this);}///////////////////////////////////////////////////////////////////////BOOL PASN_ConstrainedString::DecodePER(PPER_Stream & strm){ // X.691 Section 26 unsigned len; if (!ConstrainedLengthDecode(strm, len)) return FALSE; if (len == 0) { // 10.9.3.3 value.SetSize(1); value[0] = '\0'; return TRUE; } unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits; unsigned totalBits = upperLimit*nBits; if (constraint == Unconstrained || (lowerLimit == (int)upperLimit ? (totalBits > 16) : (totalBits >= 16))) { if (nBits == 8) return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len; if (strm.IsAligned()) strm.ByteAlign(); } if ((PINDEX)len > MaximumStringSize) return FALSE; if (!value.SetSize(len+1)) return FALSE; PINDEX i; for (i = 0; i < (PINDEX)len; i++) { unsigned theBits; if (!strm.MultiBitDecode(nBits, theBits)) return FALSE; if (nBits >= canonicalSetBits && canonicalSetBits > 4) value[i] = (char)theBits; else value[i] = characterSet[(PINDEX)theBits]; } value[i] = '\0'; return TRUE;}void PASN_ConstrainedString::EncodePER(PPER_Stream & strm) const{ // X.691 Section 26 PINDEX len = value.GetSize()-1; ConstrainedLengthEncode(strm, len); if (len == 0) // 10.9.3.3 return; unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits; unsigned totalBits = upperLimit*nBits; if (constraint == Unconstrained || (lowerLimit == (int)upperLimit ? (totalBits > 16) : (totalBits >= 16))) { // 26.5.7 if (nBits == 8) { strm.BlockEncode((const BYTE *)(const char *)value, len); return; } if (strm.IsAligned()) strm.ByteAlign(); } for (PINDEX i = 0; i < len; i++) { if (nBits >= canonicalSetBits && canonicalSetBits > 4) strm.MultiBitEncode(value[i], nBits); else { const void * ptr = memchr(characterSet, value[i], characterSet.GetSize()); PINDEX pos = 0; if (ptr != NULL) pos = ((const char *)ptr - (const char *)characterSet); strm.MultiBitEncode(pos, nBits); } }}///////////////////////////////////////////////////////////////////////BOOL PPER_Stream::ConstrainedStringDecode(PASN_ConstrainedString & value){ return value.DecodePER(*this);}void PPER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString & value){ value.EncodePER(*this);}///////////////////////////////////////////////////////////////////////BOOL PASN_BMPString::DecodePER(PPER_Stream & strm){ // X.691 Section 26 unsigned len; if (!ConstrainedLengthDecode(strm, len)) return FALSE; if ((PINDEX)len > MaximumStringSize) return FALSE; if (!value.SetSize(len)) return FALSE; PINDEX nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits; if ((constraint == Unconstrained || upperLimit*nBits > 16) && strm.IsAligned()) strm.ByteAlign(); for (PINDEX i = 0; i < (PINDEX)len; i++) { unsigned theBits; if (!strm.MultiBitDecode(nBits, theBits)) return FALSE; if (characterSet.IsEmpty()) value[i] = (WORD)(theBits + firstChar); else value[i] = characterSet[(PINDEX)theBits]; } return TRUE;}void PASN_BMPString::EncodePER(PPER_Stream & strm) const{ // X.691 Section 26 PINDEX len = value.GetSize(); ConstrainedLengthEncode(strm, len); PINDEX nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits; if ((constraint == Unconstrained || upperLimit*nBits > 16) && strm.IsAligned()) strm.ByteAlign(); for (PINDEX i = 0; i < len; i++) { if (characterSet.IsEmpty()) strm.MultiBitEncode(value[i] - firstChar, nBits); else { for (PINDEX pos = 0; pos < characterSet.GetSize(); pos++) { if (characterSet[pos] == value[i]) { strm.MultiBitEncode(pos, nBits); break; } } } }}BOOL PPER_Stream::BMPStringDecode(PASN_BMPString & value){ return value.DecodePER(*this);}void PPER_Stream::BMPStringEncode(const PASN_BMPString & value){ value.EncodePER(*this);}///////////////////////////////////////////////////////////////////////BOOL PASN_Choice::DecodePER(PPER_Stream & strm){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -