Index: src/OFASN1BitString.h ================================================================== --- src/OFASN1BitString.h +++ src/OFASN1BitString.h @@ -39,24 +39,47 @@ /*! * @brief The length of the BitString in bits. */ @property (readonly, nonatomic) size_t bitStringLength; +/*! + * @brief Creates an ASN.1 BitString with the specified BitString value and + * length. + * + * @param bitStringValue The value of the BitString + * @param bitStringLength The length of the BitString in bits + * @return A new, autoreleased OFASN1BitString + */ ++ (instancetype)bitStringWithBitStringValue: (OFData *)bitStringValue + bitStringLength: (size_t)bitStringLength; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated ASN.1 BitString with the specified + * BitString value and length. + * + * @param bitStringValue The value of the BitString + * @param bitStringLength The length of the BitString in bits + * @return An initialized OFASN1BitString + */ +- (instancetype)initWithBitStringValue: (OFData *)bitStringValue + bitStringLength: (size_t)bitStringLength + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 BitString with the specified * arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 BitString + * @return An initialized OFASN1BitString */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1BitString.m ================================================================== --- src/OFASN1BitString.m +++ src/OFASN1BitString.m @@ -27,24 +27,48 @@ @implementation OFASN1BitString @synthesize bitStringValue = _bitStringValue; @synthesize bitStringLength = _bitStringLength; -- (instancetype)init ++ (instancetype)bitStringWithBitStringValue: (OFData *)bitStringValue + bitStringLength: (size_t)bitStringLength +{ + return [[[self alloc] + initWithBitStringValue: bitStringValue + bitStringLength: bitStringLength] autorelease]; +} + +- (instancetype)initWithBitStringValue: (OFData *)bitStringValue + bitStringLength: (size_t)bitStringLength { - OF_INVALID_INIT_METHOD + self = [super init]; + + @try { + if ([bitStringValue count] * [bitStringValue itemSize] != + bitStringLength / 8) + @throw [OFInvalidFormatException exception]; + + _bitStringValue = [bitStringValue copy]; + _bitStringLength = bitStringLength; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + void *pool = objc_autoreleasePoolPush(); + OFData *bitStringValue; + size_t bitStringLength; @try { - void *pool = objc_autoreleasePoolPush(); unsigned char lastByteBits; size_t count = [DEREncodedContents count]; if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_BIT_STRING || constructed) @@ -61,22 +85,30 @@ if (SIZE_MAX / 8 < count - 1 || SIZE_MAX - (count - 1) * 8 < lastByteBits) @throw [OFOutOfRangeException exception]; - _bitStringLength = (count - 1) * 8 + lastByteBits; - _bitStringValue = [[DEREncodedContents + bitStringLength = (count - 1) * 8 + lastByteBits; + bitStringValue = [[DEREncodedContents subdataWithRange: of_range(1, count - 1)] copy]; - - objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } + self = [self initWithBitStringValue: bitStringValue + bitStringLength: bitStringLength]; + + objc_autoreleasePoolPop(pool); + return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_bitStringValue release]; Index: src/OFASN1Boolean.h ================================================================== --- src/OFASN1Boolean.h +++ src/OFASN1Boolean.h @@ -31,24 +31,42 @@ /*! * @brief The Boolean value. */ @property (readonly, nonatomic) bool booleanValue; +/*! + * @brief Creates an ASN.1 Boolean with the specified Boolean value. + * + * @param booleanValue The value of the Boolean + * @return A new, autoreleased OFASN1Boolean + */ ++ (instancetype)booleanWithBooleanValue: (bool)booleanValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated ASN.1 Boolean with the specified + * Boolean value. + * + * @param booleanValue The value of the Boolean + * @return An initialized OFASN1Boolean + */ +- (instancetype)initWithBooleanValue: (bool)booleanValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 Boolean with the specified * arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 Boolean + * @return An initialized OFASN1Boolean */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1Boolean.m ================================================================== --- src/OFASN1Boolean.m +++ src/OFASN1Boolean.m @@ -25,25 +25,32 @@ #import "OFInvalidFormatException.h" @implementation OFASN1Boolean @synthesize booleanValue = _booleanValue; -- (instancetype)init ++ (instancetype)booleanWithBooleanValue: (bool)booleanValue +{ + return [[[self alloc] initWithBooleanValue: booleanValue] autorelease]; +} + +- (instancetype)initWithBooleanValue: (bool)booleanValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + _booleanValue = booleanValue; + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + unsigned char value; @try { - unsigned char value; - if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_BOOLEAN || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1 || @@ -52,18 +59,21 @@ value = *(unsigned char *)[DEREncodedContents itemAtIndex: 0]; if (value != 0 && value != 0xFF) @throw [OFInvalidFormatException exception]; - - _booleanValue = value; } @catch (id e) { [self release]; @throw e; } - return self; + return [self initWithBooleanValue: !!value]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD } - (bool)isEqual: (id)object { OFASN1Boolean *boolean; Index: src/OFASN1Enumerated.h ================================================================== --- src/OFASN1Enumerated.h +++ src/OFASN1Enumerated.h @@ -31,24 +31,42 @@ /*! * @brief The integer value. */ @property (readonly, nonatomic) intmax_t integerValue; +/*! + * @brief Creates an ASN.1 Enumerated with the specified integer value. + * + * @param integerValue The integer value of the Enumerated + * @return A new, autoreleased OFASN1Enumerated + */ ++ (instancetype)enumeratedWithIntegerValue: (intmax_t)integerValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated ASN.1 Enumerated with the specified + * integer value. + * + * @param integerValue The integer value of the Enumerated + * @return An initialized OFASN1Enumerated + */ +- (instancetype)initWithIntegerValue: (intmax_t)integerValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 Enumerated with the specified * arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 Enumerated + * @return An initialized OFASN1Enumerated */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1Enumerated.m ================================================================== --- src/OFASN1Enumerated.m +++ src/OFASN1Enumerated.m @@ -21,44 +21,58 @@ #import "OFData.h" #import "OFString.h" #import "OFInvalidArgumentException.h" -extern intmax_t of_asn1_integer_parse(const unsigned char *buffer, +extern intmax_t of_asn1_der_integer_parse(const unsigned char *buffer, size_t length); @implementation OFASN1Enumerated @synthesize integerValue = _integerValue; -- (instancetype)init ++ (instancetype)enumeratedWithIntegerValue: (intmax_t)integerValue +{ + return [[[self alloc] initWithIntegerValue: integerValue] autorelease]; +} + +- (instancetype)initWithIntegerValue: (intmax_t)integerValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + _integerValue = integerValue; + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + intmax_t integerValue; @try { if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_ENUMERATED || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1) @throw [OFInvalidArgumentException exception]; - _integerValue = of_asn1_integer_parse( + integerValue = of_asn1_der_integer_parse( [DEREncodedContents items], [DEREncodedContents count]); } @catch (id e) { [self release]; @throw e; } - return self; + return [self initWithIntegerValue: integerValue]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD } - (bool)isEqual: (id)object { OFASN1Enumerated *enumerated; Index: src/OFASN1IA5String.h ================================================================== --- src/OFASN1IA5String.h +++ src/OFASN1IA5String.h @@ -38,24 +38,42 @@ /*! * @brief The string value. */ @property (readonly, nonatomic) OFString *stringValue; +/*! + * @brief Creates an IA5String with the specified string value. + * + * @param stringValue The string value of the IA5String + * @return A new, autoreleased OFASN1IA5String + */ ++ (instancetype)stringWithStringValue: (OFString *)stringValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated IA5String with the specified string + * value. + * + * @param stringValue The string value of the IA5String + * @return An initialized OFASN1IA5String + */ +- (instancetype)initWithStringValue: (OFString *)stringValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 IA5String with the specified * arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 IA5String + * @return An initialized OFASN1IA5String */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1IA5String.m ================================================================== --- src/OFASN1IA5String.m +++ src/OFASN1IA5String.m @@ -24,41 +24,65 @@ #import "OFInvalidArgumentException.h" @implementation OFASN1IA5String @synthesize IA5StringValue = _IA5StringValue; -- (instancetype)init ++ (instancetype)stringWithStringValue: (OFString *)stringValue +{ + return [[[self alloc] initWithStringValue: stringValue] autorelease]; +} + +- (instancetype)initWithStringValue: (OFString *)stringValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + @try { + _IA5StringValue = [stringValue copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + void *pool = objc_autoreleasePoolPush(); + OFString *IA5StringValue; @try { if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_IA5_STRING || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1) @throw [OFInvalidArgumentException exception]; - _IA5StringValue = [[OFString alloc] - initWithCString: [DEREncodedContents items] - encoding: OF_STRING_ENCODING_ASCII - length: [DEREncodedContents count]]; + IA5StringValue = [OFString + stringWithCString: [DEREncodedContents items] + encoding: OF_STRING_ENCODING_ASCII + length: [DEREncodedContents count]]; } @catch (id e) { [self release]; @throw e; } + self = [self initWithStringValue: IA5StringValue]; + + objc_autoreleasePoolPop(pool); + return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_IA5StringValue release]; Index: src/OFASN1Integer.h ================================================================== --- src/OFASN1Integer.h +++ src/OFASN1Integer.h @@ -31,24 +31,42 @@ /*! * @brief The Integer value. */ @property (readonly, nonatomic) intmax_t integerValue; +/*! + * @brief Creates an ASN.1 Integer with the specified integer value. + * + * @param integerValue The integer value of the Integer + * @return A new, autoreleased OFASN1Integer + */ ++ (instancetype)integerWithIntegerValue: (intmax_t)integerValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated ASN.1 Integer with the specified + * integer value. + * + * @param integerValue The integer value of the Integer + * @return An initialized OFASN1Integer + */ +- (instancetype)initWithIntegerValue: (intmax_t)integerValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 Integer with the specified * arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 Integer + * @return An initialized OFASN1Integer */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1Integer.m ================================================================== --- src/OFASN1Integer.m +++ src/OFASN1Integer.m @@ -24,11 +24,11 @@ #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFOutOfRangeException.h" intmax_t -of_asn1_integer_parse(const unsigned char *buffer, size_t length) +of_asn1_der_integer_parse(const unsigned char *buffer, size_t length) { uintmax_t value = 0; /* TODO: Support for big numbers */ if (length > sizeof(uintmax_t) && @@ -49,38 +49,52 @@ } @implementation OFASN1Integer @synthesize integerValue = _integerValue; -- (instancetype)init ++ (instancetype)integerWithIntegerValue: (intmax_t)integerValue +{ + return [[[self alloc] initWithIntegerValue: integerValue] autorelease]; +} + +- (instancetype)initWithIntegerValue: (intmax_t)integerValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + _integerValue = integerValue; + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + intmax_t integerValue; @try { if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_INTEGER || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1) @throw [OFInvalidArgumentException exception]; - _integerValue = of_asn1_integer_parse( + integerValue = of_asn1_der_integer_parse( [DEREncodedContents items], [DEREncodedContents count]); } @catch (id e) { [self release]; @throw e; } - return self; + return [self initWithIntegerValue: integerValue]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD } - (bool)isEqual: (id)object { OFASN1Integer *integer; Index: src/OFASN1NumericString.h ================================================================== --- src/OFASN1NumericString.h +++ src/OFASN1NumericString.h @@ -38,12 +38,30 @@ /*! * @brief The string value. */ @property (readonly, nonatomic) OFString *stringValue; +/*! + * @brief Creates an NumericString with the specified string value. + * + * @param stringValue The string value of the NumericString + * @return A new, autoreleased OFASN1NumericString + */ ++ (instancetype)stringWithStringValue: (OFString *)stringValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated NumericString with the specified + * string value. + * + * @param stringValue The string value of the NumericString + * @return An initialized OFASN1NumericString + */ +- (instancetype)initWithStringValue: (OFString *)stringValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 NumericString with the * specified arguments. * * @param tagClass The tag class of the value's type Index: src/OFASN1NumericString.m ================================================================== --- src/OFASN1NumericString.m +++ src/OFASN1NumericString.m @@ -25,49 +25,76 @@ #import "OFInvalidEncodingException.h" @implementation OFASN1NumericString @synthesize numericStringValue = _numericStringValue; -- (instancetype)init ++ (instancetype)stringWithStringValue: (OFString *)stringValue +{ + return [[[self alloc] initWithStringValue: stringValue] autorelease]; +} + +- (instancetype)initWithStringValue: (OFString *)stringValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + const char *cString = [stringValue UTF8String]; + size_t length = [stringValue UTF8StringLength]; + + for (size_t i = 0; i < length; i++) + if (!of_ascii_isdigit(cString[i]) && cString[i] != ' ') + @throw [OFInvalidEncodingException exception]; + + _numericStringValue = [stringValue copy]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + void *pool = objc_autoreleasePoolPush(); + OFString *numericStringValue; @try { - const unsigned char *items = [DEREncodedContents items]; - size_t count = [DEREncodedContents count]; - if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_NUMERIC_STRING || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1) @throw [OFInvalidArgumentException exception]; - for (size_t i = 0; i < count; i++) - if (!of_ascii_isdigit(items[i]) && items[i] != ' ') - @throw [OFInvalidEncodingException exception]; - - _numericStringValue = [[OFString alloc] - initWithCString: [DEREncodedContents items] - encoding: OF_STRING_ENCODING_ASCII - length: [DEREncodedContents count]]; + numericStringValue = [OFString + stringWithCString: [DEREncodedContents items] + encoding: OF_STRING_ENCODING_ASCII + length: [DEREncodedContents count]]; } @catch (id e) { [self release]; @throw e; } + self = [self initWithStringValue: numericStringValue]; + + objc_autoreleasePoolPop(pool); + return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_numericStringValue release]; Index: src/OFASN1ObjectIdentifier.h ================================================================== --- src/OFASN1ObjectIdentifier.h +++ src/OFASN1ObjectIdentifier.h @@ -34,24 +34,43 @@ /*! * @brief The subidentifiers of the ObjectIdentifier. */ @property (readonly, nonatomic) OFArray OF_GENERIC(OFNumber *) *subidentifiers; +/*! + * @brief Creates an ASN.1 ObjectIdentifier with the specified subidentifiers. + * + * @param subidentifiers The subidentifiers of the ASN.1 ObjectIdentifier + * @return A new, autoreleased OFASN1ObjectIdentifier + */ ++ (instancetype)objectIdentifierWithSubidentifiers: + (OFArray OF_GENERIC(OFNumber *) *)subidentifiers; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated ASN.1 ObjectIdentifier with the + * specified subidentifiers. + * + * @param subidentifiers The subidentifiers of the ASN.1 ObjectIdentifier + * @return An initialized OFASN1ObjectIdentifier + */ +- (instancetype)initWithSubidentifiers: + (OFArray OF_GENERIC(OFNumber *) *)subidentifiers OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 ObjectIdentifier with the * specified arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 ObjectIdentifier + * @return An initialized OFASN1ObjectIdentifier */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1ObjectIdentifier.m ================================================================== --- src/OFASN1ObjectIdentifier.m +++ src/OFASN1ObjectIdentifier.m @@ -28,27 +28,55 @@ #import "OFOutOfRangeException.h" @implementation OFASN1ObjectIdentifier @synthesize subidentifiers = _subidentifiers; -- (instancetype)init ++ (instancetype)objectIdentifierWithSubidentifiers: + (OFArray OF_GENERIC(OFNumber *) *)subidentifiers +{ + return [[[self alloc] + initWithSubidentifiers: subidentifiers] autorelease]; +} + +- (instancetype)initWithSubidentifiers: + (OFArray OF_GENERIC(OFNumber *) *)subidentifiers { - OF_INVALID_INIT_METHOD + self = [super init]; + + @try { + if ([subidentifiers count] < 1) + @throw [OFInvalidFormatException exception]; + + switch ([[subidentifiers objectAtIndex: 0] intMaxValue]) { + case 0: + case 1: + case 2: + break; + default: + @throw [OFInvalidFormatException exception]; + } + + _subidentifiers = [subidentifiers copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + void *pool = objc_autoreleasePoolPush(); + OFMutableArray OF_GENERIC(OFNumber *) *subidentifiers; @try { - void *pool = objc_autoreleasePoolPush(); const unsigned char *items = [DEREncodedContents items]; size_t count = [DEREncodedContents count]; - OFMutableArray *subidentifiers = [OFMutableArray array]; uintmax_t value = 0; uint_fast8_t bits = 0; if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_OBJECT_IDENTIFIER || @@ -55,10 +83,12 @@ constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1 || count == 0) @throw [OFInvalidArgumentException exception]; + + subidentifiers = [OFMutableArray array]; for (size_t i = 0; i < count; i++) { if (bits == 0 && items[i] == 0x80) @throw [OFInvalidFormatException exception]; @@ -95,20 +125,26 @@ if (items[count - 1] & 0x80) @throw [OFInvalidFormatException exception]; [subidentifiers makeImmutable]; - _subidentifiers = [subidentifiers copy]; - - objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } + self = [self initWithSubidentifiers: subidentifiers]; + + objc_autoreleasePoolPop(pool); + return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_subidentifiers release]; Index: src/OFASN1OctetString.h ================================================================== --- src/OFASN1OctetString.h +++ src/OFASN1OctetString.h @@ -33,12 +33,30 @@ /*! * @brief The OctetString value. */ @property (readonly, nonatomic) OFData *octetStringValue; +/*! + * @brief Creates an OctetString with the specified value. + * + * @param octetStringValue The OctetString value + * @return A new, autoreleased OFASN1OctetString + */ ++ (instancetype)octetStringWithOctetStringValue: (OFData *)octetStringValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated OctetString with the specified + * value. + * + * @param octetStringValue The OctetString value + * @return An initialized OFASN1OctetString + */ +- (instancetype)initWithOctetStringValue: (OFData *)octetStringValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 OctetString with the specified * arguments. * * @param tagClass The tag class of the value's type Index: src/OFASN1OctetString.m ================================================================== --- src/OFASN1OctetString.m +++ src/OFASN1OctetString.m @@ -24,38 +24,54 @@ #import "OFInvalidArgumentException.h" @implementation OFASN1OctetString @synthesize octetStringValue = _octetStringValue; -- (instancetype)init ++ (instancetype)octetStringWithOctetStringValue: (OFData *)octetStringValue +{ + return [[[self alloc] + initWithOctetStringValue: octetStringValue] autorelease]; +} + +- (instancetype)initWithOctetStringValue: (OFData *)octetStringValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + @try { + _octetStringValue = [octetStringValue copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; - @try { if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_OCTET_STRING || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1) @throw [OFInvalidArgumentException exception]; - - _octetStringValue = [DEREncodedContents copy]; } @catch (id e) { [self release]; @throw e; } - return self; + return [self initWithOctetStringValue: DEREncodedContents]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD } - (void)dealloc { [_octetStringValue release]; Index: src/OFASN1PrintableString.h ================================================================== --- src/OFASN1PrintableString.h +++ src/OFASN1PrintableString.h @@ -38,24 +38,42 @@ /*! * @brief The string value. */ @property (readonly, nonatomic) OFString *stringValue; +/*! + * @brief Creates a PrintableString with the specified string value. + * + * @param stringValue The string value of the PrintableString + * @return A new, autoreleased OFASN1PrintableString + */ ++ (instancetype)stringWithStringValue: (OFString *)stringValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated PrintableString with the specified + * string value. + * + * @param stringValue The string value of the PrintableString + * @return An initialized OFASN1PrintableString + */ +- (instancetype)initWithStringValue: (OFString *)stringValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 PrintableString with the * specified arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 PrintableString + * @return An initialized OFASN1PrintableString */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1PrintableString.m ================================================================== --- src/OFASN1PrintableString.m +++ src/OFASN1PrintableString.m @@ -25,39 +25,29 @@ #import "OFInvalidEncodingException.h" @implementation OFASN1PrintableString @synthesize printableStringValue = _printableStringValue; -- (instancetype)init ++ (instancetype)stringWithStringValue: (OFString *)stringValue { - OF_INVALID_INIT_METHOD + return [[[self alloc] initWithStringValue: stringValue] autorelease]; } -- (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass - tagNumber: (of_asn1_tag_number_t)tagNumber - constructed: (bool)constructed - DEREncodedContents: (OFData *)DEREncodedContents +- (instancetype)initWithStringValue: (OFString *)stringValue { self = [super init]; @try { - const unsigned char *items = [DEREncodedContents items]; - size_t count = [DEREncodedContents count]; - - if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || - tagNumber != OF_ASN1_TAG_NUMBER_PRINTABLE_STRING || - constructed) - @throw [OFInvalidArgumentException exception]; - - if ([DEREncodedContents itemSize] != 1) - @throw [OFInvalidArgumentException exception]; - - for (size_t i = 0; i < count; i++) { - if (of_ascii_isalnum(items[i])) + void *pool = objc_autoreleasePoolPush(); + const char *cString = [stringValue UTF8String]; + size_t length = [stringValue UTF8StringLength]; + + for (size_t i = 0; i < length; i++) { + if (of_ascii_isalnum(cString[i])) continue; - switch (items[i]) { + switch (cString[i]) { case ' ': case '\'': case '(': case ')': case '+': @@ -72,21 +62,58 @@ default: @throw [OFInvalidEncodingException exception]; } } - _printableStringValue = [[OFString alloc] - initWithCString: [DEREncodedContents items] - encoding: OF_STRING_ENCODING_ASCII - length: [DEREncodedContents count]]; + _printableStringValue = [stringValue copy]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass + tagNumber: (of_asn1_tag_number_t)tagNumber + constructed: (bool)constructed + DEREncodedContents: (OFData *)DEREncodedContents +{ + void *pool = objc_autoreleasePoolPush(); + OFString *printableStringValue; + + @try { + if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || + tagNumber != OF_ASN1_TAG_NUMBER_PRINTABLE_STRING || + constructed) + @throw [OFInvalidArgumentException exception]; + + if ([DEREncodedContents itemSize] != 1) + @throw [OFInvalidArgumentException exception]; + + printableStringValue = [OFString + stringWithCString: [DEREncodedContents items] + encoding: OF_STRING_ENCODING_ASCII + length: [DEREncodedContents count]]; } @catch (id e) { [self release]; @throw e; } + self = [self initWithStringValue: printableStringValue]; + + objc_autoreleasePoolPop(pool); + return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_printableStringValue release]; Index: src/OFASN1UTF8String.h ================================================================== --- src/OFASN1UTF8String.h +++ src/OFASN1UTF8String.h @@ -38,24 +38,42 @@ /*! * @brief The string value. */ @property (readonly, nonatomic) OFString *stringValue; +/*! + * @brief Creates a UTF8String with the specified string value. + * + * @param stringValue The string value of the UTF8String + * @return A new, autoreleased OFASN1UTF8String + */ ++ (instancetype)stringWithStringValue: (OFString *)stringValue; + - (instancetype)init OF_UNAVAILABLE; +/*! + * @brief Initializes an already allocated UTF8String with the specified + * string value. + * + * @param stringValue The string value of the UTF8String + * @return An initialized OFASN1UTF8String + */ +- (instancetype)initWithStringValue: (OFString *)stringValue + OF_DESIGNATED_INITIALIZER; + /*! * @brief Initializes an already allocated ASN.1 UTF8String with the specified * arguments. * * @param tagClass The tag class of the value's type * @param tagNumber The tag number of the value's type * @param constructed Whether the value if of a constructed type * @param DEREncodedContents The DER-encoded contents octets of the value. - * @return An initialized ASN.1 UTF8String + * @return An initialized OFASN1UTF8String */ - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents; @end OF_ASSUME_NONNULL_END Index: src/OFASN1UTF8String.m ================================================================== --- src/OFASN1UTF8String.m +++ src/OFASN1UTF8String.m @@ -24,40 +24,64 @@ #import "OFInvalidArgumentException.h" @implementation OFASN1UTF8String @synthesize UTF8StringValue = _UTF8StringValue; -- (instancetype)init ++ (instancetype)stringWithStringValue: (OFString *)stringValue +{ + return [[[self alloc] initWithStringValue: stringValue] autorelease]; +} + +- (instancetype)initWithStringValue: (OFString *)stringValue { - OF_INVALID_INIT_METHOD + self = [super init]; + + @try { + _UTF8StringValue = [stringValue copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; } - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { - self = [super init]; + void *pool = objc_autoreleasePoolPush(); + OFString *UTF8StringValue; @try { if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL || tagNumber != OF_ASN1_TAG_NUMBER_UTF8_STRING || constructed) @throw [OFInvalidArgumentException exception]; if ([DEREncodedContents itemSize] != 1) @throw [OFInvalidArgumentException exception]; - _UTF8StringValue = [[OFString alloc] - initWithUTF8String: [DEREncodedContents items] - length: [DEREncodedContents count]]; + UTF8StringValue = [OFString + stringWithUTF8String: [DEREncodedContents items] + length: [DEREncodedContents count]]; } @catch (id e) { [self release]; @throw e; } + self = [self initWithStringValue: UTF8StringValue]; + + objc_autoreleasePoolPop(pool); + return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_UTF8StringValue release]; Index: src/OFASN1Value.m ================================================================== --- src/OFASN1Value.m +++ src/OFASN1Value.m @@ -38,15 +38,10 @@ tagNumber: tagNumber constructed: constructed DEREncodedContents: DEREncodedContents] autorelease]; } -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - - (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass tagNumber: (of_asn1_tag_number_t)tagNumber constructed: (bool)constructed DEREncodedContents: (OFData *)DEREncodedContents { @@ -65,10 +60,15 @@ @throw e; } return self; } + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} - (void)dealloc { [_DEREncodedContents release];