├── LICENSE ├── README.md └── code ├── CompliConfig.xsd ├── CompliXML.xsd ├── common.h ├── compli_v2.rc ├── compli_v2.vcxproj ├── internal_base64.h ├── internal_basicfuncs.h ├── internal_basictypes.h ├── internal_transformfuncs.h ├── internal_utf8stream.h ├── main_file.cpp ├── resource.h ├── stage10.xslt ├── type_bitstring.h ├── type_boolean.h ├── type_date_times.h ├── type_datetimes.h ├── type_eoc.h ├── type_integer.h ├── type_null.h ├── type_objid.h ├── type_octetstring.h ├── type_real.h ├── type_sequence.h ├── type_set.h └── type_strings.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2018, Yury Strozhevsky 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | In 2012 before I have written [my article](http://www.strozhevsky.com/free_docs/asn1_in_simple_words.pdf) I inspected several existing implementations of ASN.1 coder/decoder functionality. It was sad, but I found few (frankly speaking sometime not a few) mistakes in such programs delivering on a market. Of course I wrote all the mistakes to developers. But at the same time I understud that there is no freely available ASN.1 coder/decoder. Yes, there are many of such implementations but there is no implementation for all ASN.1:2008 data type together with BER encoding rules. So, I decided to create one :) Also the coder/decoder gave me a greate help on creating [my ASN.1:2008 test suite](https://github.com/YuryStrozhevsky/ASN1-2008-free-test-suite). 4 | 5 | ## Words about BER (Basic Encoding Rules) 6 | 7 | Almost all specialists know about ASN.1, some of them know about DER (Distinguished Encoding Rules). DER is using widely in crypto and all other stuf. But only less part of the specialist working with ASN.1 know that DER is a simple set of restrictions on a bigger set of rules - BER. That is it - BER is much bigger than DER. These are a really "basic ASN.1 rules", DER is a secondary sub-set of these rules. Please keep it in mind, take a look at my code and get all knowledge about a real (not cutted) ASN.1 power! 8 | 9 | ## ASN1js project 10 | 11 | In 2014 I made a project [ASN1js](https://github.com/GlobalSign/ASN1.js). This is an ASN.1 BER encoder/decoder on JavaScript language. In fact all code for [ASN1js](https://github.com/GlobalSign/ASN1.js) is a "porting" from this project code, from C++ to JavaScript. Also the same was using inside [PKIjs](https://github.com/GlobalSign/PKI.js) project. [ASN1js](https://github.com/GlobalSign/ASN1.js) has many improvements related to ASN.1 schema validation. Also because of JavaScript [ASN1js](https://github.com/GlobalSign/ASN1.js) has some limitations and slightly diferent code structure. For the moment I have a plans to back-port all [ASN1js](https://github.com/GlobalSign/ASN1.js) improvements to C++ project. Coming soon! 12 | 13 | ## Features of C++ ASN.1:2008 BER coder/encoder 14 | 15 | * Really BER coder/decoder (hence DER and CER will be processed as well); 16 | * Three formats of input/output data: 17 | * Binary raw data; 18 | * BASE-64 encoded binary raw data; 19 | * XER-like XML files; 20 | * Working with all datatypes from latest ASN.1:2008 standard; 21 | * Fully object-oriented C++ code; 22 | * Layered code, can be easily extended; 23 | * A bulk mode (working with many files at once); 24 | * Special XML format (input and output) can help to understand all details of ASN. in a structured form; 25 | * Output XML files may be used as an input for backward encoding into BER; 26 | * All XML structures described in well-documented XSD; 27 | 28 | ## Usage 29 | 30 | Firstly you need to create a configuration file. Schema for configuration file is inside "code/CompliConfig.xsd". Example of such configuration: 31 | ```xml 32 | 33 | 34 | 35 | 36 | BER 37 | example.ber 38 | 39 | 40 | XML 41 | example.xml 42 | 43 | 44 | 45 | ``` 46 | 47 | There could be many "file_group" regions (and hence many files). Possible formats: 48 | * BER 49 | * BER64 50 | * XML 51 | 52 | Usually output of the program is XML. But please keep in mind - the output XML may be used as an input! Yes, you can parse BER (DER, CER) ASN.1 binary data, get XML file, change in this XML file whatever you want and encode it back to binary. Is not it funny? :) Schema for output/input XML is in "code/CompliXML.xsd". 53 | 54 | ## Limitations 55 | 56 | * Windows-only project; 57 | * MSXML6 library need to be installed; 58 | 59 | ## License 60 | 61 | Copyright (c) 2014, [Yury Strozhevsky](http://www.strozhevsky.com/) 62 | All rights reserved. 63 | 64 | Redistribution and use in source and binary forms, with or without 65 | modification, are permitted provided that the following conditions are met: 66 | 67 | * Redistributions of source code must retain the above copyright notice, this 68 | list of conditions and the following disclaimer. 69 | 70 | * Redistributions in binary form must reproduce the above copyright notice, 71 | this list of conditions and the following disclaimer in the documentation 72 | and/or other materials provided with the distribution. 73 | 74 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 75 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 76 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 77 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 78 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 79 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 80 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 81 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 82 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 83 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /code/CompliConfig.xsd: -------------------------------------------------------------------------------- 1 | Root element of configuration 2 | -------------------------------------------------------------------------------- /code/common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/common.h -------------------------------------------------------------------------------- /code/compli_v2.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/compli_v2.rc -------------------------------------------------------------------------------- /code/compli_v2.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {C1E3155E-BDC1-43F2-8F92-5EFDA6A1433C} 23 | Win32Proj 24 | compli_v2 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | v110 32 | 33 | 34 | Application 35 | true 36 | Unicode 37 | v110 38 | 39 | 40 | Application 41 | false 42 | true 43 | Unicode 44 | v110 45 | 46 | 47 | Application 48 | false 49 | true 50 | Unicode 51 | v110 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | AllRules.ruleset 72 | true 73 | false 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | 99 | 100 | true 101 | 102 | 103 | 104 | 105 | 106 | 107 | Level3 108 | Disabled 109 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | 111 | 112 | Console 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | 121 | 122 | MaxSpeed 123 | true 124 | true 125 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | 127 | 128 | Console 129 | true 130 | true 131 | true 132 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 133 | 134 | 135 | 136 | 137 | 138 | 139 | Level3 140 | 141 | 142 | MaxSpeed 143 | true 144 | true 145 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | 147 | 148 | Console 149 | true 150 | true 151 | true 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /code/internal_base64.h: -------------------------------------------------------------------------------- 1 | #ifndef _43602737_A607_4BE4_8C34_199C2CA3F292 2 | #define _43602737_A607_4BE4_8C34_199C2CA3F292 3 | //*************************************************************************** 4 | template< class _in, class _out > 5 | void base64_encode( _in _in_iterator, _in _end_of_in, _out _out_iterator ) 6 | { 7 | int BLOCK = 192; 8 | 9 | std::vector< char > buf; 10 | buf.reserve( BLOCK ); 11 | 12 | int count; 13 | int string_len=0; 14 | int len; 15 | 16 | while(_in_iterator!=_end_of_in) 17 | { 18 | buf.clear(); 19 | count=0; 20 | 21 | for( ; ( ( _in_iterator != _end_of_in ) && ( count < BLOCK ) ); _in_iterator++, count++ ) 22 | buf.push_back( *_in_iterator ); 23 | 24 | if( count < BLOCK ) 25 | buf.resize( count ); 26 | 27 | len = 0; 28 | 29 | len = Base64EncodeGetRequiredLength( buf.size(), 30 | ( _in_iterator == _end_of_in ) ? ATL_BASE64_FLAG_NOCRLF : ( ATL_BASE64_FLAG_NOPAD | ATL_BASE64_FLAG_NOCRLF ) 31 | ); 32 | 33 | LPSTR temp_string = static_cast< LPSTR >( malloc( len + 1 ) ); 34 | if( !temp_string ) 35 | return; 36 | ZeroMemory( temp_string, len + 1 ); 37 | 38 | Base64Encode( reinterpret_cast< const BYTE* >( &buf[ 0 ] ), 39 | buf.size(), 40 | temp_string, 41 | &len, 42 | ( _in_iterator == _end_of_in ) ? ATL_BASE64_FLAG_NOCRLF : ( ATL_BASE64_FLAG_NOPAD | ATL_BASE64_FLAG_NOCRLF ) 43 | ); 44 | 45 | for( unsigned int i = 0; i < strlen( temp_string ); i++ ) 46 | { 47 | _out_iterator = temp_string[ i ]; 48 | string_len++; 49 | if( string_len > 59 ) 50 | { 51 | string_len = 0; 52 | _out_iterator = '\r'; 53 | _out_iterator = '\n'; 54 | } 55 | } 56 | 57 | ZeroMemory( temp_string, len + 1 ); 58 | free( temp_string ); 59 | } 60 | 61 | _out_iterator = '\r'; 62 | _out_iterator = '\n'; 63 | } 64 | //*************************************************************************** 65 | template< class _in, class _out > 66 | void base64_decode( _in _in_iterator, _in _end_of_in, _out _out_iterator ) 67 | { 68 | std::vector< char > string_vector; 69 | 70 | int BLOCK = 1024; 71 | 72 | std::vector< char > buf; 73 | buf.reserve( BLOCK ); 74 | 75 | int count; 76 | int string_len = 0; 77 | 78 | while( _in_iterator != _end_of_in ) 79 | { 80 | buf.clear(); 81 | count = 0; 82 | 83 | for(; ( ( _in_iterator != _end_of_in ) && ( count < BLOCK ) ); ++_in_iterator, count++ ) 84 | buf.push_back( *_in_iterator ); 85 | 86 | if( count < BLOCK ) 87 | buf.resize( count ); 88 | 89 | #pragma warning( push ) 90 | #pragma warning( disable: 6309 ) 91 | string_len = 0; 92 | Base64Decode( ( LPCSTR )&buf[ 0 ], 93 | buf.size(), 94 | NULL, 95 | &string_len 96 | ); 97 | string_vector.resize( string_len ); 98 | Base64Decode( ( LPCSTR )&buf[0], 99 | buf.size(), 100 | ( BYTE* )&string_vector[0], 101 | &string_len 102 | ); 103 | #pragma warning( pop ) 104 | 105 | std::copy( string_vector.begin(), string_vector.end(), _out_iterator ); 106 | } 107 | } 108 | //*************************************************************************** 109 | #endif -------------------------------------------------------------------------------- /code/internal_basicfuncs.h: -------------------------------------------------------------------------------- 1 | #ifndef _870E69C1_1A78_42FD_93E5_5BA828575D99 2 | #define _870E69C1_1A78_42FD_93E5_5BA828575D99 3 | //************************************************************************** 4 | template< class T, class V > 5 | T value_init( T stream, 6 | unsigned long long max_block_len, 7 | BASIC_type** ret_info, 8 | inform_block* inf_block, 9 | length_block* len_block ) 10 | { 11 | delete (*ret_info); // delete previously created "BASIC_type" object instance 12 | 13 | V* type = new V(); 14 | 15 | type->inf_block = inf_block; 16 | type->len_block = len_block; 17 | 18 | type->add_warnings( inf_block ); 19 | type->add_warnings( len_block ); 20 | 21 | T end = type->decode_value( stream, 22 | ( len_block->is_indefinite_form ) ? max_block_len : len_block->length ); 23 | 24 | (*ret_info) = type; 25 | 26 | return end; 27 | } 28 | //************************************************************************** 29 | template< typename T > 30 | T type_init( T stream, 31 | unsigned long long max_block_len, 32 | BASIC_type** ret_info ) 33 | { 34 | (*ret_info) = new BASIC_type(); // in case we will not find any specific value decoding 35 | 36 | if( stream == T() ) 37 | { 38 | sprintf_s( (*ret_info)->error, 255, "NULL stream is unaccepted" ); 39 | return T(); 40 | } 41 | 42 | if( !max_block_len ) // No error, just return empty type 43 | return T(); 44 | 45 | //-------------------------------- 46 | inform_block* inf_block = new inform_block(); 47 | 48 | T end = inf_block->decode_value( stream, max_block_len ); 49 | if( inf_block->error[ 0 ] != 0x00 ) 50 | { 51 | sprintf_s( (*ret_info)->error, 255, inf_block->error ); 52 | 53 | delete inf_block; 54 | 55 | return end; 56 | } 57 | 58 | max_block_len -= inf_block->block_length; 59 | 60 | length_block* len_block = new length_block(); 61 | 62 | end = len_block->decode_value( end, max_block_len ); 63 | if( len_block->error[ 0 ] != 0x00 ) // Give a chance to process in case of zero-length value block 64 | { 65 | sprintf_s( (*ret_info)->error, 255, len_block->error ); 66 | 67 | delete inf_block; 68 | delete len_block; 69 | 70 | return end; 71 | } 72 | 73 | max_block_len -= len_block->block_length; 74 | 75 | // Check for usign indefinite length form in encoding for primitive types 76 | if( ( inf_block->tag_class == 1 ) && 77 | ( len_block->is_indefinite_form ) ) 78 | { 79 | switch( inf_block->tag_number ) 80 | { 81 | case 1: // BOOLEAN 82 | case 2: // INTEGER 83 | case 5: // NULL 84 | case 6: // OBJECT IDENTIFIER 85 | case 9: // REAL 86 | case 14: // TIME 87 | case 23: 88 | case 24: 89 | case 31: 90 | case 32: 91 | case 33: 92 | case 34: 93 | sprintf_s( (*ret_info)->error, 255, "Indefinite length form used for primitive type" ); 94 | 95 | delete inf_block; 96 | delete len_block; 97 | 98 | return T(); 99 | default: 100 | ; 101 | } 102 | } 103 | 104 | //-------------------------------- 105 | 106 | switch( inf_block->tag_class ) 107 | { 108 | case 1: // UNIVERSAL 109 | if( ( inf_block->tag_number >= 37 ) && ( !inf_block->is_too_long_tag ) ) 110 | { 111 | sprintf_s( (*ret_info)->error, 255, "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard" ); 112 | return T(); 113 | } 114 | 115 | switch( inf_block->tag_number ) 116 | { 117 | case 0: // Hopefuly EOC_type (end-of-content) 118 | if( inf_block->is_constructed || len_block->length ) 119 | { 120 | sprintf_s( (*ret_info)->error, 255, "Type [UNIVERSAL 0] is reserved" ); 121 | return T(); 122 | } 123 | 124 | return value_init< T, EOC_type >( end, 125 | max_block_len, 126 | ret_info, 127 | inf_block, 128 | len_block ); 129 | break; 130 | case 1: // BOOLEAN 131 | return value_init< T, BOOLEAN_type >( end, 132 | max_block_len, 133 | ret_info, 134 | inf_block, 135 | len_block ); 136 | break; 137 | case 2: // INTEGER 138 | return value_init< T, INTEGER_type >( end, 139 | max_block_len, 140 | ret_info, 141 | inf_block, 142 | len_block ); 143 | break; 144 | case 3: // BITSTRING 145 | return value_init< T, BITSTRING_type >( end, 146 | max_block_len, 147 | ret_info, 148 | inf_block, 149 | len_block ); 150 | break; 151 | case 4: // OCTETSTRING 152 | return value_init< T, OCTETSTRING_type >( end, 153 | max_block_len, 154 | ret_info, 155 | inf_block, 156 | len_block ); 157 | break; 158 | case 5: // NULL 159 | return value_init< T, NULL_type >( end, 160 | max_block_len, 161 | ret_info, 162 | inf_block, 163 | len_block ); 164 | break; 165 | case 6: // OBJECT IDENTIFIER 166 | return value_init< T, OID_type >( end, 167 | max_block_len, 168 | ret_info, 169 | inf_block, 170 | len_block ); 171 | break; 172 | case 7: // OBJECT DESCRIPTOR 173 | return value_init< T, OBJECTDESCRIPTOR_type >( end, 174 | max_block_len, 175 | ret_info, 176 | inf_block, 177 | len_block ); 178 | break; 179 | case 8: // EXTERNAL TYPE 180 | return value_init< T, EXTERNAL_type >( end, 181 | max_block_len, 182 | ret_info, 183 | inf_block, 184 | len_block ); 185 | break; 186 | case 9: // REAL 187 | return value_init< T, REAL_type >( end, 188 | max_block_len, 189 | ret_info, 190 | inf_block, 191 | len_block ); 192 | break; 193 | case 10: // ENUMERATED 194 | return value_init< T, ENUMERATED_type >( end, 195 | max_block_len, 196 | ret_info, 197 | inf_block, 198 | len_block ); 199 | break; 200 | case 11: // EMBEDDED PDV 201 | return value_init< T, EMBEDDEDPDV_type >( end, 202 | max_block_len, 203 | ret_info, 204 | inf_block, 205 | len_block ); 206 | break; 207 | case 12: // UTF8STRING 208 | return value_init< T, UTF8STRING_type >( end, 209 | max_block_len, 210 | ret_info, 211 | inf_block, 212 | len_block ); 213 | break; 214 | case 13: // RELATIVE OBJECT IDENTIFIER 215 | return value_init< T, ROID_type >( end, 216 | max_block_len, 217 | ret_info, 218 | inf_block, 219 | len_block ); 220 | break; 221 | case 14: // TIME 222 | return value_init< T, TIME_type >( end, 223 | max_block_len, 224 | ret_info, 225 | inf_block, 226 | len_block ); 227 | break; 228 | case 15: 229 | sprintf_s( (*ret_info)->error, 255, "[UNIVERSAL 15] is reserved by ASN.1 standard" ); 230 | return T(); 231 | 232 | break; 233 | case 16: // SEQUENCE 234 | return value_init< T, SEQUENCE_type >( end, 235 | max_block_len, 236 | ret_info, 237 | inf_block, 238 | len_block ); 239 | break; 240 | case 17: // SET 241 | return value_init< T, SET_type >( end, 242 | max_block_len, 243 | ret_info, 244 | inf_block, 245 | len_block ); 246 | break; 247 | case 18: // NUMERICSTRING 248 | return value_init< T, NUMERICSTRING_type >( end, 249 | max_block_len, 250 | ret_info, 251 | inf_block, 252 | len_block ); 253 | break; 254 | case 19: // PRINTABLESTRING 255 | return value_init< T, PRINTABLESTRING_type >( end, 256 | max_block_len, 257 | ret_info, 258 | inf_block, 259 | len_block ); 260 | break; 261 | case 20: // TELETEXSTRING 262 | return value_init< T, TELETEXSTRING_type >( end, 263 | max_block_len, 264 | ret_info, 265 | inf_block, 266 | len_block ); 267 | break; 268 | case 21: // VIDEOTEXSTRING 269 | return value_init< T, VIDEOTEXSTRING_type >( end, 270 | max_block_len, 271 | ret_info, 272 | inf_block, 273 | len_block ); 274 | break; 275 | case 22: // IA5STRING 276 | return value_init< T, IA5STRING_type >( end, 277 | max_block_len, 278 | ret_info, 279 | inf_block, 280 | len_block ); 281 | break; 282 | case 23: // UTCTIME 283 | return value_init< T, UTCTIME_type >( end, 284 | max_block_len, 285 | ret_info, 286 | inf_block, 287 | len_block ); 288 | break; 289 | case 24: // GENERALIZEDTIME 290 | return value_init< T, GENERALIZEDTIME_type >( end, 291 | max_block_len, 292 | ret_info, 293 | inf_block, 294 | len_block ); 295 | break; 296 | case 25: // GRAPHICSTRING 297 | return value_init< T, GRAPHICSTRING_type >( end, 298 | max_block_len, 299 | ret_info, 300 | inf_block, 301 | len_block ); 302 | break; 303 | case 26: // VISIBLESTRING 304 | return value_init< T, VISIBLESTRING_type >( end, 305 | max_block_len, 306 | ret_info, 307 | inf_block, 308 | len_block ); 309 | break; 310 | case 27: // GENERALSTRING 311 | return value_init< T, GENERALSTRING_type >( end, 312 | max_block_len, 313 | ret_info, 314 | inf_block, 315 | len_block ); 316 | break; 317 | case 28: // UNIVERSALSTRING 318 | return value_init< T, UNIVERSALSTRING_type >( end, 319 | max_block_len, 320 | ret_info, 321 | inf_block, 322 | len_block ); 323 | break; 324 | case 29: // CHARACTERSTRING 325 | return value_init< T, CHARACTERSTRING_type >( end, 326 | max_block_len, 327 | ret_info, 328 | inf_block, 329 | len_block ); 330 | break; 331 | case 30: // BMPSTRING 332 | return value_init< T, BMPSTRING_type >( end, 333 | max_block_len, 334 | ret_info, 335 | inf_block, 336 | len_block ); 337 | break; 338 | case 31: // DATE 339 | return value_init< T, DATE_type >( end, 340 | max_block_len, 341 | ret_info, 342 | inf_block, 343 | len_block ); 344 | break; 345 | case 32: // TIME-OF-DAY 346 | return value_init< T, TIMEOFDAY_type >( end, 347 | max_block_len, 348 | ret_info, 349 | inf_block, 350 | len_block ); 351 | break; 352 | case 33: // DATE-TIME 353 | return value_init< T, DATETIME_type >( end, 354 | max_block_len, 355 | ret_info, 356 | inf_block, 357 | len_block ); 358 | break; 359 | case 34: // DURATION 360 | return value_init< T, DURATION_type >( end, 361 | max_block_len, 362 | ret_info, 363 | inf_block, 364 | len_block ); 365 | break; 366 | case 35: // OID INTERNATIONALIZED 367 | return value_init< T, OIDINTER_type >( end, 368 | max_block_len, 369 | ret_info, 370 | inf_block, 371 | len_block ); 372 | break; 373 | case 36: // RELATIVE OID INTERNATIONALIZED 374 | return value_init< T, ROIDINTER_type >( end, 375 | max_block_len, 376 | ret_info, 377 | inf_block, 378 | len_block ); 379 | break; 380 | default: // Decoding for unknown types 381 | if( inf_block->is_constructed ) 382 | return value_init< T, CONSTRUCTED_type >( end, 383 | max_block_len, 384 | ret_info, 385 | inf_block, 386 | len_block ); 387 | else 388 | return value_init< T, PRIMITIVE_type< unsigned char* > >( end, 389 | max_block_len, 390 | ret_info, 391 | inf_block, 392 | len_block ); 393 | } 394 | break; 395 | case 2: // APPLICATION 396 | case 3: // CONTEXT-SPECIFIC 397 | case 4: // PRIVATE 398 | default: // Decoding for unknown types 399 | if( inf_block->is_constructed ) 400 | return value_init< T, CONSTRUCTED_type >( end, 401 | max_block_len, 402 | ret_info, 403 | inf_block, 404 | len_block ); 405 | else 406 | return value_init< T, PRIMITIVE_type< unsigned char* > >( end, 407 | max_block_len, 408 | ret_info, 409 | inf_block, 410 | len_block ); 411 | } 412 | 413 | return end; 414 | } 415 | //************************************************************************** 416 | #endif -------------------------------------------------------------------------------- /code/internal_transformfuncs.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/internal_transformfuncs.h -------------------------------------------------------------------------------- /code/internal_utf8stream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _A5290D64_13FD_48B5_B618_C63F11DC2446 27 | #define _A5290D64_13FD_48B5_B618_C63F11DC2446 28 | //************************************************************************** 29 | // Came from http://www.rsdn.ru/forum/cpp/1948543.1.aspx 30 | //************************************************************************** 31 | /** Conversion facet that allows to read Unicode files in UTF-8 encoding */ 32 | class utf8_conversion 33 | : public std::codecvt 34 | { 35 | protected: 36 | 37 | result do_in(std::mbstate_t& state, 38 | const char* from, const char* from_end, const char*& from_next, 39 | wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const; 40 | 41 | result do_out(std::mbstate_t& state, 42 | const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, 43 | char* to, char* to_limit, char*& to_next) const; 44 | 45 | bool do_always_noconv() const throw() { return false; } 46 | int do_encoding() const throw() { return 2; } 47 | }; 48 | //************************************************************************** 49 | typedef unsigned char uchar; 50 | //************************************************************************** 51 | inline unsigned char 52 | take_6_bits(unsigned value, size_t right_position) 53 | { 54 | return uchar((value >> right_position) & 63); 55 | } 56 | //************************************************************************** 57 | inline int 58 | most_signifant_bit_position(unsigned value) 59 | { 60 | int result(0); 61 | 62 | int half = 16; 63 | for(; half > 0; half >>= 1) { 64 | if (1u << (result + half) <= value ) result += half; 65 | } 66 | return result + 1; 67 | } 68 | //************************************************************************** 69 | utf8_conversion::result 70 | utf8_conversion::do_in(mbstate_t&, 71 | const char* from, const char* from_end, const char*& from_next, 72 | wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const 73 | { 74 | from_next = from; 75 | to_next = to; 76 | 77 | for(; to_next < to_limit && from_next < from_end; ++to_next) { 78 | 79 | if (uchar(*from_next) < 0x80) *to_next = uchar(*from_next++); 80 | else { 81 | 82 | // 111zxxxx : z = 0 xxxx are data bits 83 | int zero_bit_pos = most_signifant_bit_position(~*from_next); 84 | int extra_bytes = 7 - zero_bit_pos; 85 | 86 | if (from_end - from_next < extra_bytes + 1) 87 | return partial; 88 | 89 | *to_next = uchar(*from_next++) & ( ( ( 1 << zero_bit_pos ) - 1) - 1); 90 | 91 | for (;extra_bytes--; ++from_next) { 92 | *to_next = *to_next << 6 | uchar(*from_next) & 63; 93 | } 94 | } 95 | } 96 | return ok; 97 | } 98 | //************************************************************************** 99 | utf8_conversion::result 100 | utf8_conversion::do_out(mbstate_t&, 101 | const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, 102 | char* to, char* to_limit, char*& to_next) const 103 | { 104 | from_next = from; 105 | to_next = to; 106 | 107 | for (;from_next < from_end; ++from_next) { 108 | 109 | unsigned symbol = *from_next; 110 | 111 | if (symbol < 0x7F) { 112 | if (to_next < to_limit) 113 | *to_next++ = (unsigned char)symbol; 114 | else 115 | return ok; 116 | } else { 117 | 118 | int msb_pos = most_signifant_bit_position(symbol); 119 | int extra_bytes = msb_pos / 6; 120 | 121 | if (to_limit - to_next >= extra_bytes + 1) { 122 | 123 | *to_next = uchar(0xFF80 >> extra_bytes); 124 | *to_next++ |= take_6_bits(symbol, extra_bytes*6); 125 | 126 | for(;extra_bytes--;) 127 | *to_next++ = 0x80 | take_6_bits(symbol, extra_bytes*6); 128 | } 129 | else 130 | return ok; 131 | } 132 | } 133 | return ok; 134 | } 135 | //************************************************************************** 136 | namespace std 137 | { 138 | template inline 140 | basic_ostream<_Elem, _Traits>& 141 | __CLRCALL_OR_CDECL endlu(basic_ostream<_Elem, _Traits>& _Ostr) 142 | { // insert newline and flush stream 143 | _Ostr.put(_Ostr.widen('\r')); 144 | _Ostr.put(_Ostr.widen('\n')); 145 | _Ostr.flush(); 146 | return (_Ostr); 147 | } 148 | }; 149 | //************************************************************************** 150 | class no_conversion 151 | : public std::codecvt 152 | { 153 | protected: 154 | 155 | result do_in(std::mbstate_t& state, 156 | const char* from, const char* from_end, const char*& from_next, 157 | wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const { return noconv; }; 158 | 159 | result do_out(std::mbstate_t& state, 160 | const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, 161 | char* to, char* to_limit, char*& to_next) const { return noconv; }; 162 | 163 | bool do_always_noconv() const throw() { return true; } 164 | int do_encoding() const throw() { return 2; } 165 | }; 166 | //************************************************************************** 167 | #endif -------------------------------------------------------------------------------- /code/main_file.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #import 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #pragma warning( disable : 4250 ) 44 | 45 | #include "internal_utf8stream.h" 46 | #include "internal_base64.h" 47 | #include "common.h" 48 | #include "internal_basictypes.h" 49 | #include "internal_transformfuncs.h" 50 | #include "type_integer.h" 51 | #include "type_objid.h" 52 | #include "type_real.h" 53 | #include "type_boolean.h" 54 | #include "type_null.h" 55 | #include "type_eoc.h" 56 | #include "type_bitstring.h" 57 | #include "type_octetstring.h" 58 | #include "type_sequence.h" 59 | #include "type_strings.h" 60 | #include "type_date_times.h" 61 | 62 | #include "resource.h" 63 | //************************************************************************** 64 | struct file_element 65 | { 66 | std::wstring format; 67 | std::wstring name; 68 | }; 69 | struct file_group 70 | { 71 | file_element* in; 72 | file_element* out; 73 | 74 | file_group(); 75 | ~file_group(); 76 | }; 77 | file_group::file_group() : in( NULL), 78 | out( NULL ) 79 | { 80 | } 81 | file_group::~file_group() 82 | { 83 | if( in != NULL ) 84 | delete in; 85 | 86 | if( out != NULL ) 87 | delete out; 88 | } 89 | std::vector< file_group* > configuration; 90 | //************************************************************************** 91 | void usage() 92 | { 93 | std::cout << "compli - fully-compliant ASN.1 BER decoder/encoder, v2.0" << std::endl; 94 | std::cout << "(c) 2012, Yury Strozhevsky, www.strozhevsky.com" << std::endl; 95 | std::cout << std::endl << "Usage:" << std::endl; 96 | std::cout << "\tcompli.exe " << std::endl; 97 | } 98 | //************************************************************************** 99 | int init_configuration( char** argv ) 100 | { 101 | MSXML2::IXMLDOMDocument2Ptr pXSDDoc; 102 | HRESULT hr = pXSDDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER); 103 | 104 | pXSDDoc->async = VARIANT_FALSE; 105 | pXSDDoc->validateOnParse = VARIANT_FALSE; 106 | 107 | HRSRC xsd_res = ::FindResource(NULL, MAKEINTRESOURCE( IDR_CONFIGXSD ), RT_RCDATA); 108 | if( !xsd_res ) 109 | return 0; 110 | 111 | unsigned int xsd_res_size = ::SizeofResource( NULL, xsd_res ); 112 | HGLOBAL xsd_res_global_data = ::LoadResource( NULL, xsd_res ); 113 | if( !xsd_res_global_data ) 114 | return 0; 115 | 116 | char* xsd_res_data = ( char* )::LockResource( xsd_res_global_data ); 117 | 118 | wchar_t* wxsd = ( wchar_t* ) malloc( ( xsd_res_size + 1 ) * sizeof( wchar_t ) ); 119 | if( !wxsd ) 120 | return 0; 121 | 122 | size_t converted = 0; 123 | errno_t errnum = mbstowcs_s( &converted, wxsd, xsd_res_size + 1, xsd_res_data, xsd_res_size ); 124 | if( errnum && !converted ) 125 | return 0; 126 | 127 | VARIANT_BOOL result = pXSDDoc->loadXML( wxsd ); 128 | 129 | free( wxsd ); 130 | 131 | if( result == VARIANT_FALSE ) 132 | { 133 | std::cout << "Failed to load resource with XSD schema, exiting" << std::endl; 134 | return 0; 135 | } 136 | 137 | MSXML2::IXMLDOMSchemaCollectionPtr xsd_schema; 138 | hr = xsd_schema.CreateInstance( __uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER ); 139 | hr = xsd_schema->add(L"", pXSDDoc.GetInterfacePtr() ); 140 | if( FAILED( hr ) ) 141 | { 142 | std::cout << "Unable to load CompliXML.xsd schema file, exiting" << std::endl; 143 | return 0; 144 | } 145 | 146 | MSXML2::IXMLDOMDocument3Ptr xml_document; 147 | hr = xml_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 148 | 149 | size_t len = strlen( argv[ 1 ] ); 150 | wchar_t* whex = ( wchar_t* ) malloc( ( len + 1 ) * sizeof( wchar_t ) ); 151 | 152 | converted = 0; 153 | errno_t error_num = mbstowcs_s( &converted, whex, len + 1, argv[ 1 ], len ); 154 | if( error_num ) 155 | { 156 | free( whex ); 157 | return 0; 158 | } 159 | 160 | VARIANT_BOOL loaded = xml_document->load( whex ); 161 | free( whex ); 162 | 163 | if( loaded == VARIANT_FALSE ) 164 | { 165 | std::cout << "Unable to load configuration file: " << argv[ 1 ] << ", exiting" << std::endl; 166 | return 0; 167 | } 168 | 169 | xml_document->schemas = xsd_schema.GetInterfacePtr(); 170 | 171 | MSXML2::IXMLDOMParseErrorPtr pError = xml_document->validate(); 172 | if (pError->errorCode != 0) 173 | { 174 | std::cout << "Problem during XML validation of config file: " << std::endl; 175 | std::cout << "---------------------------------------------" << std::endl; 176 | char* error = to_console_cp( (char*)pError->Getreason() ); 177 | if( error ) 178 | { 179 | std::cout << error << std::endl; 180 | std::cout << "--------------------------------------------" << std::endl; 181 | free( error ); 182 | } 183 | 184 | return 0; 185 | } 186 | 187 | MSXML2::IXMLDOMNodeListPtr list = xml_document->selectNodes( L"/config/file_group" ); 188 | if( !list ) 189 | return 0; 190 | 191 | for( int i = 0; i < list->length; i++ ) 192 | { 193 | file_group* fg = new file_group(); 194 | 195 | MSXML2::IXMLDOMNodePtr in_xml = list->item[ i ]->selectSingleNode( L"in" ); 196 | if( !in_xml ) 197 | return 0; 198 | 199 | MSXML2::IXMLDOMElementPtr format_xml = in_xml->selectSingleNode( L"format" ); 200 | if( !format_xml ) 201 | return 0; 202 | 203 | fg->in = new file_element(); 204 | fg->in->format = ( wchar_t* ) format_xml->text; 205 | 206 | MSXML2::IXMLDOMElementPtr name_xml = in_xml->selectSingleNode( L"name" ); 207 | if( !name_xml ) 208 | return 0; 209 | 210 | fg->in->name = ( wchar_t* ) name_xml->text; 211 | 212 | MSXML2::IXMLDOMNodePtr out_xml = list->item[ i ]->selectSingleNode( L"out" ); 213 | if( !out_xml ) 214 | return 0; 215 | 216 | MSXML2::IXMLDOMElementPtr format_out_xml = out_xml->selectSingleNode( L"format" ); 217 | if( !format_out_xml ) 218 | return 0; 219 | 220 | fg->out = new file_element(); 221 | fg->out->format = ( wchar_t* ) format_out_xml->text; 222 | 223 | MSXML2::IXMLDOMElementPtr name_out_xml = out_xml->selectSingleNode( L"name" ); 224 | if( !name_out_xml ) 225 | return 0; 226 | 227 | fg->out->name = ( wchar_t* ) name_out_xml->text; 228 | 229 | configuration.push_back( fg ); 230 | } 231 | 232 | return 1; 233 | } 234 | //************************************************************************** 235 | void process_file_group( file_group* fg, MSXML2::IXMLDOMSchemaCollectionPtr xsd_schema ) 236 | { 237 | //------------------------------------------------- 238 | if( fg->in->format == L"XML" ) 239 | { 240 | MSXML2::IXMLDOMDocument3Ptr xml_document; 241 | HRESULT hr = xml_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 242 | xml_document->async = VARIANT_FALSE; 243 | xml_document->validateOnParse = VARIANT_FALSE; 244 | 245 | xml_document->load( fg->in->name.c_str() ); 246 | 247 | xml_document->schemas = xsd_schema.GetInterfacePtr(); 248 | 249 | MSXML2::IXMLDOMParseErrorPtr pError = xml_document->validate(); 250 | if (pError->errorCode != 0) 251 | { 252 | std::cout << "Problem during XML validation of input file: " << std::endl; 253 | std::cout << "--------------------------------------------" << std::endl; 254 | std::wcout << L"File name: " << fg->in->name << std::endl << std::endl; 255 | char* error = to_console_cp( (char*)pError->Getreason() ); 256 | if( error ) 257 | { 258 | std::cout << error << std::endl; 259 | std::cout << "--------------------------------------------" << std::endl; 260 | free( error ); 261 | } 262 | 263 | return; 264 | } 265 | 266 | if( fg->out->format == L"BER" ) 267 | { 268 | char* name = to_acp( fg->out->name.c_str() ); 269 | 270 | std::ofstream ostream( name, std::ios::binary ); 271 | ostream.unsetf( std::ios_base::skipws ); 272 | 273 | free( name ); 274 | 275 | std::ostreambuf_iterator< char > out( ostream ); 276 | 277 | encode_result* result = XML_BER( out, xml_document->documentElement ); 278 | if( result != NULL ) 279 | delete result; 280 | 281 | ostream.flush(); 282 | ostream.close(); 283 | } 284 | if( fg->out->format == L"BER64") 285 | { 286 | char* name = to_acp( fg->out->name.c_str() ); 287 | 288 | std::ofstream ostream( name, std::ios::binary ); 289 | ostream.unsetf( std::ios_base::skipws ); 290 | 291 | free( name ); 292 | 293 | std::ostreambuf_iterator< char > out( ostream ); 294 | 295 | encode_result* result = XML_BER64( out, xml_document->documentElement ); 296 | if( result != NULL ) 297 | delete result; 298 | 299 | ostream.flush(); 300 | ostream.close(); 301 | } 302 | if( fg->out->format == L"XER") 303 | { 304 | } 305 | if( fg->out->format == L"XML") 306 | { 307 | xml_document->save( fg->out->name.c_str() ); 308 | } 309 | } 310 | //------------------------------------------------- 311 | if( fg->in->format == L"BER" ) 312 | { 313 | MSXML2::IXMLDOMDocument3Ptr xml_document, xslt_document; 314 | HRESULT hr = xml_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 315 | hr = xslt_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 316 | 317 | char* name_in = to_acp( fg->in->name.c_str() ); 318 | char* name_out = to_acp( fg->out->name.c_str() ); 319 | 320 | if( fg->out->format == L"XML" ) 321 | { 322 | std::ifstream coded_file( name_in, std::ios_base::binary ); 323 | if( !coded_file.good() ) 324 | { 325 | std::string message = "Unable to open "; 326 | message += name_in; 327 | message += " file!"; 328 | std::cout << message << std::endl; 329 | 330 | free( name_in ); 331 | free( name_out ); 332 | 333 | return; 334 | } 335 | 336 | coded_file.unsetf( std::ios_base::skipws ); 337 | 338 | coded_file.seekg( 0, std::ios::end ); 339 | unsigned long long max_block_len = coded_file.tellg(); 340 | coded_file.seekg( 0, std::ios::beg ); 341 | 342 | BER_XML( std::istreambuf_iterator< char >( coded_file ), max_block_len, xml_document ); 343 | 344 | coded_file.close(); 345 | 346 | HRSRC xslt_res = ::FindResource(NULL, MAKEINTRESOURCE( IDR_XSLT ), RT_RCDATA); 347 | if( !xslt_res ) 348 | { 349 | free( name_in ); 350 | free( name_out ); 351 | return; 352 | } 353 | 354 | unsigned int xslt_res_size = ::SizeofResource( NULL, xslt_res ); 355 | HGLOBAL xslt_res_global_data = ::LoadResource(NULL, xslt_res); 356 | if( !xslt_res_global_data ) 357 | { 358 | free( name_in ); 359 | free( name_out ); 360 | return; 361 | } 362 | 363 | char* xslt_res_data = ( char* )::LockResource( xslt_res_global_data ); 364 | 365 | wchar_t* wxslt = ( wchar_t* ) malloc( ( xslt_res_size + 1 ) * sizeof( wchar_t ) ); 366 | if( !wxslt ) 367 | { 368 | free( name_in ); 369 | free( name_out ); 370 | return; 371 | } 372 | 373 | size_t converted = 0; 374 | errno_t errnum = mbstowcs_s( &converted, wxslt, xslt_res_size + 1, xslt_res_data, xslt_res_size ); 375 | if( errnum && !converted ) 376 | { 377 | free( name_in ); 378 | free( name_out ); 379 | return; 380 | } 381 | 382 | VARIANT_BOOL xslt_result = xslt_document->loadXML( wxslt ); 383 | free( wxslt ); 384 | if( xslt_result == VARIANT_FALSE ) 385 | { 386 | free( name_in ); 387 | free( name_out ); 388 | return; 389 | } 390 | 391 | std::wofstream ostream( name_out, std::ios::binary ); 392 | ostream.unsetf( std::ios_base::skipws ); 393 | ostream.imbue( std::locale( ostream.getloc(), new utf8_conversion() ) ); 394 | std::wstring transformed = ( wchar_t* )xml_document->transformNode( xslt_document ); 395 | ostream << transformed << std::endlu; 396 | ostream.flush(); 397 | ostream.close(); 398 | } 399 | if( fg->out->format == L"BER64") 400 | { 401 | std::ifstream istream( name_in, std::ios_base::binary ); 402 | istream.unsetf( std::ios_base::skipws ); 403 | 404 | std::ofstream ostream( name_out, std::ios::binary ); 405 | ostream.unsetf( std::ios_base::skipws ); 406 | 407 | base64_encode( std::istreambuf_iterator< char >( istream ), std::istreambuf_iterator< char >(), std::ostreambuf_iterator< char > ( ostream ) ); 408 | 409 | ostream.flush(); 410 | ostream.close(); 411 | 412 | istream.close(); 413 | } 414 | if( fg->out->format == L"XER") 415 | { 416 | } 417 | if( fg->out->format == L"BER") 418 | { 419 | std::ifstream istream( name_in, std::ios_base::binary ); 420 | istream.unsetf( std::ios_base::skipws ); 421 | 422 | std::ofstream ostream( name_out, std::ios::binary ); 423 | ostream.unsetf( std::ios_base::skipws ); 424 | 425 | std::copy( std::istreambuf_iterator< char >( istream ), std::istreambuf_iterator< char >(), std::ostreambuf_iterator< char > ( ostream ) ); 426 | 427 | ostream.flush(); 428 | ostream.close(); 429 | 430 | istream.close(); 431 | } 432 | 433 | free( name_in ); 434 | free( name_out ); 435 | } 436 | //------------------------------------------------- 437 | if( fg->in->format == L"BER64" ) 438 | { 439 | MSXML2::IXMLDOMDocument3Ptr xml_document, xslt_document; 440 | HRESULT hr = xml_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 441 | hr = xslt_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 442 | 443 | char* name_in = to_acp( fg->in->name.c_str() ); 444 | char* name_out = to_acp( fg->out->name.c_str() ); 445 | 446 | if( fg->out->format == L"BER" ) 447 | { 448 | std::ifstream istream( name_in, std::ios_base::binary ); 449 | istream.unsetf( std::ios_base::skipws ); 450 | 451 | std::ofstream ostream( name_out, std::ios::binary ); 452 | ostream.unsetf( std::ios_base::skipws ); 453 | 454 | base64_decode( std::istreambuf_iterator< char >( istream ), std::istreambuf_iterator< char >(), std::ostreambuf_iterator< char > ( ostream ) ); 455 | 456 | ostream.flush(); 457 | ostream.close(); 458 | 459 | istream.close(); 460 | } 461 | if( fg->out->format == L"XML") 462 | { 463 | std::ifstream coded_file( name_in, std::ios_base::binary ); 464 | if( !coded_file.good() ) 465 | { 466 | std::string message = "Unable to open "; 467 | message += name_in; 468 | message += " file!"; 469 | std::cout << message << std::endl; 470 | 471 | free( name_in ); 472 | free( name_out ); 473 | 474 | return; 475 | } 476 | 477 | coded_file.unsetf( std::ios_base::skipws ); 478 | 479 | coded_file.seekg( 0, std::ios::end ); 480 | unsigned long long max_block_len = coded_file.tellg(); 481 | coded_file.seekg( 0, std::ios::beg ); 482 | 483 | BER64_XML( std::istreambuf_iterator< char >( coded_file ), max_block_len, xml_document ); 484 | 485 | coded_file.close(); 486 | 487 | HRSRC xslt_res = ::FindResource(NULL, MAKEINTRESOURCE( IDR_XSLT ), RT_RCDATA); 488 | if( !xslt_res ) 489 | { 490 | free( name_in ); 491 | free( name_out ); 492 | return; 493 | } 494 | 495 | unsigned int xslt_res_size = ::SizeofResource( NULL, xslt_res ); 496 | HGLOBAL xslt_res_global_data = ::LoadResource(NULL, xslt_res); 497 | if( !xslt_res_global_data ) 498 | { 499 | free( name_in ); 500 | free( name_out ); 501 | return; 502 | } 503 | 504 | char* xslt_res_data = ( char* )::LockResource( xslt_res_global_data ); 505 | 506 | wchar_t* wxslt = ( wchar_t* ) malloc( ( xslt_res_size + 1 ) * sizeof( wchar_t ) ); 507 | if( !wxslt ) 508 | { 509 | free( name_in ); 510 | free( name_out ); 511 | return; 512 | } 513 | 514 | size_t converted = 0; 515 | errno_t errnum = mbstowcs_s( &converted, wxslt, xslt_res_size + 1, xslt_res_data, xslt_res_size ); 516 | if( errnum && !converted ) 517 | { 518 | free( name_in ); 519 | free( name_out ); 520 | return; 521 | } 522 | 523 | VARIANT_BOOL xslt_result = xslt_document->loadXML( wxslt ); 524 | free( wxslt ); 525 | if( xslt_result == VARIANT_FALSE ) 526 | { 527 | free( name_in ); 528 | free( name_out ); 529 | return; 530 | } 531 | 532 | std::wofstream ostream( name_out, std::ios::binary ); 533 | ostream.unsetf( std::ios_base::skipws ); 534 | ostream.imbue( std::locale( ostream.getloc(), new utf8_conversion() ) ); 535 | std::wstring transformed = ( wchar_t* )xml_document->transformNode( xslt_document ); 536 | ostream << transformed << std::endlu; 537 | ostream.flush(); 538 | ostream.close(); 539 | } 540 | if( fg->out->format == L"XER") 541 | { 542 | } 543 | if( fg->out->format == L"BER64") 544 | { 545 | std::ifstream istream( name_in, std::ios_base::binary ); 546 | istream.unsetf( std::ios_base::skipws ); 547 | 548 | std::ofstream ostream( name_out, std::ios::binary ); 549 | ostream.unsetf( std::ios_base::skipws ); 550 | 551 | std::copy( std::istreambuf_iterator< char >( istream ), std::istreambuf_iterator< char >(), std::ostreambuf_iterator< char > ( ostream ) ); 552 | 553 | ostream.flush(); 554 | ostream.close(); 555 | 556 | istream.close(); 557 | } 558 | 559 | free( name_in ); 560 | free( name_out ); 561 | } 562 | //------------------------------------------------- 563 | if( fg->in->format == L"XER" ) 564 | { 565 | MSXML2::IXMLDOMDocument3Ptr xml_document; 566 | HRESULT hr = xml_document.CreateInstance( __uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER ); 567 | 568 | xml_document->load( fg->in->name.c_str() ); 569 | 570 | if( fg->out->format == L"BER" ) 571 | { 572 | } 573 | if( fg->out->format == L"BER64") 574 | { 575 | } 576 | if( fg->out->format == L"XML") 577 | { 578 | } 579 | if( fg->out->format == L"XER") 580 | { 581 | xml_document->save( fg->out->name.c_str() ); 582 | } 583 | } 584 | //------------------------------------------------- 585 | } 586 | //************************************************************************** 587 | int main( int argc, char** argv ) 588 | { 589 | if( argc != 2 ) 590 | { 591 | usage(); 592 | return 0; 593 | } 594 | 595 | std::cout << "\"compli\" - fully-compliant ASN.1 BER decoder/encoder, v2.0" << std::endl; 596 | std::cout << "(c) 2012, Yury Strozhevsky, www.strozhevsky.com" << std::endl << std::endl; 597 | 598 | HRESULT hr = CoInitialize( NULL ); 599 | if( FAILED( hr ) ) 600 | { 601 | std::cout << "Something wrong with COM initialization, exiting" << std::endl; 602 | return 0; 603 | } 604 | 605 | if( !init_configuration( argv ) ) 606 | { 607 | std::cout << "Unable to process configuration file!" << std::endl; 608 | return 0; 609 | } 610 | 611 | { // additional brackets in order to give MSXML smart pointers a chance to de-init before "CoUninitialize()" 612 | MSXML2::IXMLDOMDocument2Ptr pXSDDoc; 613 | hr = pXSDDoc.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER); 614 | 615 | pXSDDoc->async = VARIANT_FALSE; 616 | pXSDDoc->validateOnParse = VARIANT_FALSE; 617 | 618 | HRSRC xsd_res = ::FindResource(NULL, MAKEINTRESOURCE( IDR_XSD ), RT_RCDATA); 619 | if( !xsd_res ) 620 | return 0; 621 | 622 | unsigned int xsd_res_size = ::SizeofResource( NULL, xsd_res ); 623 | HGLOBAL xsd_res_global_data = ::LoadResource(NULL, xsd_res ); 624 | if( !xsd_res_global_data ) 625 | return 0; 626 | 627 | char* xsd_res_data = ( char* )::LockResource( xsd_res_global_data ); 628 | 629 | wchar_t* wxsd = ( wchar_t* ) malloc( ( xsd_res_size + 1 ) * sizeof( wchar_t ) ); 630 | if( !wxsd ) 631 | return 0; 632 | 633 | size_t converted = 0; 634 | errno_t errnum = mbstowcs_s( &converted, wxsd, xsd_res_size + 1, xsd_res_data, xsd_res_size ); 635 | if( errnum && !converted ) 636 | return 0; 637 | 638 | VARIANT_BOOL result = pXSDDoc->loadXML( wxsd ); 639 | 640 | free( wxsd ); 641 | 642 | if( result == VARIANT_FALSE ) 643 | { 644 | std::cout << "Failed to load resource with XSD schema, exiting" << std::endl; 645 | return 0; 646 | } 647 | 648 | MSXML2::IXMLDOMSchemaCollectionPtr xsd_schema; 649 | hr = xsd_schema.CreateInstance( __uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER ); 650 | hr = xsd_schema->add(L"", pXSDDoc.GetInterfacePtr() ); 651 | if( FAILED( hr ) ) 652 | { 653 | std::cout << "Unable to load CompliXML.xsd schema file, exiting" << std::endl; 654 | return 0; 655 | } 656 | 657 | for( std::vector< file_group* >::iterator i = configuration.begin(); i != configuration.end(); i++ ) 658 | process_file_group( *i, xsd_schema ); 659 | 660 | for( std::vector< file_group* >::iterator i = configuration.begin(); i != configuration.end(); i++ ) 661 | delete (*i); 662 | } 663 | 664 | CoUninitialize(); 665 | 666 | return 0; 667 | } 668 | //************************************************************************** 669 | -------------------------------------------------------------------------------- /code/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder/3b439b2803251b67d0378f656c0eb916a9343945/code/resource.h -------------------------------------------------------------------------------- /code/stage10.xslt: -------------------------------------------------------------------------------- 1 | 1.0UTF-8 2 | -------------------------------------------------------------------------------- /code/type_bitstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _721C770E_3343_41E6_BEBF_F4D465EEFFF9 27 | #define _721C770E_3343_41E6_BEBF_F4D465EEFFF9 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct BITSTRING_value_block : virtual public CONSTRUCTED_value_block< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | unsigned char unused_bits; 34 | bool is_constructed; 35 | 36 | BITSTRING_value_block(); 37 | 38 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 39 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 40 | 41 | virtual In decode_BER( unsigned long long max_block_len ); 42 | virtual unsigned long long encode_BER( bool size_only = false ); 43 | }; 44 | //************************************************************************** 45 | template< typename In, typename Out > 46 | BITSTRING_value_block< In, Out >::BITSTRING_value_block() : unused_bits( 0 ), 47 | is_constructed( false ) 48 | { 49 | } 50 | //************************************************************************** 51 | template< typename In, typename Out > 52 | MSXML2::IXMLDOMElementPtr BITSTRING_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 53 | { 54 | if( is_constructed ) 55 | return CONSTRUCTED_value_block< In, Out >::to_xml( pDoc ); 56 | else 57 | { 58 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 59 | if( error[ 0 ] != 0x00 ) 60 | return result; 61 | 62 | if( !block_length ) 63 | return result; 64 | 65 | wchar_t unused_bits_buf[ 10 ]; 66 | memset( unused_bits_buf, 0x00, 10 * sizeof( wchar_t ) ); 67 | 68 | errno_t error_num = _itow_s( unused_bits, unused_bits_buf, 10, 10 ); 69 | if( error_num ) 70 | return result; 71 | 72 | MSXML2::IXMLDOMElementPtr unused_bits_xml = pDoc->createElement( L"unused_bits" ); 73 | unused_bits_xml->appendChild( pDoc->createTextNode( unused_bits_buf ) ); 74 | 75 | result->appendChild( unused_bits_xml ); 76 | 77 | std::string hex = bit_codes( value_hex, block_length, 0 ); // let's put all bits, together with "unused" 78 | //std::string hex = bit_codes( value_hex, block_length, unused_bits ); 79 | 80 | wchar_t* whex = ( wchar_t* ) malloc( ( hex.length() + 1 ) * sizeof( wchar_t ) ); 81 | memset( whex, 0x00, ( hex.length() + 1 ) * sizeof( wchar_t ) ); 82 | 83 | size_t converted = 0; 84 | error_num = mbstowcs_s( &converted, whex, hex.length() + 1, hex.c_str(), hex.length() ); 85 | if( error_num ) 86 | { 87 | free( whex ); 88 | return result; 89 | } 90 | 91 | MSXML2::IXMLDOMElementPtr value_xml = pDoc->createElement( L"value_hex" ); 92 | value_xml->appendChild( pDoc->createTextNode( whex ) ); 93 | 94 | free( whex ); 95 | 96 | result->appendChild( value_xml ); 97 | 98 | return result; 99 | } 100 | 101 | return NULL; 102 | } 103 | //************************************************************************** 104 | template< typename In, typename Out > 105 | bool BITSTRING_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 106 | { 107 | if( !element ) 108 | return false; 109 | 110 | if( !is_constructed ) // primitive form 111 | { 112 | MSXML2::IXMLDOMElementPtr unused_bits_xml = element->selectSingleNode( L"unused_bits" ); 113 | if( !unused_bits_xml ) 114 | return false; 115 | 116 | unused_bits = _wtoi( ( wchar_t* )unused_bits_xml->text ); 117 | if( errno && !unused_bits ) 118 | return false; 119 | 120 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 121 | if( !value_hex_xml ) 122 | return false; 123 | 124 | std::wstring str_hex = ( wchar_t* ) value_hex_xml->text; 125 | str_hex = wreplace( str_hex.c_str(), L" ", L"" ); 126 | 127 | block_length = from_wbit_codes( str_hex.c_str(), str_hex.length(), &value_hex ); 128 | if( !block_length ) 129 | return false; 130 | 131 | block_length++; // 1 octet for "unused bits" 132 | } 133 | else // constructed form 134 | { 135 | if( !CONSTRUCTED_value_block< In, Out >::from_xml( element ) ) 136 | return false; 137 | 138 | for( std::vector< BASIC_type< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 139 | { 140 | if( (*i)->block_name() != BITSTRING_type< In, Out >::block_name_static() ) 141 | { 142 | value.erase( value.begin(), value.end() ); 143 | sprintf_s( error, 255, "BIT STRING may consists of BIT STRINGs only" ); 144 | return false; 145 | } 146 | 147 | BITSTRING_value_block< In, Out >* constr_value_block = dynamic_cast< BITSTRING_value_block< In, Out >* >( (*i)->value_block ); 148 | 149 | if( unused_bits && constr_value_block->unused_bits ) 150 | { 151 | sprintf_s( error, 255, "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only" ); 152 | return false; 153 | } 154 | else 155 | unused_bits = constr_value_block->unused_bits; 156 | } 157 | } 158 | 159 | return true; 160 | } 161 | //************************************************************************** 162 | template< typename In, typename Out > 163 | In BITSTRING_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 164 | { 165 | if( !max_block_len ) 166 | return stream_in; 167 | 168 | if( stream_in == In() ) 169 | { 170 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 171 | return stream_in; 172 | } 173 | 174 | if( is_constructed ) 175 | { 176 | In end = CONSTRUCTED_value_block< In, Out >::decode_BER( max_block_len ); 177 | if( error[ 0 ] != 0x00 ) 178 | return In(); 179 | 180 | for( std::vector< BASIC_type< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 181 | { 182 | if( (*i)->block_name() == EOC_type< In, Out >::block_name_static() ) 183 | { 184 | if( is_indefinite_form ) 185 | break; 186 | else 187 | { 188 | value.erase( value.begin(), value.end() ); 189 | sprintf_s( error, 255, "EOC is unexpected, BIT STRING may consists of BIT STRINGs only" ); 190 | return In(); 191 | } 192 | } 193 | 194 | if( (*i)->block_name() != BITSTRING_type< In, Out >::block_name_static() ) 195 | { 196 | value.erase( value.begin(), value.end() ); 197 | sprintf_s( error, 255, "BIT STRING may consists of BIT STRINGs only" ); 198 | return In(); 199 | } 200 | 201 | BITSTRING_value_block< In, Out >* constr_value_block = dynamic_cast< BITSTRING_value_block< In, Out >* >( (*i)->value_block ); 202 | 203 | if( unused_bits && constr_value_block->unused_bits ) 204 | { 205 | value.erase( value.begin(), value.end() ); 206 | sprintf_s( error, 255, "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only" ); 207 | return In(); 208 | } 209 | else 210 | { 211 | unused_bits = constr_value_block->unused_bits; 212 | if( unused_bits > 7 ) 213 | { 214 | sprintf_s( error, 255, "Unused bits for BITSTRING must be in range 0-7" ); 215 | return In(); 216 | } 217 | } 218 | } 219 | 220 | return end; 221 | } 222 | else 223 | { 224 | In end = stream_in; 225 | 226 | unused_bits = (unsigned char)*end; 227 | if( unused_bits > 7 ) 228 | { 229 | sprintf_s( error, 255, "Unused bits for BITSTRING must be in range 0-7" ); 230 | return In(); 231 | } 232 | 233 | end++; 234 | if( end == In() ) 235 | { 236 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 237 | return end; 238 | } 239 | 240 | value_hex = ( unsigned char* ) malloc( ( size_t ) ( max_block_len - 1 ) ); 241 | if( !value_hex ) 242 | return In(); 243 | 244 | unsigned char* data = value_hex; 245 | 246 | for( unsigned long long i = 0; i < ( max_block_len - 1 ); i++ ) 247 | { 248 | if( end == In() ) 249 | { 250 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 251 | return end; 252 | } 253 | 254 | *data = *end; 255 | 256 | data++; 257 | end++; 258 | } 259 | 260 | block_length = max_block_len; 261 | 262 | return end; 263 | } 264 | 265 | return In(); 266 | } 267 | //************************************************************************** 268 | template< typename In, typename Out > 269 | unsigned long long BITSTRING_value_block< In, Out >::encode_BER( bool size_only ) 270 | { 271 | if( !is_constructed ) 272 | { 273 | if( size_only ) 274 | return block_length; 275 | 276 | if( !block_length ) 277 | return 0; 278 | 279 | stream_out = unused_bits; 280 | 281 | for( unsigned long long i = 0; i < ( block_length - 1 ); i++ ) 282 | stream_out = value_hex[ i ]; 283 | 284 | return block_length; 285 | } 286 | else 287 | return CONSTRUCTED_value_block< In, Out >::encode_BER( size_only ); 288 | 289 | return 0; 290 | } 291 | //************************************************************************** 292 | template< typename In, typename Out > 293 | struct BITSTRING_type : virtual public BASIC_type< In, Out > 294 | { 295 | static std::string block_name_static(); 296 | virtual std::string block_name(); 297 | 298 | BITSTRING_type(); 299 | 300 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 301 | virtual In decode_BER( unsigned long long max_block_len ); 302 | }; 303 | //************************************************************************** 304 | template< typename In, typename Out > 305 | BITSTRING_type< In, Out >::BITSTRING_type() 306 | { 307 | tag_class = 1; 308 | tag_number = 3; 309 | 310 | value_block = new BITSTRING_value_block< In, Out >(); 311 | } 312 | //************************************************************************** 313 | template< typename In, typename Out > 314 | std::string BITSTRING_type< In, Out >::block_name_static() 315 | { 316 | return "BIT STRING"; 317 | } 318 | //************************************************************************** 319 | template< typename In, typename Out > 320 | std::string BITSTRING_type< In, Out >::block_name() 321 | { 322 | return block_name_static(); 323 | } 324 | //************************************************************************** 325 | template< typename In, typename Out > 326 | bool BITSTRING_type< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 327 | { 328 | id_block = new identification_block_type< In, Out >(); 329 | if( !id_block->from_xml( element->selectSingleNode( L"./identification_block" ) ) ) 330 | return false; 331 | 332 | if( ( id_block->tag_class != tag_class ) || 333 | ( id_block->tag_number != tag_number ) ) 334 | { 335 | if( ( tag_class != ( unsigned char ) ( -1 ) ) && 336 | ( tag_number != ( unsigned long long ) ( -1 ) ) ) 337 | { 338 | std::string str = "Wrong \"tag_class\" or \"tag_number\" for ASN.1 type " + block_name(); 339 | sprintf_s( id_block->error, 255, str.c_str() ); 340 | return false; 341 | } 342 | } 343 | 344 | len_block = new length_block_type< In, Out >(); 345 | if( !len_block->from_xml( element->selectSingleNode( L"./length_block" ) ) ) 346 | return false; 347 | 348 | BITSTRING_value_block< In, Out >* vb = dynamic_cast< BITSTRING_value_block< In, Out >* >( value_block ); 349 | if( vb == NULL ) 350 | return false; 351 | 352 | vb->is_constructed = id_block->is_constructed; 353 | vb->is_indefinite_form = len_block->is_indefinite_form; 354 | 355 | if( value_block != NULL ) 356 | if( !value_block->from_xml( element->selectSingleNode( L"./value_block" ) ) ) 357 | return false; 358 | 359 | return true; 360 | } 361 | //************************************************************************** 362 | template< typename In, typename Out > 363 | In BITSTRING_type< In, Out >::decode_BER( unsigned long long max_block_len ) 364 | { 365 | if( !max_block_len ) // Ability to decode empty BIT STRING 366 | return stream_in; 367 | 368 | BITSTRING_value_block< In, Out >* vb = dynamic_cast< BITSTRING_value_block< In, Out >* >( value_block ); 369 | if( vb == NULL ) 370 | return false; 371 | 372 | vb->is_constructed = id_block->is_constructed; 373 | vb->is_indefinite_form = len_block->is_indefinite_form; 374 | 375 | return BASIC_type< In, Out >::decode_BER( max_block_len ); 376 | } 377 | //************************************************************************** 378 | #endif -------------------------------------------------------------------------------- /code/type_boolean.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _C0F3C217_84C5_4E2E_B8BC_A4F8F9EB2C0A 27 | #define _C0F3C217_84C5_4E2E_B8BC_A4F8F9EB2C0A 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct BOOLEAN_value_block : virtual public value_block_type< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | bool value; 34 | 35 | BOOLEAN_value_block(); 36 | 37 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 38 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 39 | 40 | virtual In decode_BER( unsigned long long max_block_len ); 41 | }; 42 | //************************************************************************** 43 | template< typename In, typename Out > 44 | BOOLEAN_value_block< In, Out >::BOOLEAN_value_block() : value( false ) 45 | { 46 | } 47 | //************************************************************************** 48 | template< typename In, typename Out > 49 | MSXML2::IXMLDOMElementPtr BOOLEAN_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 50 | { 51 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 52 | if( error[ 0 ] != 0x00 ) 53 | return result; 54 | 55 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 56 | 57 | std::string hex = hex_codes( value_hex, block_length ); 58 | 59 | wchar_t* whex = ( wchar_t* ) malloc( ( hex.length() + 1 ) * sizeof( wchar_t ) ); 60 | memset( whex, 0x00, ( hex.length() + 1 ) * sizeof( wchar_t ) ); 61 | 62 | size_t converted = 0; 63 | errno_t error_num = mbstowcs_s( &converted, whex, hex.length() + 1, hex.c_str(), hex.length() ); 64 | if( error_num ) 65 | { 66 | free( whex ); 67 | return result; 68 | } 69 | 70 | value_hex_xml->appendChild( pDoc->createTextNode( whex ) ); 71 | 72 | free( whex ); 73 | 74 | result->appendChild( value_hex_xml ); 75 | 76 | return result; 77 | } 78 | //************************************************************************** 79 | template< typename In, typename Out > 80 | bool BOOLEAN_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 81 | { 82 | if( !element ) 83 | return false; 84 | 85 | is_hex_only = true; 86 | 87 | MSXML2::IXMLDOMNodePtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 88 | if( !value_hex_xml ) 89 | return false; 90 | 91 | std::wstring str_hex = ( wchar_t* ) value_hex_xml->text; 92 | str_hex = wreplace( str_hex.c_str(), L" ", L"" ); 93 | 94 | if( !from_whex_codes( str_hex.c_str(), str_hex.length(), &value_hex ) ) 95 | return false; 96 | 97 | block_length = str_hex.length() >> 1; 98 | 99 | long long result = decode_tc( value_hex, ( unsigned char )block_length, &warnings ); 100 | 101 | if( result != 0 ) 102 | value = true; 103 | else 104 | value = false; 105 | 106 | if( block_length > 1 ) 107 | warnings.push_back( "BOOLEAN value encoded in more then 1 octet" ); 108 | 109 | return true; 110 | } 111 | //************************************************************************** 112 | template< typename In, typename Out > 113 | In BOOLEAN_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 114 | { 115 | In end = hex_block_type::decode_BER( max_block_len ); 116 | if( error[ 0 ] != 0x00 ) 117 | return In(); 118 | 119 | is_hex_only = true; 120 | 121 | long long result = decode_tc( value_hex, ( unsigned char )block_length, &warnings ); 122 | 123 | if( result != 0 ) 124 | value = true; 125 | else 126 | value = false; 127 | 128 | if( block_length > 1 ) 129 | warnings.push_back( "BOOLEAN value encoded in more then 1 octet" ); 130 | 131 | return end; 132 | } 133 | //************************************************************************** 134 | template< typename In, typename Out > 135 | struct BOOLEAN_type : virtual public BASIC_type< In, Out > 136 | { 137 | BOOLEAN_type(); 138 | 139 | static std::string block_name_static(); 140 | virtual std::string block_name(); 141 | }; 142 | //************************************************************************** 143 | template< typename In, typename Out > 144 | BOOLEAN_type< In, Out >::BOOLEAN_type() 145 | { 146 | tag_class = 1; 147 | tag_number = 1; 148 | 149 | value_block = new BOOLEAN_value_block< In, Out >(); 150 | } 151 | //************************************************************************** 152 | template< typename In, typename Out > 153 | std::string BOOLEAN_type< In, Out >::block_name_static() 154 | { 155 | return "BOOLEAN"; 156 | } 157 | //************************************************************************** 158 | template< typename In, typename Out > 159 | std::string BOOLEAN_type< In, Out >::block_name() 160 | { 161 | return block_name_static(); 162 | } 163 | //************************************************************************** 164 | #endif -------------------------------------------------------------------------------- /code/type_date_times.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _50508D69_192F_4B5B_8FD8_69157D7008D2 27 | #define _50508D69_192F_4B5B_8FD8_69157D7008D2 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct UTCTIME_value_block : virtual public value_block_type< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | unsigned int year; 34 | unsigned int month; 35 | unsigned int day; 36 | unsigned int hours; 37 | unsigned int minutes; 38 | 39 | bool format_with_seconds; 40 | 41 | unsigned int seconds; 42 | 43 | bool format_with_dif; 44 | 45 | unsigned char utc_dif_sign; 46 | unsigned int utc_dif_hours; 47 | unsigned int utc_dif_minutes; 48 | 49 | UTCTIME_value_block(); 50 | 51 | virtual In decode_BER( unsigned long long max_block_len ); 52 | virtual unsigned long long encode_BER( bool size_only = false ); 53 | 54 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 55 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 56 | }; 57 | //************************************************************************** 58 | template< typename In, typename Out > 59 | UTCTIME_value_block< In, Out >::UTCTIME_value_block() : year( 0 ), 60 | month( 0 ), 61 | day( 0 ), 62 | hours( 0 ), 63 | minutes( 0 ), 64 | format_with_seconds( false ), 65 | seconds( 0 ), 66 | format_with_dif( false ), 67 | utc_dif_sign( 0 ), 68 | utc_dif_hours( 0 ), 69 | utc_dif_minutes( 0 ) 70 | { 71 | } 72 | //************************************************************************** 73 | template< typename In, typename Out > 74 | In UTCTIME_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 75 | { 76 | // !!!!!!!!!!!!! 77 | T end = VISIBLESTRING_type< In, Out >::decode_BER( max_block_len ); 78 | 79 | //unsigned long long value_len = block_length - inf_block->block_length - len_block->block_length; 80 | //// !!!!!!!!!!!!! 81 | //std::string result; 82 | 83 | //if( value_len == 0 ) 84 | //{ 85 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 86 | // return T(); 87 | //} 88 | 89 | //char year_buf[ 5 ]; 90 | //char month_buf[ 4 ]; 91 | //char day_buf[ 5 ]; 92 | //char hours_buf[ 4 ]; 93 | //char minutes_buf[ 4 ]; 94 | 95 | //if( value_len >= 2 ) 96 | //{ 97 | // if( value[ 0 ] > 0x35 ) // 19-th century 98 | // { 99 | // year_buf[ 0 ] = 0x31; 100 | // year_buf[ 1 ] = 0x39; 101 | // } 102 | // else // 20-th century 103 | // { 104 | // year_buf[ 0 ] = 0x32; 105 | // year_buf[ 1 ] = 0x30; 106 | // } 107 | // year_buf[ 2 ] = value[ 0 ]; 108 | // year_buf[ 3 ] = value[ 1 ]; 109 | // year_buf[ 4 ] = 0x00; 110 | 111 | // if( !isdigit( year_buf[ 0 ] ) || !isdigit( year_buf[ 1 ] ) ) 112 | // { 113 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 114 | // return T(); 115 | // } 116 | 117 | // year = atoi( year_buf ); 118 | //} 119 | //else 120 | //{ 121 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 122 | // return T(); 123 | //} 124 | 125 | //result += year_buf; 126 | 127 | //if( value_len >= 4 ) 128 | //{ 129 | // month_buf[ 0 ] = 0x20; 130 | // month_buf[ 1 ] = value[ 2 ]; 131 | // month_buf[ 2 ] = value[ 3 ]; 132 | // month_buf[ 3 ] = 0x00; 133 | // 134 | // if( !isdigit( month_buf[ 1 ] ) || !isdigit( month_buf[ 2 ] ) ) 135 | // { 136 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 137 | // return T(); 138 | // } 139 | 140 | // month = atoi( month_buf ); 141 | 142 | // month_buf[ 0 ] = 0x2F; // ":/" sign 143 | //} 144 | //else 145 | //{ 146 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 147 | // return T(); 148 | //} 149 | 150 | //result += month_buf; 151 | 152 | //if( value_len >= 6 ) 153 | //{ 154 | // day_buf[ 0 ] = 0x20; 155 | // day_buf[ 1 ] = value[ 4 ]; 156 | // day_buf[ 2 ] = value[ 5 ]; 157 | // day_buf[ 3 ] = 0x00; 158 | 159 | // if( !isdigit( day_buf[ 1 ] ) || !isdigit( day_buf[ 2 ] ) ) 160 | // { 161 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 162 | // return T(); 163 | // } 164 | 165 | // day = atoi( day_buf ); 166 | 167 | // day_buf[ 0 ] = 0x2F; // "/" sign 168 | //} 169 | //else 170 | //{ 171 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 172 | // return T(); 173 | //} 174 | 175 | //result += day_buf; 176 | 177 | //if( value_len >= 8 ) 178 | //{ 179 | // hours_buf[ 0 ] = 0x20; // " " sign 180 | // hours_buf[ 1 ] = value[ 6 ]; 181 | // hours_buf[ 2 ] = value[ 7 ]; 182 | // hours_buf[ 3 ] = 0x00; 183 | 184 | // if( !isdigit( hours_buf[ 1 ] ) || !isdigit( hours_buf[ 2 ] ) ) 185 | // { 186 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 187 | // return T(); 188 | // } 189 | 190 | // hours = atoi( hours_buf ); 191 | //} 192 | //else 193 | //{ 194 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 195 | // return T(); 196 | //} 197 | 198 | //result += hours_buf; 199 | 200 | //if( value_len >= 10 ) 201 | //{ 202 | // minutes_buf[ 0 ] = 0x20; 203 | // minutes_buf[ 1 ] = value[ 8 ]; 204 | // minutes_buf[ 2 ] = value[ 9 ]; 205 | // minutes_buf[ 3 ] = 0x00; 206 | 207 | // if( !isdigit( minutes_buf[ 1 ] ) || !isdigit( minutes_buf[ 2 ] ) ) 208 | // { 209 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 210 | // return T(); 211 | // } 212 | 213 | // minutes = atoi( minutes_buf ); 214 | 215 | // minutes_buf[ 0 ] = 0x3A; // ":" sign 216 | //} 217 | //else 218 | //{ 219 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 220 | // return T(); 221 | //} 222 | 223 | //result += minutes_buf; 224 | 225 | //char seconds_buf[ 4 ]; 226 | //seconds_buf[ 0 ] = 0x00; 227 | //char difference_buf[ 6 ]; 228 | //difference_buf[ 0 ] = 0x00; 229 | 230 | //if( value_len >= 11 ) 231 | //{ 232 | // if( ( value[ 10 ] != 0x2D ) && ( value[ 10 ] != 0x2B ) && ( value[ 10 ] != 0x5A ) ) 233 | // { 234 | // if( value_len >= 12 ) 235 | // { 236 | // seconds_buf[ 0 ] = 0x20; 237 | // seconds_buf[ 1 ] = value[ 10 ]; 238 | // seconds_buf[ 2 ] = value[ 11 ]; 239 | // seconds_buf[ 3 ] = 0x00; 240 | 241 | // if( !isdigit( seconds_buf[ 1 ] ) || !isdigit( seconds_buf[ 2 ] ) ) 242 | // { 243 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 244 | // return T(); 245 | // } 246 | 247 | // format_with_seconds = true; 248 | // seconds = atoi( seconds_buf ); 249 | 250 | // seconds_buf[ 0 ] = 0x3A; // ":" sign 251 | // } 252 | // else 253 | // { 254 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 255 | // return T(); 256 | // } 257 | 258 | // if( ( value[ 12 ] == 0x2D ) || ( value[ 12 ] == 0x2B ) ) 259 | // { 260 | // if( value_len >= 17) 261 | // { 262 | // difference_buf[ 0 ] = 0x20; 263 | // difference_buf[ 1 ] = value[ 13 ]; 264 | // difference_buf[ 2 ] = value[ 14 ]; 265 | // difference_buf[ 3 ] = value[ 15 ]; 266 | // difference_buf[ 4 ] = value[ 16 ]; 267 | // difference_buf[ 5 ] = 0x00; 268 | 269 | // if( !isdigit( difference_buf[ 1 ] ) || 270 | // !isdigit( difference_buf[ 2 ] ) || 271 | // !isdigit( difference_buf[ 3 ] ) || 272 | // !isdigit( difference_buf[ 4 ] ) 273 | // ) 274 | // { 275 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 276 | // return T(); 277 | // } 278 | 279 | // difference_buf[ 0 ] = value[ 12 ]; 280 | // } 281 | // else 282 | // { 283 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 284 | // return T(); 285 | // } 286 | // } 287 | // } 288 | // else 289 | // { 290 | // if( ( value[ 10 ] == 0x2D ) || ( value[ 10 ] == 0x2B ) ) 291 | // { 292 | // if( value_len >= 15 ) 293 | // { 294 | // difference_buf[ 0 ] = 0x20; 295 | // difference_buf[ 1 ] = value[ 11 ]; 296 | // difference_buf[ 2 ] = value[ 12 ]; 297 | // difference_buf[ 3 ] = value[ 13 ]; 298 | // difference_buf[ 4 ] = value[ 14 ]; 299 | // difference_buf[ 5 ] = 0x00; 300 | 301 | // if( !isdigit( difference_buf[ 1 ] ) || 302 | // !isdigit( difference_buf[ 2 ] ) || 303 | // !isdigit( difference_buf[ 3 ] ) || 304 | // !isdigit( difference_buf[ 4 ] ) 305 | // ) 306 | // { 307 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 308 | // return T(); 309 | // } 310 | 311 | // difference_buf[ 0 ] = value[ 10 ]; 312 | // } 313 | // else 314 | // { 315 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 316 | // return T(); 317 | // } 318 | // } 319 | // } 320 | //} 321 | //else 322 | //{ 323 | // sprintf_s( error, 255, "Bad encoded UTCTime" ); 324 | // return T(); 325 | //} 326 | 327 | return end; 328 | } 329 | //************************************************************************** 330 | template< typename In, typename Out > 331 | unsigned long long UTCTIME_value_block< In, Out >::encode_BER( bool size_only ) 332 | { 333 | return 0; 334 | } 335 | //************************************************************************** 336 | template< typename In, typename Out > 337 | MSXML2::IXMLDOMElementPtr UTCTIME_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 338 | { 339 | MSXML2::IXMLDOMElementPtr result = block_type::to_xml( pDoc ); 340 | if( error[ 0 ] != 0x00 ) 341 | return result; 342 | 343 | if( !is_hex_only ) 344 | { 345 | std::wstring format = "%d/%d/%d %d:%d"; 346 | 347 | if( format_with_seconds ) 348 | format += ":%d"; 349 | 350 | if( format_with_dif ) 351 | format += "%c%d%d"; 352 | 353 | format += " UTC time"; 354 | 355 | wchar_t time_buf[ 255 ]; 356 | memset( time_buf, 0x00, 255 * sizeof( wchar_t ) ); 357 | 358 | swprintf_s( time_buf, 255, format.c_str(), year, month, day, hours, minutes, seconds, utc_dif_sign, utc_dif_hours, utc_dif_minutes ); 359 | 360 | MSXML2::IXMLDOMElementPtr value_dec_xml = pDoc->createElement( L"value_dec" ); 361 | value_dec_xml->appendChild( pDoc->createTextNode( time_buf ) ); 362 | result->appendChild( value_dec_xml ); 363 | } 364 | else 365 | { 366 | wchar_t* time_buf = ( wchar_t* ) malloc( ( block_length + 1 ) * sizeof( wchar_t ) ); 367 | memset( time_buf, 0x00, ( block_length + 1 ) * sizeof( wchar_t ) ); 368 | 369 | size_t converted = 0; 370 | errno_t error_num = mbstowcs_s( &converted, time_buf, block_length + 1, value_hex, block_length ); 371 | if( error_num ) 372 | return result; 373 | 374 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 375 | value_hex_xml->appendChild( pDoc->createTextNode( time_buf ) ); 376 | result->appendChild( value_hex_xml ); 377 | } 378 | 379 | return result; 380 | } 381 | //************************************************************************** 382 | template< typename In, typename Out > 383 | bool UTCTIME_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 384 | { 385 | return false; 386 | } 387 | //************************************************************************** 388 | template< typename In, typename Out > 389 | struct UTCTIME_type : virtual public VISIBLESTRING_type< In, Out > 390 | { 391 | UTCTIME_type(); 392 | 393 | static std::string block_name_static(); 394 | virtual std::string block_name(); 395 | }; 396 | //************************************************************************** 397 | template< typename In, typename Out > 398 | UTCTIME_type< In, Out >::UTCTIME_type() 399 | { 400 | tag_class = 1; 401 | tag_number = 23; 402 | } 403 | //************************************************************************** 404 | template< typename In, typename Out > 405 | std::string UTCTIME_type< In, Out >::block_name_static() 406 | { 407 | return "UTCTIME"; 408 | } 409 | //************************************************************************** 410 | template< typename In, typename Out > 411 | std::string UTCTIME_type< In, Out >::block_name() 412 | { 413 | return block_name_static(); 414 | } 415 | //************************************************************************** 416 | template< typename In, typename Out > 417 | struct GENERALIZEDTIME_type : virtual public VISIBLESTRING_type< In, Out > 418 | { 419 | GENERALIZEDTIME_type(); 420 | 421 | static std::string block_name_static(); 422 | virtual std::string block_name(); 423 | }; 424 | //************************************************************************** 425 | template< typename In, typename Out > 426 | GENERALIZEDTIME_type< In, Out >::GENERALIZEDTIME_type() 427 | { 428 | tag_class = 1; 429 | tag_number = 24; 430 | } 431 | //************************************************************************** 432 | template< typename In, typename Out > 433 | std::string GENERALIZEDTIME_type< In, Out >::block_name_static() 434 | { 435 | return "GENERALIZEDTIME"; 436 | } 437 | //************************************************************************** 438 | template< typename In, typename Out > 439 | std::string GENERALIZEDTIME_type< In, Out >::block_name() 440 | { 441 | return block_name_static(); 442 | } 443 | //************************************************************************** 444 | template< typename In, typename Out > 445 | struct DATE_type : virtual public UTF8STRING_type< In, Out > 446 | { 447 | DATE_type(); 448 | 449 | static std::string block_name_static(); 450 | virtual std::string block_name(); 451 | }; 452 | //************************************************************************** 453 | template< typename In, typename Out > 454 | DATE_type< In, Out >::DATE_type() 455 | { 456 | tag_class = 1; 457 | tag_number = 31; 458 | } 459 | //************************************************************************** 460 | template< typename In, typename Out > 461 | std::string DATE_type< In, Out >::block_name_static() 462 | { 463 | return "DATE"; 464 | } 465 | //************************************************************************** 466 | template< typename In, typename Out > 467 | std::string DATE_type< In, Out >::block_name() 468 | { 469 | return block_name_static(); 470 | } 471 | //************************************************************************** 472 | template< typename In, typename Out > 473 | struct TIMEOFDAY_type : virtual public UTF8STRING_type< In, Out > 474 | { 475 | TIMEOFDAY_type(); 476 | 477 | static std::string block_name_static(); 478 | virtual std::string block_name(); 479 | }; 480 | //************************************************************************** 481 | template< typename In, typename Out > 482 | TIMEOFDAY_type< In, Out >::TIMEOFDAY_type() 483 | { 484 | tag_class = 1; 485 | tag_number = 32; 486 | } 487 | //************************************************************************** 488 | template< typename In, typename Out > 489 | std::string TIMEOFDAY_type< In, Out >::block_name_static() 490 | { 491 | return "TIME OF DAY"; 492 | } 493 | //************************************************************************** 494 | template< typename In, typename Out > 495 | std::string TIMEOFDAY_type< In, Out >::block_name() 496 | { 497 | return block_name_static(); 498 | } 499 | //************************************************************************** 500 | template< typename In, typename Out > 501 | struct DATETIME_type : virtual public UTF8STRING_type< In, Out > 502 | { 503 | DATETIME_type(); 504 | 505 | static std::string block_name_static(); 506 | virtual std::string block_name(); 507 | }; 508 | //************************************************************************** 509 | template< typename In, typename Out > 510 | DATETIME_type< In, Out >::DATETIME_type() 511 | { 512 | tag_class = 1; 513 | tag_number = 33; 514 | } 515 | //************************************************************************** 516 | template< typename In, typename Out > 517 | std::string DATETIME_type< In, Out >::block_name_static() 518 | { 519 | return "DATETIME"; 520 | } 521 | //************************************************************************** 522 | template< typename In, typename Out > 523 | std::string DATETIME_type< In, Out >::block_name() 524 | { 525 | return block_name_static(); 526 | } 527 | //************************************************************************** 528 | template< typename In, typename Out > 529 | struct DURATION_type : virtual public UTF8STRING_type< In, Out > 530 | { 531 | DURATION_type(); 532 | 533 | static std::string block_name_static(); 534 | virtual std::string block_name(); 535 | }; 536 | //************************************************************************** 537 | template< typename In, typename Out > 538 | DURATION_type< In, Out >::DURATION_type() 539 | { 540 | tag_class = 1; 541 | tag_number = 34; 542 | } 543 | //************************************************************************** 544 | template< typename In, typename Out > 545 | std::string DURATION_type< In, Out >::block_name_static() 546 | { 547 | return "DURATION"; 548 | } 549 | //************************************************************************** 550 | template< typename In, typename Out > 551 | std::string DURATION_type< In, Out >::block_name() 552 | { 553 | return block_name_static(); 554 | } 555 | //************************************************************************** 556 | template< typename In, typename Out > 557 | struct TIME_type : virtual public UTF8STRING_type< In, Out > 558 | { 559 | TIME_type(); 560 | 561 | static std::string block_name_static(); 562 | virtual std::string block_name(); 563 | }; 564 | //************************************************************************** 565 | template< typename In, typename Out > 566 | TIME_type< In, Out >::TIME_type() 567 | { 568 | tag_class = 1; 569 | tag_number = 3; 570 | } 571 | //************************************************************************** 572 | template< typename In, typename Out > 573 | std::string TIME_type< In, Out >::block_name_static() 574 | { 575 | return "TIME"; 576 | } 577 | //************************************************************************** 578 | template< typename In, typename Out > 579 | std::string TIME_type< In, Out >::block_name() 580 | { 581 | return block_name_static(); 582 | } 583 | //************************************************************************** 584 | #endif -------------------------------------------------------------------------------- /code/type_datetimes.h: -------------------------------------------------------------------------------- 1 | #ifndef _0C2A870B_A6F6_45F0_92CE_EE98EAE24F0A 2 | #define _0C2A870B_A6F6_45F0_92CE_EE98EAE24F0A 3 | //************************************************************************** 4 | struct UTCTIME_type : virtual public VISIBLESTRING_type 5 | { 6 | virtual ~UTCTIME_type(); 7 | virtual std::string type_name(); 8 | 9 | template< typename T > T decode_value( T stream, unsigned long long max_block_len ); 10 | 11 | virtual std::string encode_type( int detailed_level ); 12 | virtual MSXML2::IXMLDOMElementPtr encode_type( int detailed_level, MSXML2::IXMLDOMDocumentPtr pDoc ); 13 | }; 14 | //************************************************************************** 15 | UTCTIME_type::~UTCTIME_type() 16 | { 17 | } 18 | //************************************************************************** 19 | std::string UTCTIME_type::type_name() 20 | { 21 | return "UTCTIME"; 22 | } 23 | //************************************************************************** 24 | std::string UTCTIME_type::encode_type( int detailed_level ) 25 | { 26 | unsigned long long value_len = block_length - inf_block->block_length - len_block->block_length; 27 | std::string result; 28 | 29 | if( value_len == 0 ) 30 | return ""; 31 | 32 | char year_buf[ 5 ]; 33 | char month_buf[ 4 ]; 34 | char day_buf[ 5 ]; 35 | char hours_buf[ 4 ]; 36 | char minutes_buf[ 4 ]; 37 | 38 | if( value_len >= 2 ) 39 | { 40 | if( value_block[ 0 ] > 0x35 ) // 19-th century 41 | { 42 | year_buf[ 0 ] = 0x31; 43 | year_buf[ 1 ] = 0x39; 44 | } 45 | else // 20-th century 46 | { 47 | year_buf[ 0 ] = 0x32; 48 | year_buf[ 1 ] = 0x30; 49 | } 50 | year_buf[ 2 ] = value_block[ 0 ]; 51 | year_buf[ 3 ] = value_block[ 1 ]; 52 | year_buf[ 4 ] = 0x00; 53 | } 54 | else 55 | return ""; 56 | 57 | result += year_buf; 58 | 59 | if( value_len >= 4 ) 60 | { 61 | month_buf[ 0 ] = 0x2F; // ":/" sign 62 | month_buf[ 1 ] = value_block[ 2 ]; 63 | month_buf[ 2 ] = value_block[ 3 ]; 64 | month_buf[ 3 ] = 0x00; 65 | } 66 | else 67 | return result; 68 | 69 | result += month_buf; 70 | 71 | if( value_len >= 6 ) 72 | { 73 | day_buf[ 0 ] = 0x2F; // "/" sign 74 | day_buf[ 1 ] = value_block[ 4 ]; 75 | day_buf[ 2 ] = value_block[ 5 ]; 76 | day_buf[ 3 ] = 0x00; 77 | } 78 | else 79 | return result; 80 | 81 | result += day_buf; 82 | 83 | if( value_len >= 8 ) 84 | { 85 | hours_buf[ 0 ] = 0x20; // " " sign 86 | hours_buf[ 1 ] = value_block[ 6 ]; 87 | hours_buf[ 2 ] = value_block[ 7 ]; 88 | hours_buf[ 3 ] = 0x00; 89 | } 90 | else 91 | return result; 92 | 93 | result += hours_buf; 94 | 95 | if( value_len >= 10 ) 96 | { 97 | minutes_buf[ 0 ] = 0x3A; // ":" sign 98 | minutes_buf[ 1 ] = value_block[ 8 ]; 99 | minutes_buf[ 2 ] = value_block[ 9 ]; 100 | minutes_buf[ 3 ] = 0x00; 101 | } 102 | else 103 | return result; 104 | 105 | result += minutes_buf; 106 | 107 | char seconds_buf[ 4 ]; 108 | seconds_buf[ 0 ] = 0x00; 109 | char difference_buf[ 6 ]; 110 | difference_buf[ 0 ] = 0x00; 111 | 112 | if( value_len >= 11 ) 113 | { 114 | if( ( value_block[ 10 ] != 0x2D ) && ( value_block[ 10 ] != 0x2B ) && ( value_block[ 10 ] != 0x5A ) ) 115 | { 116 | if( value_len >= 12 ) 117 | { 118 | seconds_buf[ 0 ] = 0x3A; // ":" sign 119 | seconds_buf[ 1 ] = value_block[ 10 ]; 120 | seconds_buf[ 2 ] = value_block[ 11 ]; 121 | seconds_buf[ 3 ] = 0x00; 122 | } 123 | else 124 | return result; 125 | 126 | if( ( value_block[ 12 ] == 0x2D ) || ( value_block[ 12 ] == 0x2B ) ) 127 | { 128 | if( value_len >= 17) 129 | { 130 | difference_buf[ 0 ] = value_block[ 12 ]; 131 | difference_buf[ 1 ] = value_block[ 13 ]; 132 | difference_buf[ 2 ] = value_block[ 14 ]; 133 | difference_buf[ 3 ] = value_block[ 15 ]; 134 | difference_buf[ 4 ] = value_block[ 16 ]; 135 | difference_buf[ 5 ] = 0x00; 136 | } 137 | else 138 | return result; 139 | } 140 | } 141 | else 142 | { 143 | if( ( value_block[ 10 ] == 0x2D ) || ( value_block[ 10 ] == 0x2B ) ) 144 | { 145 | if( value_len >= 15 ) 146 | { 147 | difference_buf[ 0 ] = value_block[ 10 ]; 148 | difference_buf[ 1 ] = value_block[ 11 ]; 149 | difference_buf[ 2 ] = value_block[ 12 ]; 150 | difference_buf[ 3 ] = value_block[ 13 ]; 151 | difference_buf[ 4 ] = value_block[ 14 ]; 152 | difference_buf[ 5 ] = 0x00; 153 | } 154 | else 155 | return result; 156 | } 157 | } 158 | } 159 | else 160 | return result; 161 | 162 | result += seconds_buf; 163 | result += difference_buf; 164 | result += " UTC"; 165 | 166 | return result; 167 | } 168 | //************************************************************************** 169 | MSXML2::IXMLDOMElementPtr UTCTIME_type::encode_type( int detailed_level, MSXML2::IXMLDOMDocumentPtr pDoc ) 170 | { 171 | //----------------------------------------------------- 172 | // In case of using "successors" of type 173 | // without their own XML encoding 174 | 175 | std::string name = type_name(); 176 | name = clear_xml_tag( name ); 177 | 178 | wchar_t name_buf[255]; 179 | size_t converted = 0; 180 | errno_t error_num = mbstowcs_s( &converted, name_buf, 255, name.c_str(), 255 ); 181 | if( error_num ) 182 | { 183 | sprintf_s( error, 255, "Wrong name convertion" ); 184 | return NULL; 185 | } 186 | //----------------------------------------------------- 187 | 188 | MSXML2::IXMLDOMElementPtr result = pDoc->createElement( name_buf ); 189 | 190 | if( warnings_and_error( pDoc, result) ) 191 | { 192 | MSXML2::IXMLDOMElementPtr value_xml = pDoc->createElement( L"value" ); 193 | 194 | std::string bit_value = encode_type( detailed_level ); 195 | 196 | wchar_t* value_buf = ( wchar_t* ) malloc( ( bit_value.length() + 1 ) * sizeof( wchar_t ) ); 197 | memset( value_buf, 0x00, ( bit_value.length() + 1 ) * sizeof( wchar_t ) ); 198 | 199 | converted = 0; 200 | error_num = mbstowcs_s( &converted, value_buf, bit_value.length() + 1, bit_value.c_str(), bit_value.length() + 1 ); 201 | if( error_num ) 202 | { 203 | sprintf_s( error, 255, "Wrong UTCTIME value convertion" ); 204 | return NULL; 205 | } 206 | 207 | value_xml->appendChild( pDoc->createTextNode( value_buf ) ); 208 | result->appendChild( value_xml ); 209 | 210 | free( value_buf ); 211 | } 212 | 213 | return result; 214 | } 215 | //************************************************************************** 216 | template< typename T > 217 | T UTCTIME_type::decode_value( T stream, 218 | unsigned long long max_block_len ) 219 | { 220 | T end = VISIBLESTRING_type::decode_value( stream, max_block_len ); 221 | 222 | unsigned long long value_len = block_length - inf_block->block_length - len_block->block_length; 223 | std::string result; 224 | 225 | if( value_len == 0 ) 226 | { 227 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 228 | return T(); 229 | } 230 | 231 | char year_buf[ 5 ]; 232 | char month_buf[ 4 ]; 233 | char day_buf[ 5 ]; 234 | char hours_buf[ 4 ]; 235 | char minutes_buf[ 4 ]; 236 | 237 | if( value_len >= 2 ) 238 | { 239 | if( value_block[ 0 ] > 0x35 ) // 19-th century 240 | { 241 | year_buf[ 0 ] = 0x31; 242 | year_buf[ 1 ] = 0x39; 243 | } 244 | else // 20-th century 245 | { 246 | year_buf[ 0 ] = 0x32; 247 | year_buf[ 1 ] = 0x30; 248 | } 249 | year_buf[ 2 ] = value_block[ 0 ]; 250 | year_buf[ 3 ] = value_block[ 1 ]; 251 | year_buf[ 4 ] = 0x00; 252 | 253 | if( !isdigit( year_buf[ 0 ] ) || !isdigit( year_buf[ 1 ] ) ) 254 | { 255 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 256 | return T(); 257 | } 258 | } 259 | else 260 | { 261 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 262 | return T(); 263 | } 264 | 265 | result += year_buf; 266 | 267 | if( value_len >= 4 ) 268 | { 269 | month_buf[ 0 ] = 0x20; 270 | month_buf[ 1 ] = value_block[ 2 ]; 271 | month_buf[ 2 ] = value_block[ 3 ]; 272 | month_buf[ 3 ] = 0x00; 273 | 274 | if( !isdigit( month_buf[ 1 ] ) || !isdigit( month_buf[ 2 ] ) ) 275 | { 276 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 277 | return T(); 278 | } 279 | 280 | month_buf[ 0 ] = 0x2F; // ":/" sign 281 | } 282 | else 283 | { 284 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 285 | return T(); 286 | } 287 | 288 | result += month_buf; 289 | 290 | if( value_len >= 6 ) 291 | { 292 | day_buf[ 0 ] = 0x20; 293 | day_buf[ 1 ] = value_block[ 4 ]; 294 | day_buf[ 2 ] = value_block[ 5 ]; 295 | day_buf[ 3 ] = 0x00; 296 | 297 | if( !isdigit( day_buf[ 1 ] ) || !isdigit( day_buf[ 2 ] ) ) 298 | { 299 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 300 | return T(); 301 | } 302 | 303 | day_buf[ 0 ] = 0x2F; // "/" sign 304 | } 305 | else 306 | { 307 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 308 | return T(); 309 | } 310 | 311 | result += day_buf; 312 | 313 | if( value_len >= 8 ) 314 | { 315 | hours_buf[ 0 ] = 0x20; // " " sign 316 | hours_buf[ 1 ] = value_block[ 6 ]; 317 | hours_buf[ 2 ] = value_block[ 7 ]; 318 | hours_buf[ 3 ] = 0x00; 319 | 320 | if( !isdigit( hours_buf[ 1 ] ) || !isdigit( hours_buf[ 2 ] ) ) 321 | { 322 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 323 | return T(); 324 | } 325 | } 326 | else 327 | { 328 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 329 | return T(); 330 | } 331 | 332 | result += hours_buf; 333 | 334 | if( value_len >= 10 ) 335 | { 336 | minutes_buf[ 0 ] = 0x20; 337 | minutes_buf[ 1 ] = value_block[ 8 ]; 338 | minutes_buf[ 2 ] = value_block[ 9 ]; 339 | minutes_buf[ 3 ] = 0x00; 340 | 341 | if( !isdigit( minutes_buf[ 1 ] ) || !isdigit( minutes_buf[ 2 ] ) ) 342 | { 343 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 344 | return T(); 345 | } 346 | 347 | minutes_buf[ 0 ] = 0x3A; // ":" sign 348 | } 349 | else 350 | { 351 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 352 | return T(); 353 | } 354 | 355 | result += minutes_buf; 356 | 357 | char seconds_buf[ 4 ]; 358 | seconds_buf[ 0 ] = 0x00; 359 | char difference_buf[ 6 ]; 360 | difference_buf[ 0 ] = 0x00; 361 | 362 | if( value_len >= 11 ) 363 | { 364 | if( ( value_block[ 10 ] != 0x2D ) && ( value_block[ 10 ] != 0x2B ) && ( value_block[ 10 ] != 0x5A ) ) 365 | { 366 | if( value_len >= 12 ) 367 | { 368 | seconds_buf[ 0 ] = 0x20; 369 | seconds_buf[ 1 ] = value_block[ 10 ]; 370 | seconds_buf[ 2 ] = value_block[ 11 ]; 371 | seconds_buf[ 3 ] = 0x00; 372 | 373 | if( !isdigit( seconds_buf[ 1 ] ) || !isdigit( seconds_buf[ 2 ] ) ) 374 | { 375 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 376 | return T(); 377 | } 378 | 379 | seconds_buf[ 0 ] = 0x3A; // ":" sign 380 | } 381 | else 382 | { 383 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 384 | return T(); 385 | } 386 | 387 | if( ( value_block[ 12 ] == 0x2D ) || ( value_block[ 12 ] == 0x2B ) ) 388 | { 389 | if( value_len >= 17) 390 | { 391 | difference_buf[ 0 ] = 0x20; 392 | difference_buf[ 1 ] = value_block[ 13 ]; 393 | difference_buf[ 2 ] = value_block[ 14 ]; 394 | difference_buf[ 3 ] = value_block[ 15 ]; 395 | difference_buf[ 4 ] = value_block[ 16 ]; 396 | difference_buf[ 5 ] = 0x00; 397 | 398 | if( !isdigit( difference_buf[ 1 ] ) || 399 | !isdigit( difference_buf[ 2 ] ) || 400 | !isdigit( difference_buf[ 3 ] ) || 401 | !isdigit( difference_buf[ 4 ] ) 402 | ) 403 | { 404 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 405 | return T(); 406 | } 407 | 408 | difference_buf[ 0 ] = value_block[ 12 ]; 409 | } 410 | else 411 | { 412 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 413 | return T(); 414 | } 415 | } 416 | } 417 | else 418 | { 419 | if( ( value_block[ 10 ] == 0x2D ) || ( value_block[ 10 ] == 0x2B ) ) 420 | { 421 | if( value_len >= 15 ) 422 | { 423 | difference_buf[ 0 ] = 0x20; 424 | difference_buf[ 1 ] = value_block[ 11 ]; 425 | difference_buf[ 2 ] = value_block[ 12 ]; 426 | difference_buf[ 3 ] = value_block[ 13 ]; 427 | difference_buf[ 4 ] = value_block[ 14 ]; 428 | difference_buf[ 5 ] = 0x00; 429 | 430 | if( !isdigit( difference_buf[ 1 ] ) || 431 | !isdigit( difference_buf[ 2 ] ) || 432 | !isdigit( difference_buf[ 3 ] ) || 433 | !isdigit( difference_buf[ 4 ] ) 434 | ) 435 | { 436 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 437 | return T(); 438 | } 439 | 440 | difference_buf[ 0 ] = value_block[ 10 ]; 441 | } 442 | else 443 | { 444 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 445 | return T(); 446 | } 447 | } 448 | } 449 | } 450 | else 451 | { 452 | sprintf_s( error, 255, "Bad encoded UTCTime" ); 453 | return T(); 454 | } 455 | 456 | return end; 457 | } 458 | //************************************************************************** 459 | struct GENERALIZEDTIME_type : virtual public VISIBLESTRING_type 460 | { 461 | virtual ~GENERALIZEDTIME_type(); 462 | virtual std::string type_name(); 463 | 464 | virtual std::string encode_type( int detailed_level ); 465 | virtual MSXML2::IXMLDOMElementPtr encode_type( int detailed_level, MSXML2::IXMLDOMDocumentPtr pDoc ); 466 | }; 467 | //************************************************************************** 468 | GENERALIZEDTIME_type::~GENERALIZEDTIME_type() 469 | { 470 | } 471 | //************************************************************************** 472 | std::string GENERALIZEDTIME_type::type_name() 473 | { 474 | return "GENERALIZEDTIME"; 475 | } 476 | //************************************************************************** 477 | std::string GENERALIZEDTIME_type::encode_type( int detailed_level ) 478 | { 479 | // !!! For now this way ( temporary ) 480 | return VISIBLESTRING_type::encode_type( detailed_level ); 481 | 482 | unsigned long long value_len = block_length - inf_block->block_length - len_block->block_length; 483 | std::string result; 484 | 485 | if( value_len == 0 ) 486 | return ""; 487 | 488 | char year_buf[ 5 ]; 489 | char month_buf[ 4 ]; 490 | char day_buf[ 5 ]; 491 | char hours_buf[ 4 ]; 492 | char minutes_buf[ 4 ]; 493 | 494 | if( value_len >= 2 ) 495 | { 496 | if( value_block[ 0 ] > 0x35 ) // 19-th century 497 | { 498 | year_buf[ 0 ] = 0x31; 499 | year_buf[ 1 ] = 0x39; 500 | } 501 | else // 20-th century 502 | { 503 | year_buf[ 0 ] = 0x32; 504 | year_buf[ 1 ] = 0x30; 505 | } 506 | year_buf[ 2 ] = value_block[ 0 ]; 507 | year_buf[ 3 ] = value_block[ 1 ]; 508 | year_buf[ 4 ] = 0x00; 509 | } 510 | else 511 | return ""; 512 | 513 | result += year_buf; 514 | 515 | if( value_len >= 4 ) 516 | { 517 | month_buf[ 0 ] = 0x2F; // ":/" sign 518 | month_buf[ 1 ] = value_block[ 2 ]; 519 | month_buf[ 2 ] = value_block[ 3 ]; 520 | month_buf[ 3 ] = 0x00; 521 | } 522 | else 523 | return result; 524 | 525 | result += month_buf; 526 | 527 | if( value_len >= 6 ) 528 | { 529 | day_buf[ 0 ] = 0x2F; // "/" sign 530 | day_buf[ 1 ] = value_block[ 4 ]; 531 | day_buf[ 2 ] = value_block[ 5 ]; 532 | day_buf[ 3 ] = 0x00; 533 | } 534 | else 535 | return result; 536 | 537 | result += day_buf; 538 | 539 | if( value_len >= 8 ) 540 | { 541 | hours_buf[ 0 ] = 0x20; // " " sign 542 | hours_buf[ 1 ] = value_block[ 6 ]; 543 | hours_buf[ 2 ] = value_block[ 7 ]; 544 | hours_buf[ 3 ] = 0x00; 545 | } 546 | else 547 | return result; 548 | 549 | result += hours_buf; 550 | 551 | if( value_len >= 10 ) 552 | { 553 | minutes_buf[ 0 ] = 0x3A; // ":" sign 554 | minutes_buf[ 1 ] = value_block[ 8 ]; 555 | minutes_buf[ 2 ] = value_block[ 9 ]; 556 | minutes_buf[ 3 ] = 0x00; 557 | } 558 | else 559 | return result; 560 | 561 | result += minutes_buf; 562 | 563 | char seconds_buf[ 4 ]; 564 | seconds_buf[ 0 ] = 0x00; 565 | char difference_buf[ 6 ]; 566 | difference_buf[ 0 ] = 0x00; 567 | 568 | if( value_len >= 11 ) 569 | { 570 | if( ( value_block[ 10 ] != 0x2D ) && ( value_block[ 10 ] != 0x2B ) && ( value_block[ 10 ] != 0x5A ) ) 571 | { 572 | if( value_len >= 12 ) 573 | { 574 | seconds_buf[ 0 ] = 0x3A; // ":" sign 575 | seconds_buf[ 1 ] = value_block[ 10 ]; 576 | seconds_buf[ 2 ] = value_block[ 11 ]; 577 | seconds_buf[ 3 ] = 0x00; 578 | } 579 | else 580 | return result; 581 | 582 | if( ( value_block[ 12 ] == 0x2D ) || ( value_block[ 12 ] == 0x2B ) ) 583 | { 584 | if( value_len >= 17) 585 | { 586 | difference_buf[ 0 ] = value_block[ 12 ]; 587 | difference_buf[ 1 ] = value_block[ 13 ]; 588 | difference_buf[ 2 ] = value_block[ 14 ]; 589 | difference_buf[ 3 ] = value_block[ 15 ]; 590 | difference_buf[ 4 ] = value_block[ 16 ]; 591 | difference_buf[ 5 ] = 0x00; 592 | } 593 | else 594 | return result; 595 | } 596 | } 597 | else 598 | { 599 | if( ( value_block[ 10 ] == 0x2D ) || ( value_block[ 10 ] == 0x2B ) ) 600 | { 601 | if( value_len >= 15 ) 602 | { 603 | difference_buf[ 0 ] = value_block[ 10 ]; 604 | difference_buf[ 1 ] = value_block[ 11 ]; 605 | difference_buf[ 2 ] = value_block[ 12 ]; 606 | difference_buf[ 3 ] = value_block[ 13 ]; 607 | difference_buf[ 4 ] = value_block[ 14 ]; 608 | difference_buf[ 5 ] = 0x00; 609 | } 610 | else 611 | return result; 612 | } 613 | } 614 | } 615 | else 616 | return result; 617 | 618 | result += seconds_buf; 619 | result += difference_buf; 620 | result += " UTC"; 621 | 622 | return result; 623 | } 624 | //************************************************************************** 625 | MSXML2::IXMLDOMElementPtr GENERALIZEDTIME_type::encode_type( int detailed_level, MSXML2::IXMLDOMDocumentPtr pDoc ) 626 | { 627 | //----------------------------------------------------- 628 | // In case of using "successors" of type 629 | // without their own XML encoding 630 | 631 | std::string name = type_name(); 632 | name = clear_xml_tag( name ); 633 | 634 | wchar_t name_buf[255]; 635 | size_t converted = 0; 636 | errno_t error_num = mbstowcs_s( &converted, name_buf, 255, name.c_str(), 255 ); 637 | if( error_num ) 638 | { 639 | sprintf_s( error, 255, "Wrong name convertion" ); 640 | return NULL; 641 | } 642 | //----------------------------------------------------- 643 | 644 | MSXML2::IXMLDOMElementPtr result = pDoc->createElement( name_buf ); 645 | 646 | if( warnings_and_error( pDoc, result) ) 647 | { 648 | MSXML2::IXMLDOMElementPtr value_xml = pDoc->createElement( L"value" ); 649 | 650 | std::string bit_value = encode_type( detailed_level ); 651 | 652 | wchar_t* value_buf = ( wchar_t* ) malloc( ( bit_value.length() + 1 ) * sizeof( wchar_t ) ); 653 | memset( value_buf, 0x00, ( bit_value.length() + 1 ) * sizeof( wchar_t ) ); 654 | 655 | converted = 0; 656 | error_num = mbstowcs_s( &converted, value_buf, bit_value.length() + 1, bit_value.c_str(), bit_value.length() + 1 ); 657 | if( error_num ) 658 | { 659 | sprintf_s( error, 255, "Wrong GENERALIZEDTIME value convertion" ); 660 | return NULL; 661 | } 662 | 663 | value_xml->appendChild( pDoc->createTextNode( value_buf ) ); 664 | result->appendChild( value_xml ); 665 | 666 | free( value_buf ); 667 | } 668 | 669 | return result; 670 | } 671 | //************************************************************************** 672 | struct DATE_type : virtual public UTF8STRING_type 673 | { 674 | virtual ~DATE_type(); 675 | virtual std::string type_name(); 676 | }; 677 | //************************************************************************** 678 | DATE_type::~DATE_type() 679 | { 680 | } 681 | //************************************************************************** 682 | std::string DATE_type::type_name() 683 | { 684 | return "DATE"; 685 | } 686 | //************************************************************************** 687 | struct TIMEOFDAY_type : virtual public UTF8STRING_type 688 | { 689 | virtual ~TIMEOFDAY_type(); 690 | virtual std::string type_name(); 691 | }; 692 | //************************************************************************** 693 | TIMEOFDAY_type::~TIMEOFDAY_type() 694 | { 695 | } 696 | //************************************************************************** 697 | std::string TIMEOFDAY_type::type_name() 698 | { 699 | return "TIMEOFDAY"; 700 | } 701 | //************************************************************************** 702 | struct DATETIME_type : virtual public UTF8STRING_type 703 | { 704 | virtual ~DATETIME_type(); 705 | virtual std::string type_name(); 706 | }; 707 | //************************************************************************** 708 | DATETIME_type::~DATETIME_type() 709 | { 710 | } 711 | //************************************************************************** 712 | std::string DATETIME_type::type_name() 713 | { 714 | return "DATETIME"; 715 | } 716 | //************************************************************************** 717 | struct DURATION_type : virtual public UTF8STRING_type 718 | { 719 | virtual ~DURATION_type(); 720 | virtual std::string type_name(); 721 | }; 722 | //************************************************************************** 723 | DURATION_type::~DURATION_type() 724 | { 725 | } 726 | //************************************************************************** 727 | std::string DURATION_type::type_name() 728 | { 729 | return "DURATION"; 730 | } 731 | //************************************************************************** 732 | struct TIME_type : virtual public UTF8STRING_type 733 | { 734 | virtual ~TIME_type(); 735 | virtual std::string type_name(); 736 | }; 737 | //************************************************************************** 738 | TIME_type::~TIME_type() 739 | { 740 | } 741 | //************************************************************************** 742 | std::string TIME_type::type_name() 743 | { 744 | return "TIME"; 745 | } 746 | //************************************************************************** 747 | #endif -------------------------------------------------------------------------------- /code/type_eoc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _368F4CD8_AD32_449C_BEB2_57F336F11103 27 | #define _368F4CD8_AD32_449C_BEB2_57F336F11103 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct EOC_value_block : virtual public value_block_type< In, Out > 31 | { 32 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 33 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 34 | 35 | virtual In decode_BER( unsigned long long max_block_len ); 36 | virtual unsigned long long encode_BER( bool size_only = false ); 37 | }; 38 | //************************************************************************** 39 | template< typename In, typename Out > 40 | MSXML2::IXMLDOMElementPtr EOC_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 41 | { 42 | return block_type< In, Out >::to_xml( pDoc ); 43 | } 44 | //************************************************************************** 45 | template< typename In, typename Out > 46 | bool EOC_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 47 | { 48 | return true; 49 | } 50 | //************************************************************************** 51 | template< typename In, typename Out > 52 | In EOC_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 53 | { 54 | if( max_block_len != 0 ) 55 | { 56 | sprintf_s( error, 255, "Wrong encoding for EOC block"); 57 | return In(); 58 | } 59 | 60 | block_length = 0; 61 | 62 | return stream_in; // should not move "stream" because no value in the type and "inf_block" and "len_block" were already decoded 63 | } 64 | //************************************************************************** 65 | template< typename In, typename Out > 66 | unsigned long long EOC_value_block< In, Out >::encode_BER( bool size_only ) 67 | { 68 | return 0; 69 | } 70 | //************************************************************************** 71 | template< typename In, typename Out > 72 | struct EOC_type : virtual public BASIC_type< In, Out > 73 | { 74 | EOC_type(); 75 | 76 | static std::string block_name_static(); 77 | virtual std::string block_name(); 78 | }; 79 | //************************************************************************** 80 | template< typename In, typename Out > 81 | EOC_type< In, Out >::EOC_type() 82 | { 83 | value_block = new EOC_value_block< In, Out >(); 84 | } 85 | //************************************************************************** 86 | template< typename In, typename Out > 87 | std::string EOC_type< In, Out >::block_name_static() 88 | { 89 | return "END OF CONTENT"; 90 | } 91 | //************************************************************************** 92 | template< typename In, typename Out > 93 | std::string EOC_type< In, Out >::block_name() 94 | { 95 | return block_name_static(); 96 | } 97 | //************************************************************************** 98 | #endif -------------------------------------------------------------------------------- /code/type_integer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _A1ED10DE_1D07_4EC4_D57_9B82EB54D320 27 | #define _A1ED10DE_1D07_4EC4_D57_9B82EB54D320 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct INTEGER_value_block : virtual public value_block_type< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | long long value_dec; 34 | 35 | INTEGER_value_block(); 36 | 37 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 38 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 39 | 40 | virtual In decode_BER( unsigned long long max_block_len ); 41 | virtual unsigned long long encode_BER( bool size_only = false ); 42 | }; 43 | //************************************************************************** 44 | template< typename In, typename Out > 45 | INTEGER_value_block< In, Out >::INTEGER_value_block() : value_dec( 0 ) 46 | { 47 | } 48 | //************************************************************************** 49 | template< typename In, typename Out > 50 | MSXML2::IXMLDOMElementPtr INTEGER_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 51 | { 52 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 53 | if( error[ 0 ] != 0x00 ) 54 | return result; 55 | 56 | if( !block_length ) 57 | return result; 58 | 59 | MSXML2::IXMLDOMElementPtr value_xml; 60 | 61 | if( !is_hex_only ) 62 | { 63 | wchar_t buf[255]; 64 | _i64tow_s( value_dec, buf, 255, 10 ); 65 | 66 | value_xml = pDoc->createElement( L"value_dec" ); 67 | value_xml->appendChild( pDoc->createTextNode( buf ) ); 68 | } 69 | else 70 | { 71 | std::string codes = hex_codes( value_hex, block_length ); 72 | 73 | wchar_t* whex = ( wchar_t* ) malloc( ( codes.length() + 1 ) * sizeof( wchar_t ) ); 74 | memset( whex, 0x00, ( codes.length() + 1 ) * sizeof( wchar_t ) ); 75 | 76 | size_t converted = 0; 77 | errno_t error_num = mbstowcs_s( &converted, whex, codes.length() + 1, codes.c_str(), codes.length() ); 78 | if( error_num ) 79 | { 80 | free( whex ); 81 | return result; 82 | } 83 | 84 | value_xml = pDoc->createElement( L"value_hex" ); 85 | value_xml->appendChild( pDoc->createTextNode( whex ) ); 86 | 87 | free( whex ); 88 | } 89 | 90 | result->appendChild( value_xml ); 91 | 92 | return result; 93 | } 94 | //************************************************************************** 95 | template< typename In, typename Out > 96 | bool INTEGER_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 97 | { 98 | if( !element ) 99 | return false; 100 | 101 | MSXML2::IXMLDOMNodePtr value_dec_xml = element->selectSingleNode( L"value_dec" ); 102 | if( value_dec_xml ) 103 | { 104 | value_dec = _wtoi64( ( wchar_t* )value_dec_xml->firstChild->text ); 105 | if( errno && !value_dec ) 106 | return false; 107 | 108 | block_length = encode_tc( value_dec, &value_hex ); 109 | } 110 | else 111 | { 112 | MSXML2::IXMLDOMNodePtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 113 | if( !value_hex_xml ) 114 | return false; 115 | 116 | is_hex_only = true; 117 | 118 | std::wstring result = wreplace( (wchar_t*)value_hex_xml->firstChild->text, L" ", L"" ); 119 | 120 | from_whex_codes( result.c_str(), result.length(), &value_hex ); 121 | block_length = result.length() >> 1; 122 | } 123 | 124 | return true; 125 | } 126 | //************************************************************************** 127 | template< typename In, typename Out > 128 | In INTEGER_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 129 | { 130 | In end = hex_block_type::decode_BER( max_block_len ); 131 | if( error[ 0 ] != 0x00 ) 132 | return In(); 133 | 134 | if( block_length > 8 ) 135 | { 136 | warnings.push_back( "Too big INTEGER for decoding, hex only" ); 137 | is_hex_only = true; 138 | } 139 | else 140 | value_dec = decode_tc( value_hex, ( unsigned char )block_length, &warnings ); 141 | 142 | return end; 143 | } 144 | //************************************************************************** 145 | template< typename In, typename Out > 146 | unsigned long long INTEGER_value_block< In, Out >::encode_BER( bool size_only ) 147 | { 148 | if( !block_length ) 149 | return 0; 150 | 151 | unsigned long long size = 0; 152 | 153 | if( !is_hex_only ) 154 | { 155 | unsigned char* encoded; 156 | 157 | size = encode_tc( value_dec, &encoded ); 158 | if( !size ) 159 | { 160 | sprintf_s( error, 255, "Error during encoding INTEGER value" ); 161 | return 0; 162 | } 163 | 164 | if( !size_only ) 165 | { 166 | for( unsigned long long i = 0; i < size; i++ ) 167 | stream_out = encoded[ i ]; 168 | } 169 | 170 | free( encoded ); 171 | } 172 | else 173 | { 174 | size = block_length; 175 | 176 | if( !size_only ) 177 | { 178 | for( unsigned long long i = 0; i < size; i++ ) 179 | stream_out = value_hex[ i ]; 180 | } 181 | } 182 | 183 | return size; 184 | } 185 | //************************************************************************** 186 | template< typename In, typename Out > 187 | struct INTEGER_type : virtual public BASIC_type< In, Out > 188 | { 189 | INTEGER_type(); 190 | 191 | static std::string block_name_static(); 192 | virtual std::string block_name(); 193 | }; 194 | //************************************************************************** 195 | template< typename In, typename Out > 196 | INTEGER_type< In, Out >::INTEGER_type() 197 | { 198 | tag_class = 1; 199 | tag_number = 2; 200 | 201 | value_block = new INTEGER_value_block< In, Out >(); 202 | } 203 | //************************************************************************** 204 | template< typename In, typename Out > 205 | std::string INTEGER_type< In, Out >::block_name_static() 206 | { 207 | return "INTEGER"; 208 | } 209 | //************************************************************************** 210 | template< typename In, typename Out > 211 | std::string INTEGER_type< In, Out >::block_name() 212 | { 213 | return block_name_static(); 214 | } 215 | //************************************************************************** 216 | template< typename In, typename Out > 217 | struct ENUMERATED_type : virtual public INTEGER_type< In, Out > 218 | { 219 | ENUMERATED_type(); 220 | 221 | static std::string block_name_static(); 222 | virtual std::string block_name(); 223 | }; 224 | //************************************************************************** 225 | template< typename In, typename Out > 226 | ENUMERATED_type< In, Out >::ENUMERATED_type() 227 | { 228 | tag_class = 1; 229 | tag_number = 10; 230 | } 231 | //************************************************************************** 232 | template< typename In, typename Out > 233 | std::string ENUMERATED_type< In, Out >::block_name_static() 234 | { 235 | return "ENUMERATED"; 236 | } 237 | //************************************************************************** 238 | template< typename In, typename Out > 239 | std::string ENUMERATED_type< In, Out >::block_name() 240 | { 241 | return block_name_static(); 242 | } 243 | //************************************************************************** 244 | #endif -------------------------------------------------------------------------------- /code/type_null.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _8E5F4C88_E280_4F7C_BE77_E66F48D0C083 27 | #define _8E5F4C88_E280_4F7C_BE77_E66F48D0C083 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct NULL_value_block : virtual public value_block_type< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 34 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 35 | 36 | virtual In decode_BER( unsigned long long max_block_len ); 37 | virtual unsigned long long encode_BER( bool size_only = false ); 38 | }; 39 | //************************************************************************** 40 | template< typename In, typename Out > 41 | MSXML2::IXMLDOMElementPtr NULL_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 42 | { 43 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 44 | return result; 45 | } 46 | //************************************************************************** 47 | template< typename In, typename Out > 48 | bool NULL_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 49 | { 50 | if( !element) 51 | return false; 52 | 53 | return true; 54 | } 55 | //************************************************************************** 56 | template< typename In, typename Out > 57 | In NULL_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 58 | { 59 | if( max_block_len ) 60 | warnings.push_back( "Non-zero length of value block for NULL type" ); 61 | 62 | block_length = max_block_len; 63 | 64 | while( max_block_len ) 65 | { 66 | if( stream_in == In() ) 67 | { 68 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 69 | return stream_in; 70 | } 71 | 72 | stream_in++; 73 | max_block_len--; 74 | } 75 | 76 | return stream_in; 77 | } 78 | //************************************************************************** 79 | template< typename In, typename Out > 80 | unsigned long long NULL_value_block< In, Out >::encode_BER( bool size_only ) 81 | { 82 | return 0; 83 | } 84 | //************************************************************************** 85 | template< typename In, typename Out > 86 | struct NULL_type : virtual public BASIC_type< In, Out > 87 | { 88 | NULL_type(); 89 | 90 | static std::string block_name_static(); 91 | virtual std::string block_name(); 92 | }; 93 | //************************************************************************** 94 | template< typename In, typename Out > 95 | NULL_type< In, Out >::NULL_type() 96 | { 97 | tag_class = 1; 98 | tag_number = 5; 99 | 100 | value_block = new NULL_value_block< In, Out >(); 101 | } 102 | //************************************************************************** 103 | template< typename In, typename Out > 104 | std::string NULL_type< In, Out >::block_name_static() 105 | { 106 | return "NULL"; 107 | } 108 | //************************************************************************** 109 | template< typename In, typename Out > 110 | std::string NULL_type< In, Out >::block_name() 111 | { 112 | return block_name_static(); 113 | } 114 | //************************************************************************** 115 | #endif -------------------------------------------------------------------------------- /code/type_objid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _ABF41DE2_8824_46AE_94CE_552B79A68D99 27 | #define _ABF41DE2_8824_46AE_94CE_552B79A68D99 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct SID_value_block : virtual public hex_block_type< In, Out > 31 | { 32 | unsigned long long value_dec; 33 | 34 | bool is_first_sid; 35 | 36 | SID_value_block(); 37 | 38 | virtual std::string block_name(); 39 | 40 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 41 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 42 | 43 | virtual In decode_BER( unsigned long long max_block_len ); 44 | virtual unsigned long long encode_BER( bool size_only = false ); 45 | }; 46 | //************************************************************************** 47 | template< typename In, typename Out > 48 | SID_value_block< In, Out >::SID_value_block() : value_dec( 0 ), 49 | is_first_sid( false ) 50 | { 51 | } 52 | //************************************************************************** 53 | template< typename In, typename Out > 54 | std::string SID_value_block< In, Out >::block_name() 55 | { 56 | return "sid_block"; 57 | } 58 | //************************************************************************** 59 | template< typename In, typename Out > 60 | MSXML2::IXMLDOMElementPtr SID_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 61 | { 62 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 63 | if( error[ 0 ] != 0x00 ) 64 | return result; 65 | 66 | if( !block_length ) 67 | return result; 68 | 69 | MSXML2::IXMLDOMElementPtr is_first_sid_xml = pDoc->createElement( L"is_first_sid" ); 70 | is_first_sid_xml->appendChild( pDoc->createTextNode( ( is_first_sid )? L"true" : L"false" ) ); 71 | result->appendChild( is_first_sid_xml ); 72 | 73 | MSXML2::IXMLDOMElementPtr is_hex_only_xml = pDoc->createElement( L"is_hex_only" ); 74 | is_hex_only_xml->appendChild( pDoc->createTextNode( ( is_hex_only )? L"true" : L"false" ) ); 75 | result->appendChild( is_hex_only_xml ); 76 | 77 | if( is_hex_only ) 78 | { 79 | std::string codes = hex_codes( value_hex, block_length ); 80 | 81 | wchar_t* whex = ( wchar_t* ) malloc( ( codes.length() + 1 ) * sizeof( wchar_t ) ); 82 | memset( whex, 0x00, ( codes.length() + 1 ) * sizeof( wchar_t ) ); 83 | 84 | size_t converted = 0; 85 | errno_t error_num = mbstowcs_s( &converted, whex, codes.length() + 1, codes.c_str(), codes.length() ); 86 | if( error_num ) 87 | { 88 | free( whex ); 89 | return result; 90 | } 91 | 92 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 93 | value_hex_xml->appendChild( pDoc->createTextNode( whex ) ); 94 | result->appendChild( value_hex_xml ); 95 | 96 | free( whex ); 97 | } 98 | else 99 | { 100 | wchar_t buf[255]; 101 | _ui64tow_s( value_dec, buf, 255, 10 ); 102 | 103 | MSXML2::IXMLDOMElementPtr value_dec_xml = pDoc->createElement( L"value_dec" ); 104 | value_dec_xml->appendChild( pDoc->createTextNode( buf ) ); 105 | result->appendChild( value_dec_xml ); 106 | } 107 | 108 | return result; 109 | } 110 | //************************************************************************** 111 | template< typename In, typename Out > 112 | bool SID_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 113 | { 114 | if( !element ) 115 | return false; 116 | 117 | MSXML2::IXMLDOMElementPtr is_first_sid_xml = element->selectSingleNode( L"is_first_sid" ); 118 | if( !is_first_sid_xml ) 119 | return false; 120 | 121 | if( is_first_sid_xml->text == ( _bstr_t )L"true" ) 122 | is_first_sid = true; 123 | else 124 | { 125 | if( is_first_sid_xml->text == ( _bstr_t )L"false" ) 126 | is_first_sid = false; 127 | else 128 | return false; 129 | } 130 | 131 | MSXML2::IXMLDOMElementPtr is_hex_only_xml = element->selectSingleNode( L"is_hex_only" ); 132 | if( !is_hex_only_xml ) 133 | return false; 134 | 135 | if( is_hex_only_xml->text == ( _bstr_t )L"true" ) 136 | is_hex_only = true; 137 | else 138 | { 139 | if( is_hex_only_xml->text == ( _bstr_t )L"false" ) 140 | is_hex_only = false; 141 | else 142 | return false; 143 | } 144 | 145 | if( is_hex_only ) 146 | { 147 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 148 | if( !value_hex_xml ) 149 | return false; 150 | 151 | std::wstring str_hex = ( wchar_t* ) value_hex_xml->text; 152 | str_hex = wreplace( str_hex.c_str(), L" ", L"" ); 153 | 154 | if( !from_whex_codes( str_hex.c_str(), str_hex.length(), &value_hex ) ) 155 | return false; 156 | 157 | block_length = str_hex.length() >> 1; 158 | } 159 | else 160 | { 161 | MSXML2::IXMLDOMElementPtr value_dec_xml = element->selectSingleNode( L"value_dec" ); 162 | if( !value_dec_xml ) 163 | return false; 164 | 165 | value_dec = _wtoi64( ( wchar_t* ) value_dec_xml->text ); 166 | if( errno && !value_dec ) 167 | return false; 168 | } 169 | 170 | return true; 171 | } 172 | //************************************************************************** 173 | template< typename In, typename Out > 174 | In SID_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 175 | { 176 | if( !max_block_len ) 177 | return stream_in; 178 | 179 | if( stream_in == In() ) 180 | { 181 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 182 | return stream_in; 183 | } 184 | 185 | value_hex = ( unsigned char* ) malloc( ( size_t )max_block_len ); 186 | if( !value_hex ) 187 | return In(); 188 | 189 | In end = stream_in; 190 | unsigned char* data = value_hex; 191 | 192 | while( (unsigned char)(*end) & 0x80 ) 193 | { 194 | if( block_length > ( max_block_len - 1 ) ) 195 | { 196 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 197 | return end; 198 | } 199 | 200 | *data = (unsigned char)(*end) & 0x7F; 201 | 202 | data++; 203 | end++; 204 | block_length++; 205 | 206 | if( end == In() ) 207 | { 208 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 209 | return end; 210 | } 211 | } 212 | 213 | // The least octet 214 | if( end == In() ) 215 | { 216 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 217 | return end; 218 | } 219 | *data = (unsigned char)(*end) & 0x7F; 220 | block_length++; 221 | end++; 222 | 223 | if( !value_hex[ 0 ] ) 224 | warnings.push_back( "Needlessly long format of SID encoding" ); 225 | 226 | if( block_length <= 8 ) 227 | from_base( value_hex, &value_dec, 7, ( unsigned char )block_length ); 228 | else 229 | { 230 | is_hex_only = true; 231 | warnings.push_back( "Too big SID for decoding, hex only" ); 232 | } 233 | 234 | return end; 235 | } 236 | //************************************************************************** 237 | template< typename In, typename Out > 238 | unsigned long long SID_value_block< In, Out >::encode_BER( bool size_only ) 239 | { 240 | if( is_hex_only ) 241 | { 242 | if( !size_only ) 243 | { 244 | for( unsigned long long i = 0; i < ( block_length - 1 ); i++ ) 245 | stream_out = value_hex[ i ] | 0x80; 246 | 247 | stream_out = value_hex[ block_length - 1 ]; 248 | } 249 | 250 | return block_length; 251 | } 252 | 253 | unsigned char* encoded; 254 | 255 | int size = to_base( value_dec, &encoded, 7 ); 256 | if( !size ) 257 | { 258 | sprintf_s( error, 255, "Error during encoding SID value" ); 259 | free( encoded ); 260 | return 0; 261 | } 262 | 263 | if( !size_only ) 264 | { 265 | for( int i = 0; i < ( size - 1 ); i++ ) 266 | stream_out = encoded[ i ] | 0x80; 267 | 268 | stream_out = encoded[ size - 1 ]; 269 | } 270 | 271 | free( encoded ); 272 | 273 | return size; 274 | } 275 | //************************************************************************** 276 | template< typename In, typename Out > 277 | struct OID_value_block : virtual public value_block_type< In, Out > 278 | { 279 | std::vector< SID_value_block< In, Out >* > value; 280 | 281 | virtual ~OID_value_block(); 282 | 283 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 284 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 285 | 286 | virtual In decode_BER( unsigned long long max_block_len ); 287 | virtual unsigned long long encode_BER( bool size_only = false ); 288 | }; 289 | //************************************************************************** 290 | template< typename In, typename Out > 291 | OID_value_block< In, Out >::~OID_value_block() 292 | { 293 | for( std::vector< SID_value_block< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 294 | delete (*i); 295 | } 296 | //************************************************************************** 297 | template< typename In, typename Out > 298 | MSXML2::IXMLDOMElementPtr OID_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 299 | { 300 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 301 | if( error[ 0 ] != 0x00 ) 302 | return result; 303 | 304 | std::string oid; 305 | 306 | MSXML2::IXMLDOMElementPtr sid_blocks_xml = pDoc->createElement( L"sid_blocks" ); 307 | 308 | bool is_hex_only = false; 309 | 310 | for( std::vector< SID_value_block< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 311 | { 312 | is_hex_only |= (*i)->is_hex_only; 313 | 314 | MSXML2::IXMLDOMElementPtr element = (*i)->to_xml( pDoc ); 315 | sid_blocks_xml->appendChild( element ); 316 | 317 | if( i != value.begin() ) 318 | oid += "."; 319 | 320 | if( (*i)->is_hex_only ) 321 | { 322 | char* buf = ( char* ) malloc( ( size_t ) ( (*i)->block_length + 1 ) ); 323 | if( !buf ) 324 | return result; 325 | 326 | memcpy( buf, (*i)->value_hex, ( size_t )(*i)->block_length ); 327 | buf[ (*i)->block_length ] = 0x00; 328 | 329 | std::string temp_oid = "{" + hex_codes( (*i)->value_hex, (*i)->block_length ) + "}"; 330 | 331 | if( (*i)->is_first_sid ) 332 | oid = "2.{" + temp_oid + " - 80}"; 333 | else 334 | oid += temp_oid; 335 | 336 | free( buf ); 337 | } 338 | else 339 | { 340 | unsigned long long sid = (*i)->value_dec; 341 | 342 | if( (*i)->is_first_sid ) 343 | { 344 | if( (*i)->value_dec <= 39 ) 345 | oid = "0."; 346 | else 347 | { 348 | if( (*i)->value_dec <= 79 ) 349 | { 350 | oid = "1."; 351 | sid -= 40; 352 | } 353 | else 354 | { 355 | oid = "2."; 356 | sid -= 80; 357 | } 358 | } 359 | } 360 | 361 | char buf[255]; 362 | _ui64toa_s( sid, buf, 255, 10 ); 363 | oid += buf; 364 | } 365 | } 366 | 367 | result->appendChild( sid_blocks_xml ); 368 | 369 | MSXML2::IXMLDOMElementPtr is_hex_only_xml = pDoc->createElement( L"is_hex_only" ); 370 | is_hex_only_xml->appendChild( pDoc->createTextNode( ( is_hex_only )? L"true" : L"false" ) ); 371 | result->appendChild( is_hex_only_xml ); 372 | 373 | wchar_t* whex = ( wchar_t* ) malloc( ( oid.length() + 1 ) * sizeof( wchar_t ) ); 374 | memset( whex, 0x00, ( oid.length() + 1 ) * sizeof( wchar_t ) ); 375 | 376 | size_t converted = 0; 377 | errno_t error_num = mbstowcs_s( &converted, whex, oid.length() + 1, oid.c_str(), oid.length() ); 378 | if( error_num ) 379 | { 380 | free( whex ); 381 | return NULL; 382 | } 383 | 384 | MSXML2::IXMLDOMElementPtr value_xml = pDoc->createElement( L"value_dec" ); 385 | value_xml->appendChild( pDoc->createTextNode( whex ) ); 386 | 387 | free( whex ); 388 | 389 | result->appendChild( value_xml ); 390 | 391 | return result; 392 | } 393 | //************************************************************************** 394 | template< typename In, typename Out > 395 | bool OID_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 396 | { 397 | if( !element ) 398 | return false; 399 | 400 | bool is_hex_only = false; 401 | 402 | MSXML2::IXMLDOMElementPtr is_hex_only_xml = element->selectSingleNode( L"is_hex_only" ); 403 | if( !is_hex_only_xml ) 404 | return false; 405 | 406 | if( is_hex_only_xml->text == ( _bstr_t )L"true" ) 407 | is_hex_only = true; 408 | else 409 | { 410 | if( is_hex_only_xml->text == ( _bstr_t )L"false" ) 411 | is_hex_only = false; 412 | else 413 | return false; 414 | } 415 | 416 | if( is_hex_only ) 417 | { 418 | MSXML2::IXMLDOMNodeListPtr list = element->selectNodes( L"./sid_blocks/sid_block" ); 419 | 420 | for( int i = 0; i < list->length; i++ ) 421 | { 422 | SID_value_block< In, Out >* sid = new SID_value_block< In, Out >(); 423 | sid->from_xml( list->item[ i ] ); 424 | value.push_back( sid ); 425 | } 426 | 427 | return true; 428 | } 429 | 430 | MSXML2::IXMLDOMNodePtr value_dec_xml = element->selectSingleNode( L"value_dec" ); 431 | if( !value_dec_xml ) 432 | return false; 433 | 434 | std::wstring str_value = ( wchar_t* )value_dec_xml->firstChild->text; 435 | std::wstring sid; 436 | 437 | std::wstring::size_type pos1 = 0, pos2; 438 | bool flag = false; 439 | 440 | do 441 | { 442 | pos2 = str_value.find( L".", pos1 ); 443 | sid.assign( str_value, pos1, pos2 - pos1 ); 444 | pos1 = pos2 + 1; 445 | 446 | SID_value_block< In, Out >* sid_block = NULL; 447 | 448 | if( flag ) 449 | { 450 | sid_block = value[ 0 ]; 451 | unsigned long long plus = 0; 452 | 453 | switch( sid_block->value_dec ) 454 | { 455 | case 0: 456 | break; 457 | case 1: 458 | plus = 40; 459 | break; 460 | case 2: 461 | plus = 80; 462 | break; 463 | default: 464 | return false; 465 | } 466 | 467 | sid_block->value_dec = _wtoi64( sid.c_str() ) + plus; 468 | 469 | flag = false; 470 | } 471 | else 472 | { 473 | sid_block = new SID_value_block< In, Out >(); 474 | sid_block->value_dec = _wtoi64( sid.c_str() ); 475 | 476 | if( !value.size() ) 477 | { 478 | sid_block->is_first_sid = true; 479 | flag = true; 480 | } 481 | 482 | value.push_back( sid_block ); 483 | } 484 | 485 | }while( pos2 != std::wstring::npos ); 486 | 487 | return true; 488 | } 489 | //************************************************************************** 490 | template< typename In, typename Out > 491 | In OID_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 492 | { 493 | In end = stream_in; 494 | 495 | while( max_block_len ) 496 | { 497 | if( end == In() ) 498 | { 499 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 500 | return end; 501 | } 502 | 503 | SID_value_block< In, Out >* sid_type = new SID_value_block< In, Out >(); 504 | sid_type->stream_in = end; 505 | 506 | end = sid_type->decode_BER( max_block_len ); 507 | if( sid_type->error[ 0 ] != 0x00 ) 508 | { 509 | block_length = 0; 510 | sprintf_s( error, 255, sid_type->error ); 511 | 512 | delete sid_type; 513 | 514 | return end; 515 | } 516 | 517 | if( !(value.size()) ) 518 | sid_type->is_first_sid = true; 519 | 520 | block_length += sid_type->block_length; 521 | max_block_len -= sid_type->block_length; 522 | 523 | value.push_back( sid_type ); 524 | 525 | if( end == In() ) 526 | break; 527 | } 528 | 529 | return end; 530 | } 531 | //************************************************************************** 532 | template< typename In, typename Out > 533 | unsigned long long OID_value_block< In, Out >::encode_BER( bool size_only ) 534 | { 535 | unsigned long long result = 0; 536 | unsigned long long encoded = 0; 537 | 538 | for( std::vector< SID_value_block< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 539 | { 540 | (*i)->stream_out = stream_out; 541 | encoded = (*i)->encode_BER( size_only ); 542 | if( !encoded ) 543 | { 544 | sprintf_s( error, 255, (*i)->error ); 545 | return 0; 546 | } 547 | 548 | result += encoded; 549 | } 550 | 551 | return result; 552 | } 553 | //************************************************************************** 554 | template< typename In, typename Out > 555 | struct OID_type : virtual public BASIC_type< In, Out > 556 | { 557 | OID_type(); 558 | 559 | static std::string block_name_static(); 560 | virtual std::string block_name(); 561 | }; 562 | //************************************************************************** 563 | template< typename In, typename Out > 564 | OID_type< In, Out >::OID_type() 565 | { 566 | tag_class = 1; 567 | tag_number = 6; 568 | 569 | value_block = new OID_value_block< In, Out >(); 570 | } 571 | //************************************************************************** 572 | template< typename In, typename Out > 573 | std::string OID_type< In, Out >::block_name_static() 574 | { 575 | return "OBJECT IDENTIFIER"; 576 | } 577 | //************************************************************************** 578 | template< typename In, typename Out > 579 | std::string OID_type< In, Out >::block_name() 580 | { 581 | return block_name_static(); 582 | } 583 | //************************************************************************** 584 | template< typename In, typename Out > 585 | struct ROID_value_block : virtual public OID_value_block< In, Out > 586 | { 587 | virtual In decode_BER( unsigned long long max_block_len ); 588 | }; 589 | //************************************************************************** 590 | template< typename In, typename Out > 591 | In ROID_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 592 | { 593 | In end = stream_in; 594 | 595 | while( max_block_len ) 596 | { 597 | if( end == In() ) 598 | { 599 | sprintf_s( error, 255, "End of input reached before message was fully decoded" ); 600 | return end; 601 | } 602 | 603 | SID_value_block< In, Out >* sid_type = new SID_value_block< In, Out >(); 604 | sid_type->stream_in = end; 605 | 606 | end = sid_type->decode_BER( max_block_len ); 607 | if( sid_type->error[ 0 ] != 0x00 ) 608 | { 609 | block_length = 0; 610 | sprintf_s( error, 255, sid_type->error ); 611 | 612 | delete sid_type; 613 | 614 | return end; 615 | } 616 | 617 | block_length += sid_type->block_length; 618 | max_block_len -= sid_type->block_length; 619 | 620 | value.push_back( sid_type ); 621 | 622 | if( end == In() ) 623 | break; 624 | } 625 | 626 | return end; 627 | } 628 | //************************************************************************** 629 | template< typename In, typename Out > 630 | struct ROID_type : virtual public BASIC_type< In, Out > 631 | { 632 | ROID_type(); 633 | 634 | static std::string block_name_static(); 635 | virtual std::string block_name(); 636 | }; 637 | //************************************************************************** 638 | template< typename In, typename Out > 639 | ROID_type< In, Out >::ROID_type() 640 | { 641 | tag_class = 1; 642 | tag_number = 13; 643 | 644 | value_block = new ROID_value_block< In, Out >(); 645 | } 646 | //************************************************************************** 647 | template< typename In, typename Out > 648 | std::string ROID_type< In, Out >::block_name_static() 649 | { 650 | return "RELATIVE OBJECT IDENTIFIER"; 651 | } 652 | //************************************************************************** 653 | template< typename In, typename Out > 654 | std::string ROID_type< In, Out >::block_name() 655 | { 656 | return block_name_static(); 657 | } 658 | //************************************************************************** 659 | #endif -------------------------------------------------------------------------------- /code/type_octetstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _C8A3B24B_5E3F_4CEF_BBA1_F1029408A589 27 | #define _C8A3B24B_5E3F_4CEF_BBA1_F1029408A589 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct OCTETSTRING_value_block : virtual public CONSTRUCTED_value_block< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | bool is_constructed; 34 | 35 | OCTETSTRING_value_block(); 36 | 37 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 38 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 39 | 40 | virtual In decode_BER( unsigned long long max_block_len ); 41 | virtual unsigned long long encode_BER( bool size_only = false ); 42 | }; 43 | //************************************************************************** 44 | template< typename In, typename Out > 45 | OCTETSTRING_value_block< In, Out >::OCTETSTRING_value_block() : is_constructed( false ) 46 | { 47 | } 48 | //************************************************************************** 49 | template< typename In, typename Out > 50 | MSXML2::IXMLDOMElementPtr OCTETSTRING_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 51 | { 52 | if( is_constructed ) 53 | return CONSTRUCTED_value_block< In, Out >::to_xml( pDoc ); 54 | else 55 | { 56 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 57 | if( error[ 0 ] != 0x00 ) 58 | return result; 59 | 60 | if( !block_length ) 61 | return result; 62 | 63 | std::string hex = hex_codes( value_hex, block_length ); 64 | 65 | wchar_t* whex = ( wchar_t* ) malloc( ( hex.length() + 1 ) * sizeof( wchar_t ) ); 66 | memset( whex, 0x00, ( hex.length() + 1 ) * sizeof( wchar_t ) ); 67 | 68 | size_t converted = 0; 69 | errno_t error_num = mbstowcs_s( &converted, whex, hex.length() + 1, hex.c_str(), hex.length() ); 70 | if( error_num ) 71 | { 72 | free( whex ); 73 | return result; 74 | } 75 | 76 | MSXML2::IXMLDOMElementPtr value_xml = pDoc->createElement( L"value_hex" ); 77 | value_xml->appendChild( pDoc->createTextNode( whex ) ); 78 | 79 | free( whex ); 80 | 81 | result->appendChild( value_xml ); 82 | 83 | return result; 84 | } 85 | 86 | return NULL; 87 | } 88 | //************************************************************************** 89 | template< typename In, typename Out > 90 | bool OCTETSTRING_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 91 | { 92 | if( !element ) 93 | return false; 94 | 95 | if( is_constructed ) 96 | { 97 | if( !CONSTRUCTED_value_block< In, Out >::from_xml( element ) ) 98 | return false; 99 | 100 | for( std::vector< BASIC_type< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 101 | { 102 | if( (*i)->block_name() != OCTETSTRING_type< In, Out >::block_name_static() ) 103 | { 104 | value.erase( value.begin(), value.end() ); 105 | sprintf_s( error, 255, "OCTET STRING may consists of OCTET STRINGs only" ); 106 | return false; 107 | } 108 | } 109 | } 110 | else 111 | { 112 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 113 | if( !value_hex_xml ) 114 | return false; 115 | 116 | std::wstring str_hex = ( wchar_t* ) value_hex_xml->text; 117 | str_hex = wreplace( str_hex.c_str(), L" ", L"" ); 118 | 119 | if( !from_whex_codes( str_hex.c_str(), str_hex.length(), &value_hex ) ) 120 | return false; 121 | 122 | block_length = str_hex.length() >> 1; 123 | } 124 | 125 | return false; 126 | } 127 | //************************************************************************** 128 | template< typename In, typename Out > 129 | In OCTETSTRING_value_block< In, Out >::decode_BER( unsigned long long max_block_len ) 130 | { 131 | if( is_constructed ) 132 | { 133 | In end = CONSTRUCTED_value_block< In, Out >::decode_BER( max_block_len ); 134 | if( error[ 0 ] != 0x00 ) 135 | return In(); 136 | 137 | for( std::vector< BASIC_type< In, Out >* >::iterator i = value.begin(); i != value.end(); i++ ) 138 | { 139 | if( (*i)->block_name() == EOC_type< In, Out >::block_name_static() ) 140 | { 141 | if( is_indefinite_form ) 142 | break; 143 | else 144 | { 145 | value.erase( value.begin(), value.end() ); 146 | sprintf_s( error, 255, "EOC is unexpected, OCTET STRING may consists of OCTET STRINGs only" ); 147 | return In(); 148 | } 149 | } 150 | 151 | if( (*i)->block_name() != OCTETSTRING_type< In, Out >::block_name_static() ) 152 | { 153 | value.erase( value.begin(), value.end() ); 154 | sprintf_s( error, 255, "OCTET STRING may consists of OCTET STRINGs only" ); 155 | return In(); 156 | } 157 | } 158 | 159 | return end; 160 | } 161 | else 162 | { 163 | In end = hex_block_type::decode_BER( max_block_len ); 164 | if( error[ 0 ] != 0x00 ) 165 | return In(); 166 | 167 | return end; 168 | } 169 | 170 | return In(); 171 | } 172 | //************************************************************************** 173 | template< typename In, typename Out > 174 | unsigned long long OCTETSTRING_value_block< In, Out >::encode_BER( bool size_only ) 175 | { 176 | if( is_constructed ) 177 | return CONSTRUCTED_value_block< In, Out >::encode_BER( size_only ); 178 | else 179 | { 180 | if( size_only ) 181 | return block_length; 182 | 183 | if( !block_length ) 184 | return 0; 185 | 186 | for( unsigned long long i = 0; i < block_length; i++ ) 187 | stream_out = value_hex[ i ]; 188 | 189 | return block_length; 190 | } 191 | 192 | return 0; 193 | } 194 | //************************************************************************** 195 | template< typename In, typename Out > 196 | struct OCTETSTRING_type : virtual public BASIC_type< In, Out > 197 | { 198 | static std::string block_name_static(); 199 | virtual std::string block_name(); 200 | 201 | OCTETSTRING_type(); 202 | 203 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 204 | virtual In decode_BER( unsigned long long max_block_len ); 205 | }; 206 | //************************************************************************** 207 | template< typename In, typename Out > 208 | OCTETSTRING_type< In, Out >::OCTETSTRING_type() 209 | { 210 | tag_class = 1; 211 | tag_number = 4; 212 | 213 | value_block = new OCTETSTRING_value_block< In, Out >(); 214 | } 215 | //************************************************************************** 216 | template< typename In, typename Out > 217 | std::string OCTETSTRING_type< In, Out >::block_name_static() 218 | { 219 | return "OCTET STRING"; 220 | } 221 | //************************************************************************** 222 | template< typename In, typename Out > 223 | std::string OCTETSTRING_type< In, Out >::block_name() 224 | { 225 | return block_name_static(); 226 | } 227 | //************************************************************************** 228 | template< typename In, typename Out > 229 | bool OCTETSTRING_type< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 230 | { 231 | id_block = new identification_block_type< In, Out >(); 232 | if( !id_block->from_xml( element->selectSingleNode( L"./identification_block" ) ) ) 233 | return false; 234 | 235 | if( ( id_block->tag_class != tag_class ) || 236 | ( id_block->tag_number != tag_number ) ) 237 | { 238 | if( ( tag_class != ( unsigned char ) ( -1 ) ) && 239 | ( tag_number != ( unsigned long long ) ( -1 ) ) ) 240 | { 241 | std::string str = "Wrong \"tag_class\" or \"tag_number\" for ASN.1 type " + block_name(); 242 | sprintf_s( id_block->error, 255, str.c_str() ); 243 | return false; 244 | } 245 | } 246 | 247 | len_block = new length_block_type< In, Out >(); 248 | if( !len_block->from_xml( element->selectSingleNode( L"./length_block" ) ) ) 249 | return false; 250 | 251 | OCTETSTRING_value_block< In, Out >* vb = dynamic_cast< OCTETSTRING_value_block< In, Out >* >( value_block ); 252 | if( vb == NULL ) 253 | return false; 254 | 255 | vb->is_constructed = id_block->is_constructed; 256 | vb->is_indefinite_form = len_block->is_indefinite_form; 257 | 258 | if( value_block != NULL ) 259 | if( !value_block->from_xml( element->selectSingleNode( L"./value_block" ) ) ) 260 | return false; 261 | 262 | return true; 263 | } 264 | //************************************************************************** 265 | template< typename In, typename Out > 266 | In OCTETSTRING_type< In, Out >::decode_BER( unsigned long long max_block_len ) 267 | { 268 | if( !max_block_len ) // Ability to encode empty OCTET STRING 269 | return stream_in; 270 | 271 | OCTETSTRING_value_block< In, Out >* vb = dynamic_cast< OCTETSTRING_value_block< In, Out >* >( value_block ); 272 | if( vb == NULL ) 273 | return false; 274 | 275 | vb->is_constructed = id_block->is_constructed; 276 | vb->is_indefinite_form = len_block->is_indefinite_form; 277 | 278 | return BASIC_type< In, Out >::decode_BER( max_block_len ); 279 | } 280 | //************************************************************************** 281 | #endif -------------------------------------------------------------------------------- /code/type_sequence.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _41D7494D_DAAD_41E1_8FA0_B2BD3CD405AE 27 | #define _41D7494D_DAAD_41E1_8FA0_B2BD3CD405AE 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct SEQUENCE_type : virtual public CONSTRUCTED_type< In, Out > 31 | { 32 | SEQUENCE_type(); 33 | 34 | static std::string block_name_static(); 35 | virtual std::string block_name(); 36 | }; 37 | //************************************************************************** 38 | template< typename In, typename Out > 39 | SEQUENCE_type< In, Out >::SEQUENCE_type() 40 | { 41 | tag_class = 1; 42 | tag_number = 16; 43 | } 44 | //************************************************************************** 45 | template< typename In, typename Out > 46 | std::string SEQUENCE_type< In, Out >::block_name_static() 47 | { 48 | return "SEQUENCE"; 49 | } 50 | //************************************************************************** 51 | template< typename In, typename Out > 52 | std::string SEQUENCE_type< In, Out >::block_name() 53 | { 54 | return block_name_static(); 55 | } 56 | //************************************************************************** 57 | template< typename In, typename Out > 58 | struct SET_type : virtual public CONSTRUCTED_type< In, Out > 59 | { 60 | SET_type(); 61 | 62 | static std::string block_name_static(); 63 | virtual std::string block_name(); 64 | }; 65 | //************************************************************************** 66 | template< typename In, typename Out > 67 | SET_type< In, Out >::SET_type() 68 | { 69 | tag_class = 1; 70 | tag_number = 17; 71 | } 72 | //************************************************************************** 73 | template< typename In, typename Out > 74 | std::string SET_type< In, Out >::block_name_static() 75 | { 76 | return "SET"; 77 | } 78 | //************************************************************************** 79 | template< typename In, typename Out > 80 | std::string SET_type< In, Out >::block_name() 81 | { 82 | return block_name_static(); 83 | } 84 | //************************************************************************** 85 | template< typename In, typename Out > 86 | struct EXTERNAL_type : virtual public SEQUENCE_type< In, Out > 87 | { 88 | EXTERNAL_type(); 89 | 90 | static std::string block_name_static(); 91 | virtual std::string block_name(); 92 | }; 93 | //************************************************************************** 94 | template< typename In, typename Out > 95 | EXTERNAL_type< In, Out >::EXTERNAL_type() 96 | { 97 | tag_class = 1; 98 | tag_number = 8; 99 | } 100 | //************************************************************************** 101 | template< typename In, typename Out > 102 | std::string EXTERNAL_type< In, Out >::block_name_static() 103 | { 104 | return "EXTERNAL"; 105 | } 106 | //************************************************************************** 107 | template< typename In, typename Out > 108 | std::string EXTERNAL_type< In, Out >::block_name() 109 | { 110 | return block_name_static(); 111 | } 112 | //************************************************************************** 113 | template< typename In, typename Out > 114 | struct EMBEDDEDPDV_type : virtual public SEQUENCE_type< In, Out > 115 | { 116 | EMBEDDEDPDV_type(); 117 | 118 | static std::string block_name_static(); 119 | virtual std::string block_name(); 120 | }; 121 | //************************************************************************** 122 | template< typename In, typename Out > 123 | EMBEDDEDPDV_type< In, Out >::EMBEDDEDPDV_type() 124 | { 125 | tag_class = 1; 126 | tag_number = 11; 127 | } 128 | //************************************************************************** 129 | template< typename In, typename Out > 130 | std::string EMBEDDEDPDV_type< In, Out >::block_name_static() 131 | { 132 | return "EMBEDDEDPDV"; 133 | } 134 | //************************************************************************** 135 | template< typename In, typename Out > 136 | std::string EMBEDDEDPDV_type< In, Out >::block_name() 137 | { 138 | return block_name_static(); 139 | } 140 | //************************************************************************** 141 | #endif -------------------------------------------------------------------------------- /code/type_set.h: -------------------------------------------------------------------------------- 1 | #ifndef _F9D10B75_D83A_4178_8887_CE9BC5E2844C 2 | #define _F9D10B75_D83A_4178_8887_CE9BC5E2844C 3 | //************************************************************************** 4 | struct SET_type : virtual public CONSTRUCTED_type 5 | { 6 | virtual ~SET_type(); 7 | 8 | virtual std::string type_name(); 9 | }; 10 | //************************************************************************** 11 | SET_type::~SET_type() 12 | { 13 | } 14 | //************************************************************************** 15 | std::string SET_type::type_name() 16 | { 17 | return "SET"; 18 | } 19 | //************************************************************************** 20 | #endif -------------------------------------------------------------------------------- /code/type_strings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Yury Strozhevsky . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #ifndef _55A67A0D_B3AE_4635_8274_BF209D7E88A4 27 | #define _55A67A0D_B3AE_4635_8274_BF209D7E88A4 28 | //************************************************************************** 29 | template< typename In, typename Out > 30 | struct UTF8STRING_value_block : virtual public value_block_type< In, Out >, 31 | virtual public hex_block_type< In, Out > 32 | { 33 | UTF8STRING_value_block(); 34 | 35 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 36 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 37 | }; 38 | //************************************************************************** 39 | template< typename In, typename Out > 40 | UTF8STRING_value_block< In, Out >::UTF8STRING_value_block() 41 | { 42 | } 43 | //************************************************************************** 44 | template< typename In, typename Out > 45 | MSXML2::IXMLDOMElementPtr UTF8STRING_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 46 | { 47 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 48 | if( error[ 0 ] != 0x00 ) 49 | return result; 50 | 51 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 52 | 53 | unsigned long long value_len = block_length; 54 | 55 | int wide_string_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, (LPCSTR)value_hex, ( int )block_length, NULL, 0 ); 56 | if( !wide_string_len ) 57 | { 58 | sprintf_s( error, 255, "MultiByteToWideChar error" ); 59 | return result; 60 | } 61 | 62 | wchar_t* wide_buf = (wchar_t*) malloc( ( wide_string_len + 1 ) * sizeof( wchar_t ) ); // "wide_string_len" is in "chars", hence multiply it by 2 63 | memset( wide_buf, 0x00, ( wide_string_len + 1 ) * sizeof( wchar_t ) ); 64 | 65 | wide_string_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, (LPCSTR)value_hex, ( int )block_length, (LPWSTR)wide_buf, wide_string_len ); 66 | if( !wide_string_len ) 67 | { 68 | sprintf_s( error, 255, "MultiByteToWideChar error" ); 69 | free( wide_buf ); 70 | return result; 71 | } 72 | 73 | value_hex_xml->appendChild( pDoc->createTextNode( wide_buf ) ); 74 | 75 | free( wide_buf ); 76 | 77 | result->appendChild( value_hex_xml ); 78 | 79 | return result; 80 | } 81 | //************************************************************************** 82 | template< typename In, typename Out > 83 | bool UTF8STRING_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 84 | { 85 | if( !element ) 86 | return false; 87 | 88 | if( value_hex ) 89 | free( value_hex ); 90 | 91 | is_hex_only = true; 92 | 93 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 94 | if( !value_hex_xml ) 95 | return false; 96 | 97 | std::wstring text = ( wchar_t* ) value_hex_xml->text; 98 | 99 | int string_len = WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)value_hex_xml->text, -1, NULL, 0, NULL, NULL ); 100 | if( !string_len ) 101 | return false; 102 | 103 | value_hex = ( unsigned char* ) malloc( string_len ); 104 | 105 | string_len = WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)value_hex_xml->text, -1, ( char* ) value_hex, string_len, NULL, NULL ); 106 | if( !string_len ) 107 | return false; 108 | 109 | block_length = string_len - 1; // minus least NULL symbols 110 | 111 | return true; 112 | } 113 | //************************************************************************** 114 | template< typename In, typename Out > 115 | struct UTF8STRING_type : virtual public BASIC_type< In, Out > 116 | { 117 | UTF8STRING_type(); 118 | 119 | static std::string block_name_static(); 120 | virtual std::string block_name(); 121 | }; 122 | //************************************************************************** 123 | template< typename In, typename Out > 124 | UTF8STRING_type< In, Out >::UTF8STRING_type() 125 | { 126 | tag_class = 1; 127 | tag_number = 12; 128 | 129 | value_block = new UTF8STRING_value_block< In, Out >(); 130 | } 131 | //************************************************************************** 132 | template< typename In, typename Out > 133 | std::string UTF8STRING_type< In, Out >::block_name_static() 134 | { 135 | return "UTF8STRING"; 136 | } 137 | //************************************************************************** 138 | template< typename In, typename Out > 139 | std::string UTF8STRING_type< In, Out >::block_name() 140 | { 141 | return block_name_static(); 142 | } 143 | //************************************************************************** 144 | template< typename In, typename Out > 145 | struct BMPSTRING_value_block : virtual public value_block_type< In, Out >, 146 | virtual public hex_block_type< In, Out > 147 | { 148 | BMPSTRING_value_block(); 149 | 150 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 151 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 152 | }; 153 | //************************************************************************** 154 | template< typename In, typename Out > 155 | BMPSTRING_value_block< In, Out >::BMPSTRING_value_block() 156 | { 157 | } 158 | //************************************************************************** 159 | template< typename In, typename Out > 160 | MSXML2::IXMLDOMElementPtr BMPSTRING_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 161 | { 162 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 163 | if( error[ 0 ] != 0x00 ) 164 | return result; 165 | 166 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 167 | 168 | std::string codes = xcodes( value_hex, block_length, 2 ); 169 | 170 | wchar_t* wcodes = ( wchar_t* ) malloc( ( codes.length() + 1 ) * sizeof( wchar_t ) ); 171 | size_t converted = 0; 172 | errno_t error_num = mbstowcs_s( &converted, wcodes, ( codes.length() + 1 ), codes.c_str(), ( codes.length() + 1 ) ); 173 | if( error_num ) 174 | { 175 | sprintf_s( error, 255, "Wrong name convertion" ); 176 | return NULL; 177 | } 178 | 179 | value_hex_xml->appendChild( pDoc->createTextNode( wcodes ) ); 180 | result->appendChild( value_hex_xml ); 181 | 182 | free( wcodes ); 183 | 184 | return result; 185 | } 186 | //************************************************************************** 187 | template< typename In, typename Out > 188 | bool BMPSTRING_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 189 | { 190 | if( !element ) 191 | return false; 192 | 193 | if( value_hex ) 194 | free( value_hex ); 195 | 196 | is_hex_only = true; 197 | 198 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 199 | if( !value_hex_xml ) 200 | return false; 201 | 202 | block_length = value_hex_xml->text.length(); 203 | 204 | value_hex = ( unsigned char* ) malloc( ( size_t )( block_length * 2 ) ); 205 | if( !value_hex ) 206 | return false; 207 | 208 | wchar_t* wstring = ( wchar_t* )value_hex_xml->text; 209 | 210 | for( size_t i = 0; i < block_length; i++ ) 211 | { 212 | value_hex[ i * 2 + 0 ] = ( ( char* )wstring )[ i * 2 + 1 ]; 213 | value_hex[ i * 2 + 1 ] = ( ( char* )wstring )[ i * 2 + 0 ]; 214 | } 215 | 216 | block_length *= 2; 217 | 218 | return true; 219 | } 220 | //************************************************************************** 221 | template< typename In, typename Out > 222 | struct BMPSTRING_type : virtual public BASIC_type< In, Out > 223 | { 224 | BMPSTRING_type(); 225 | 226 | static std::string block_name_static(); 227 | virtual std::string block_name(); 228 | }; 229 | //************************************************************************** 230 | template< typename In, typename Out > 231 | BMPSTRING_type< In, Out >::BMPSTRING_type() 232 | { 233 | tag_class = 1; 234 | tag_number = 30; 235 | 236 | value_block = new BMPSTRING_value_block< In, Out >(); 237 | } 238 | //************************************************************************** 239 | template< typename In, typename Out > 240 | std::string BMPSTRING_type< In, Out >::block_name_static() 241 | { 242 | return "BMPSTRING"; 243 | } 244 | //************************************************************************** 245 | template< typename In, typename Out > 246 | std::string BMPSTRING_type< In, Out >::block_name() 247 | { 248 | return block_name_static(); 249 | } 250 | //************************************************************************** 251 | template< typename In, typename Out > 252 | struct UNIVERSALSTRING_value_block : virtual public value_block_type< In, Out >, 253 | virtual public hex_block_type< In, Out > 254 | { 255 | UNIVERSALSTRING_value_block(); 256 | 257 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 258 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 259 | }; 260 | //************************************************************************** 261 | template< typename In, typename Out > 262 | UNIVERSALSTRING_value_block< In, Out >::UNIVERSALSTRING_value_block() 263 | { 264 | } 265 | //************************************************************************** 266 | template< typename In, typename Out > 267 | MSXML2::IXMLDOMElementPtr UNIVERSALSTRING_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 268 | { 269 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 270 | if( error[ 0 ] != 0x00 ) 271 | return result; 272 | 273 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 274 | 275 | std::string codes = xcodes( value_hex, block_length, 4 ); 276 | 277 | wchar_t* wcodes = ( wchar_t* ) malloc( ( codes.length() + 1 ) * sizeof( wchar_t ) ); 278 | size_t converted = 0; 279 | errno_t error_num = mbstowcs_s( &converted, wcodes, ( codes.length() + 1 ), codes.c_str(), ( codes.length() + 1 ) ); 280 | if( error_num ) 281 | { 282 | sprintf_s( error, 255, "Wrong name convertion" ); 283 | return NULL; 284 | } 285 | 286 | value_hex_xml->appendChild( pDoc->createTextNode( wcodes ) ); 287 | result->appendChild( value_hex_xml ); 288 | 289 | free( wcodes ); 290 | 291 | return result; 292 | } 293 | //************************************************************************** 294 | template< typename In, typename Out > 295 | bool UNIVERSALSTRING_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 296 | { 297 | if( !element ) 298 | return false; 299 | 300 | if( value_hex ) 301 | free( value_hex ); 302 | 303 | is_hex_only = true; 304 | 305 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 306 | if( !value_hex_xml ) 307 | return false; 308 | 309 | block_length = value_hex_xml->text.length(); 310 | 311 | value_hex = ( unsigned char* ) malloc( ( size_t )( block_length * 4 ) ); 312 | if( !value_hex ) 313 | return false; 314 | 315 | wchar_t* wstring = ( wchar_t* )value_hex_xml->text; 316 | 317 | for( size_t i = 0; i < block_length; i++ ) 318 | { 319 | value_hex[ i * 4 + 0 ] = 0x00; 320 | value_hex[ i * 4 + 1 ] = 0x00; 321 | value_hex[ i * 4 + 2 ] = ( ( char* )wstring )[ i * 2 + 1 ]; 322 | value_hex[ i * 4 + 3 ] = ( ( char* )wstring )[ i * 2 + 0 ]; 323 | } 324 | 325 | block_length *= 4; 326 | 327 | return true; 328 | } 329 | //************************************************************************** 330 | template< typename In, typename Out > 331 | struct UNIVERSALSTRING_type : virtual public BASIC_type< In, Out > 332 | { 333 | UNIVERSALSTRING_type(); 334 | 335 | static std::string block_name_static(); 336 | virtual std::string block_name(); 337 | }; 338 | //************************************************************************** 339 | template< typename In, typename Out > 340 | UNIVERSALSTRING_type< In, Out >::UNIVERSALSTRING_type() 341 | { 342 | tag_class = 1; 343 | tag_number = 28; 344 | 345 | value_block = new UNIVERSALSTRING_value_block< In, Out >(); 346 | } 347 | //************************************************************************** 348 | template< typename In, typename Out > 349 | std::string UNIVERSALSTRING_type< In, Out >::block_name_static() 350 | { 351 | return "UNIVERSALSTRING"; 352 | } 353 | //************************************************************************** 354 | template< typename In, typename Out > 355 | std::string UNIVERSALSTRING_type< In, Out >::block_name() 356 | { 357 | return block_name_static(); 358 | } 359 | //************************************************************************** 360 | template< typename In, typename Out > 361 | struct SIMPLESTRING_value_block : virtual public value_block_type< In, Out >, 362 | virtual public hex_block_type< In, Out > 363 | { 364 | SIMPLESTRING_value_block(); 365 | 366 | virtual MSXML2::IXMLDOMElementPtr to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ); 367 | virtual bool from_xml( MSXML2::IXMLDOMElementPtr element ); 368 | }; 369 | //************************************************************************** 370 | template< typename In, typename Out > 371 | SIMPLESTRING_value_block< In, Out >::SIMPLESTRING_value_block() 372 | { 373 | } 374 | //************************************************************************** 375 | template< typename In, typename Out > 376 | MSXML2::IXMLDOMElementPtr SIMPLESTRING_value_block< In, Out >::to_xml( MSXML2::IXMLDOMDocumentPtr pDoc ) 377 | { 378 | MSXML2::IXMLDOMElementPtr result = block_type< In, Out >::to_xml( pDoc ); 379 | if( error[ 0 ] != 0x00 ) 380 | return result; 381 | 382 | if( !block_length ) 383 | return result; 384 | 385 | MSXML2::IXMLDOMElementPtr value_hex_xml = pDoc->createElement( L"value_hex" ); 386 | 387 | wchar_t* value_buf = NULL; 388 | 389 | try // try to store as a string 390 | { 391 | unsigned long long value_len = block_length; 392 | value_buf = ( wchar_t* ) malloc( ( size_t ) ( ( value_len + 1 ) * sizeof( wchar_t ) ) ); 393 | 394 | size_t converted = 0; 395 | errno_t error_num = mbstowcs_s( &converted, value_buf, ( size_t ) ( value_len + 1 ), (char*)value_hex, ( size_t )value_len ); 396 | if( error_num || ( converted == 1 ) ) // if error or converted only NULL character 397 | throw ""; 398 | 399 | value_hex_xml->appendChild( pDoc->createTextNode( value_buf ) ); 400 | result->appendChild( value_hex_xml ); 401 | 402 | free( value_buf ); 403 | } 404 | catch(...) // a problem, store as a "hex-encoded" value 405 | { 406 | free( value_buf ); 407 | 408 | value_hex_xml->put_dataType( L"bin.hex" ); 409 | 410 | SAFEARRAY* psa = SafeArrayCreateVector( VT_UI1, 0L, ( ULONG )block_length ); 411 | if( psa == NULL ) 412 | return result; 413 | 414 | memcpy( psa->pvData, value_hex, ( size_t )block_length ); 415 | 416 | VARIANT var; 417 | VariantInit( &var ); 418 | var.parray = psa; 419 | var.vt = ( VT_ARRAY | VT_UI1 ); 420 | 421 | value_hex_xml->nodeTypedValue = var; 422 | 423 | HRESULT hr = SafeArrayDestroy( psa ); 424 | if( FAILED( hr )) 425 | return result; 426 | 427 | result->appendChild( value_hex_xml ); 428 | } 429 | 430 | return result; 431 | } 432 | //************************************************************************** 433 | template< typename In, typename Out > 434 | bool SIMPLESTRING_value_block< In, Out >::from_xml( MSXML2::IXMLDOMElementPtr element ) 435 | { 436 | if( !element ) 437 | return false; 438 | 439 | is_hex_only = true; 440 | 441 | MSXML2::IXMLDOMElementPtr value_hex_xml = element->selectSingleNode( L"value_hex" ); 442 | if( !value_hex_xml ) 443 | return false; 444 | 445 | std::wstring text = ( wchar_t* ) value_hex_xml->text; 446 | 447 | value_hex = ( unsigned char* ) malloc( text.length() + 1 ); 448 | 449 | size_t converted = 0; 450 | errno_t errnum = wcstombs_s( &converted, (char*) value_hex, text.length() + 1, text.c_str(), text.length() ); 451 | if( errnum ) 452 | return false; 453 | 454 | block_length = text.length(); 455 | 456 | return true; 457 | } 458 | //************************************************************************** 459 | template< typename In, typename Out > 460 | struct SIMPLESTRING_type : virtual public BASIC_type< In, Out > 461 | { 462 | SIMPLESTRING_type(); 463 | 464 | static std::string block_name_static(); 465 | virtual std::string block_name(); 466 | }; 467 | //************************************************************************** 468 | template< typename In, typename Out > 469 | SIMPLESTRING_type< In, Out >::SIMPLESTRING_type() 470 | { 471 | value_block = new SIMPLESTRING_value_block< In, Out >(); 472 | } 473 | //************************************************************************** 474 | template< typename In, typename Out > 475 | std::string SIMPLESTRING_type< In, Out >::block_name_static() 476 | { 477 | return "SIMPLESTRING"; 478 | } 479 | //************************************************************************** 480 | template< typename In, typename Out > 481 | std::string SIMPLESTRING_type< In, Out >::block_name() 482 | { 483 | return block_name_static(); 484 | } 485 | //************************************************************************** 486 | template< typename In, typename Out > 487 | struct NUMERICSTRING_type : virtual public SIMPLESTRING_type< In, Out > 488 | { 489 | NUMERICSTRING_type(); 490 | 491 | static std::string block_name_static(); 492 | virtual std::string block_name(); 493 | }; 494 | //************************************************************************** 495 | template< typename In, typename Out > 496 | NUMERICSTRING_type< In, Out >::NUMERICSTRING_type() 497 | { 498 | tag_class = 1; 499 | tag_number = 18; 500 | } 501 | //************************************************************************** 502 | template< typename In, typename Out > 503 | std::string NUMERICSTRING_type< In, Out >::block_name_static() 504 | { 505 | return "NUMERICSTRING"; 506 | } 507 | //************************************************************************** 508 | template< typename In, typename Out > 509 | std::string NUMERICSTRING_type< In, Out >::block_name() 510 | { 511 | return block_name_static(); 512 | } 513 | //************************************************************************** 514 | template< typename In, typename Out > 515 | struct PRINTABLESTRING_type : virtual public SIMPLESTRING_type< In, Out > 516 | { 517 | PRINTABLESTRING_type(); 518 | 519 | static std::string block_name_static(); 520 | virtual std::string block_name(); 521 | }; 522 | //************************************************************************** 523 | template< typename In, typename Out > 524 | PRINTABLESTRING_type< In, Out >::PRINTABLESTRING_type() 525 | { 526 | tag_class = 1; 527 | tag_number = 19; 528 | } 529 | //************************************************************************** 530 | template< typename In, typename Out > 531 | std::string PRINTABLESTRING_type< In, Out >::block_name_static() 532 | { 533 | return "PRINTABLESTRING"; 534 | } 535 | //************************************************************************** 536 | template< typename In, typename Out > 537 | std::string PRINTABLESTRING_type< In, Out >::block_name() 538 | { 539 | return block_name_static(); 540 | } 541 | //************************************************************************** 542 | template< typename In, typename Out > 543 | struct TELETEXSTRING_type : virtual public SIMPLESTRING_type< In, Out > 544 | { 545 | TELETEXSTRING_type(); 546 | 547 | static std::string block_name_static(); 548 | virtual std::string block_name(); 549 | }; 550 | //************************************************************************** 551 | template< typename In, typename Out > 552 | TELETEXSTRING_type< In, Out >::TELETEXSTRING_type() 553 | { 554 | tag_class = 1; 555 | tag_number = 20; 556 | } 557 | //************************************************************************** 558 | template< typename In, typename Out > 559 | std::string TELETEXSTRING_type< In, Out >::block_name_static() 560 | { 561 | return "TELETEXSTRING"; 562 | } 563 | //************************************************************************** 564 | template< typename In, typename Out > 565 | std::string TELETEXSTRING_type< In, Out >::block_name() 566 | { 567 | return block_name_static(); 568 | } 569 | //************************************************************************** 570 | template< typename In, typename Out > 571 | struct VIDEOTEXSTRING_type : virtual public SIMPLESTRING_type< In, Out > 572 | { 573 | VIDEOTEXSTRING_type(); 574 | 575 | static std::string block_name_static(); 576 | virtual std::string block_name(); 577 | }; 578 | //************************************************************************** 579 | template< typename In, typename Out > 580 | VIDEOTEXSTRING_type< In, Out >::VIDEOTEXSTRING_type() 581 | { 582 | tag_class = 1; 583 | tag_number = 21; 584 | } 585 | //************************************************************************** 586 | template< typename In, typename Out > 587 | std::string VIDEOTEXSTRING_type< In, Out >::block_name_static() 588 | { 589 | return "VIDEOTEXSTRING"; 590 | } 591 | //************************************************************************** 592 | template< typename In, typename Out > 593 | std::string VIDEOTEXSTRING_type< In, Out >::block_name() 594 | { 595 | return block_name_static(); 596 | } 597 | //************************************************************************** 598 | template< typename In, typename Out > 599 | struct IA5STRING_type : virtual public SIMPLESTRING_type< In, Out > 600 | { 601 | IA5STRING_type(); 602 | 603 | static std::string block_name_static(); 604 | virtual std::string block_name(); 605 | }; 606 | //************************************************************************** 607 | template< typename In, typename Out > 608 | IA5STRING_type< In, Out >::IA5STRING_type() 609 | { 610 | tag_class = 1; 611 | tag_number = 22; 612 | } 613 | //************************************************************************** 614 | template< typename In, typename Out > 615 | std::string IA5STRING_type< In, Out >::block_name_static() 616 | { 617 | return "IA5STRING"; 618 | } 619 | //************************************************************************** 620 | template< typename In, typename Out > 621 | std::string IA5STRING_type< In, Out >::block_name() 622 | { 623 | return block_name_static(); 624 | } 625 | //************************************************************************** 626 | template< typename In, typename Out > 627 | struct GRAPHICSTRING_type : virtual public SIMPLESTRING_type< In, Out > 628 | { 629 | GRAPHICSTRING_type(); 630 | 631 | static std::string block_name_static(); 632 | virtual std::string block_name(); 633 | }; 634 | //************************************************************************** 635 | template< typename In, typename Out > 636 | GRAPHICSTRING_type< In, Out >::GRAPHICSTRING_type() 637 | { 638 | tag_class = 1; 639 | tag_number = 25; 640 | } 641 | //************************************************************************** 642 | template< typename In, typename Out > 643 | std::string GRAPHICSTRING_type< In, Out >::block_name_static() 644 | { 645 | return "GRAPHICSTRING"; 646 | } 647 | //************************************************************************** 648 | template< typename In, typename Out > 649 | std::string GRAPHICSTRING_type< In, Out >::block_name() 650 | { 651 | return block_name_static(); 652 | } 653 | //************************************************************************** 654 | template< typename In, typename Out > 655 | struct VISIBLESTRING_type : virtual public SIMPLESTRING_type< In, Out > 656 | { 657 | VISIBLESTRING_type(); 658 | 659 | static std::string block_name_static(); 660 | virtual std::string block_name(); 661 | }; 662 | //************************************************************************** 663 | template< typename In, typename Out > 664 | VISIBLESTRING_type< In, Out >::VISIBLESTRING_type() 665 | { 666 | tag_class = 1; 667 | tag_number = 26; 668 | } 669 | //************************************************************************** 670 | template< typename In, typename Out > 671 | std::string VISIBLESTRING_type< In, Out >::block_name_static() 672 | { 673 | return "VISIBLESTRING"; 674 | } 675 | //************************************************************************** 676 | template< typename In, typename Out > 677 | std::string VISIBLESTRING_type< In, Out >::block_name() 678 | { 679 | return block_name_static(); 680 | } 681 | //************************************************************************** 682 | template< typename In, typename Out > 683 | struct GENERALSTRING_type : virtual public SIMPLESTRING_type< In, Out > 684 | { 685 | GENERALSTRING_type(); 686 | 687 | static std::string block_name_static(); 688 | virtual std::string block_name(); 689 | }; 690 | //************************************************************************** 691 | template< typename In, typename Out > 692 | GENERALSTRING_type< In, Out >::GENERALSTRING_type() 693 | { 694 | tag_class = 1; 695 | tag_number = 27; 696 | } 697 | //************************************************************************** 698 | template< typename In, typename Out > 699 | std::string GENERALSTRING_type< In, Out >::block_name_static() 700 | { 701 | return "GENERALSTRING"; 702 | } 703 | //************************************************************************** 704 | template< typename In, typename Out > 705 | std::string GENERALSTRING_type< In, Out >::block_name() 706 | { 707 | return block_name_static(); 708 | } 709 | //************************************************************************** 710 | template< typename In, typename Out > 711 | struct CHARACTERSTRING_type : virtual public SIMPLESTRING_type< In, Out > 712 | { 713 | CHARACTERSTRING_type(); 714 | 715 | static std::string block_name_static(); 716 | virtual std::string block_name(); 717 | }; 718 | //************************************************************************** 719 | template< typename In, typename Out > 720 | CHARACTERSTRING_type< In, Out >::CHARACTERSTRING_type() 721 | { 722 | tag_class = 1; 723 | tag_number = 29; 724 | } 725 | //************************************************************************** 726 | template< typename In, typename Out > 727 | std::string CHARACTERSTRING_type< In, Out >::block_name_static() 728 | { 729 | return "CHARACTERSTRING"; 730 | } 731 | //************************************************************************** 732 | template< typename In, typename Out > 733 | std::string CHARACTERSTRING_type< In, Out >::block_name() 734 | { 735 | return block_name_static(); 736 | } 737 | //************************************************************************** 738 | template< typename In, typename Out > 739 | struct OBJECTDESCRIPTOR_type : virtual public SIMPLESTRING_type< In, Out > 740 | { 741 | OBJECTDESCRIPTOR_type(); 742 | 743 | static std::string block_name_static(); 744 | virtual std::string block_name(); 745 | }; 746 | //************************************************************************** 747 | template< typename In, typename Out > 748 | OBJECTDESCRIPTOR_type< In, Out >::OBJECTDESCRIPTOR_type() 749 | { 750 | tag_class = 1; 751 | tag_number = 7; 752 | } 753 | //************************************************************************** 754 | template< typename In, typename Out > 755 | std::string OBJECTDESCRIPTOR_type< In, Out >::block_name_static() 756 | { 757 | return "OBJECT DESCRIPTOR"; 758 | } 759 | //************************************************************************** 760 | template< typename In, typename Out > 761 | std::string OBJECTDESCRIPTOR_type< In, Out >::block_name() 762 | { 763 | return block_name_static(); 764 | } 765 | //************************************************************************** 766 | template< typename In, typename Out > 767 | struct OIDINTER_type : virtual public UTF8STRING_type< In, Out > 768 | { 769 | OIDINTER_type(); 770 | 771 | static std::string block_name_static(); 772 | virtual std::string block_name(); 773 | }; 774 | //************************************************************************** 775 | template< typename In, typename Out > 776 | OIDINTER_type< In, Out >::OIDINTER_type() 777 | { 778 | tag_class = 1; 779 | tag_number = 35; 780 | } 781 | //************************************************************************** 782 | template< typename In, typename Out > 783 | std::string OIDINTER_type< In, Out >::block_name_static() 784 | { 785 | return "OID INTERNATIONALIZED"; 786 | } 787 | //************************************************************************** 788 | template< typename In, typename Out > 789 | std::string OIDINTER_type< In, Out >::block_name() 790 | { 791 | return block_name_static(); 792 | } 793 | //************************************************************************** 794 | template< typename In, typename Out > 795 | struct ROIDINTER_type : virtual public UTF8STRING_type< In, Out > 796 | { 797 | ROIDINTER_type(); 798 | 799 | static std::string block_name_static(); 800 | virtual std::string block_name(); 801 | }; 802 | //************************************************************************** 803 | template< typename In, typename Out > 804 | ROIDINTER_type< In, Out >::ROIDINTER_type() 805 | { 806 | tag_class = 1; 807 | tag_number = 36; 808 | } 809 | //************************************************************************** 810 | template< typename In, typename Out > 811 | std::string ROIDINTER_type< In, Out >::block_name_static() 812 | { 813 | return "RELATIVE OID INTERNATIONALIZED"; 814 | } 815 | //************************************************************************** 816 | template< typename In, typename Out > 817 | std::string ROIDINTER_type< In, Out >::block_name() 818 | { 819 | return block_name_static(); 820 | } 821 | //************************************************************************** 822 | #endif --------------------------------------------------------------------------------