1#include <stdio.h> 2#include <string.h> 3 4/////////////////////////////////////////////////////////////// 5// global data 6enum EnumMode { enum_Mode_Quiet, enum_Mode_Default, enum_Mode_MDF } g_eMode = enum_Mode_Default; 7 8const char* c_szType[] = { 9 "null", "chr", "int", "bool", 10 "bin", "node", "", "", 11 "", "test", "", "", 12 "", "", "", "" 13}; 14 15const char* c_szAccess[] = { 16 "", // 0 17 "access:Add", // 1 18 "access:Delete", // 2 19 "access:Add,Delete", // 2 + 1 20 "access:Get", // 4 21 "access:Get,Add", // 1+4 22 "access:Get,Delete", // 2 + 4 23 "access:Get,Add,Delete", // 1 +2+4 24 "access:Replace", // 8 25 "access:Add,Replace", // 1 + 8 26 "access:Delete,Replace", // 2 + 8 27 "access:Add,Delete,Replace", // 1 +2+8 28 "access:Get,Replace", // 4 + 8 29 "access:Add,Get,Replace", // 1+ 4 +8 30 "access:Delete,Get,Replace", // 2 + 4 + 8 31 "access:Add,Delete,Get,Replace", // 1+ 2 + 4 + 8 32 33 "access:Exec", // 0 34 "access:Exec,Add", // 1 35 "access:Exec,Delete", // 2 36 "access:Exec,Add,Delete", // 2 + 1 37 "access:Exec,Get", // 4 38 "access:Exec,Get,Add", // 1+4 39 "access:Exec,Get,Delete", // 2 + 4 40 "access:Exec,Get,Add,Delete", // 1 +2+4 41 "access:Exec,Replace", // 8 42 "access:Exec,Add,Replace", // 1 + 8 43 "access:Exec,Delete,Replace", // 2 + 8 44 "access:Exec,Add,Delete,Replace", // 1 +2+8 45 "access:Exec,Get,Replace", // 4 + 8 46 "access:Exec,Add,Get,Replace", // 1+ 4 +8 47 "access:Exec,Delete,Get,Replace", // 2 + 4 + 8 48 "access:Exec,Add,Delete,Get,Replace", // 1+ 2 + 4 + 8 49 50}; 51 52/////////////////////////////////////////////////////////////// 53/////////////////////////////////////////////////////////////// 54static int GetInt( const unsigned char* buf, int& nOffset ) 55{ 56 int value = 0; 57 58 for (int i=0; i < 4; i++) 59 { 60 value |= (*(buf+nOffset)) << (i*8); 61 nOffset++; 62 } 63 return value; 64} 65 66/////////////////////////////////////////////////////////////// 67static int GetInt16( const unsigned char* buf, int& nOffset ) 68{ 69 int value = 0; 70 71 for (int i=0; i < 2; i++) 72 { 73 value |= (*(buf+nOffset)) << (i*8); 74 nOffset++; 75 } 76 return value; 77} 78 79 80/////////////////////////////////////////////////////////////// 81static int GetPrintItem( const unsigned char* buf, int& nOffset, long nSize, int nLevel, const char* szParentURI ) 82{ 83 int nRes = 0; 84 char szIndent[100]; 85 int nStartOffset = nOffset; 86 char szCurrentURI[1024]; 87 88 strcpy( szCurrentURI, szParentURI ); 89 90 for ( int i = 0; i < nLevel; i++ ){ 91 szIndent[i] = '\t'; 92 } 93 szIndent[nLevel]=0; 94 95 if ( nOffset + 11 >= nSize ){ 96 if ( g_eMode != enum_Mode_Quiet ) 97 printf( "Item does not fit buffer completelly, offset %d, \n", nOffset); 98 99 return 6; 100 } 101 102 int nNameOffset = GetInt( buf, nOffset ); 103 104 const unsigned char* szName = buf + nNameOffset; 105 106 if ( nNameOffset >= nSize ){ 107 szName = (const unsigned char*)"<<out of the buffer>>"; 108 nRes = 7; 109 } 110 111 strcat( szCurrentURI, (const char*)szName ); 112 113 int nType = GetInt16( buf, nOffset ); 114 int nIDOffset = 0; 115 116 if ( nType & 0x400 ) 117 nIDOffset = GetInt( buf, nOffset ); 118 119 const unsigned char* szID = nIDOffset ? buf + nIDOffset :(const unsigned char*)"<unset>"; 120 121 if ( nIDOffset >= nSize ){ 122 szID = (const unsigned char*)"<<out of the buffer>>"; 123 nRes = 7; 124 } 125 126 int nAccess = buf[nOffset++]; 127 int nMimeType = buf[nOffset++]; 128 int nChildren = GetInt16( buf, nOffset ); 129 130 int aChildren[500]; 131 132 if ( nOffset + nChildren * 4 >= nSize ){ 133 if ( g_eMode != enum_Mode_Quiet ) 134 printf( "Item does not fit buffer completelly, offset %d, \n", nOffset); 135 136 return 6; 137 } 138 139 for( int i = 0; i < nChildren; i++ ){ 140 aChildren[i] = GetInt(buf, nOffset ); 141 } 142 143 int nConst = buf[nOffset++]; 144 145 if ( g_eMode == enum_Mode_Default) 146 printf( "%s%04x-%04x: Name (%03x): \"%s\", type %x\tid %s\taccess %x,\tmime %x,\tchildren count %x,\t constr %x\n", 147 szIndent, nStartOffset, nOffset-1, nNameOffset, 148 szName, 149 /*szIndent,*/ nType, szID, 150 nAccess, nMimeType, nChildren, nConst ); 151 else if ( g_eMode == enum_Mode_MDF) { 152 printf( "[%s]\n" 153 "type:%s\n%s\n", 154 szCurrentURI, 155 c_szType[nType &0x0f], 156 c_szAccess[nAccess &0x1f] ); 157 158 if ( nType & 0x400 ) 159 printf( "ID:%s\n", szID ); 160 161 if ( nType & 0x200 ) 162 printf( "HandledByPlugin:1\n" ); 163 164 if ( nType & 0x100 ) 165 printf( "storesPD:1\n" ); 166 } 167 168 if ( strcmp( (const char*)szName, "." ) ==0 ) 169 szCurrentURI[0]=0; 170 171 strcat(szCurrentURI, "/" ); 172 173 174 // constraints 175 for ( int i = 0; i < nConst; i++ ){ 176 int nConstType = buf[nOffset++]; 177 178 const char* sz_Const[] = { 179 "", 180 "min", 181 "max", 182 "values", 183 "default", 184 "minLen", 185 "maxLen", 186 "regexp", 187 "nMaxLen", 188 "nValues", 189 "nRegexp", 190 "auto", 191 "recur-after-segment", 192 "max-recurrence", 193 "fk", 194 "child", 195 "depend", 196 "maxChild" 197 }; 198 199 if ( nOffset + 4 >= nSize ){ 200 if ( g_eMode != enum_Mode_Quiet ) 201 printf( "Item does not fit buffer completelly, offset %d, \n", nOffset); 202 203 return 6; 204 } 205 206 int nValue = 0; 207 char szStrValue[30] = ""; 208 const unsigned char* szValue = (const unsigned char*)szStrValue; 209 210 switch ( nConstType ){ 211 default: 212 if ( g_eMode != enum_Mode_Quiet ) 213 printf( "Invalid constraint type %d, offset %d, \n", nConstType, nOffset); 214 return 6; 215 case 3: case 7: case 9: case 10: case 11: case 12: case 14: case 15: case 16: 216 nValue = GetInt( buf, nOffset ); 217 218 if ( nValue >= nSize ){ 219 szValue = (const unsigned char*)"<<out of the buffer>>"; 220 nRes = 7; 221 } 222 else 223 szValue = buf + nValue; 224 break; 225 226 case 1: case 2: 227 nValue = GetInt( buf, nOffset ); 228 sprintf(szStrValue, "%d", nValue); 229 break; 230 case 5: case 6: case 8: case 13: case 17: 231 nValue = GetInt16( buf, nOffset ); 232 sprintf(szStrValue, "%d", nValue); 233 break; 234 case 4: 235 if ( (nType & 0x7f) == 3 ) {// bool 236 nValue = buf[nOffset++]; 237 sprintf(szStrValue, "%s", nValue ? "true": "false"); 238 } 239 else { 240 nValue = GetInt( buf, nOffset ); 241 242 if( (nType & 0x7f) == 2 ) // int 243 sprintf(szStrValue, "%d", nValue); 244 else { 245 if ( nValue >= nSize ){ 246 szValue = (const unsigned char*)"<<out of the buffer>>"; 247 nRes = 7; 248 } 249 else 250 szValue = buf + nValue; 251 } 252 253 } 254 255 break; 256 } 257 258 if ( g_eMode == enum_Mode_Default) 259 printf("%s constraint type %s, value %x \"%s\"\n", szIndent, sz_Const[nConstType], nValue, szValue ); 260 else if ( g_eMode == enum_Mode_MDF) 261 printf("%s:%s\n", sz_Const[nConstType], szValue ); 262 263 264 } 265 266 for ( int i = 0; i < nChildren; i++ ){ 267 int n = aChildren[i]; 268 269 int nResFromChildren = GetPrintItem( buf, n, nSize, nLevel + 1, szCurrentURI ); 270 271 if ( nResFromChildren ) 272 nRes = nResFromChildren; 273 } 274 return nRes; 275} 276 277/////////////////////////////////////////////////////////////// 278static int ProcessBuffer( FILE* f, unsigned char* buf, long nSize ) 279{ 280 if ( fread( buf, 1, nSize, f ) != nSize ) 281 return 6; 282 283 if ( g_eMode == enum_Mode_Default ) 284 printf("buffer loaded...\n"); 285 286 int nOffset = 0; 287 288 int n = GetInt( buf, nOffset ); 289 int nVer = GetInt16( buf, nOffset ); 290 291 if ( g_eMode == enum_Mode_Default ) 292 printf( "%x: fsize %x; ver %x (%s)\n", nOffset - 6, n, nVer, n == nSize ? "valid" : "invalid"); 293 294 return GetPrintItem( buf, nOffset, nSize, 0, "" ); 295} 296 297/////////////////////////////////////////////////////////////// 298static int ProcessFile( FILE* f ) 299{ 300 fseek( f, 0, SEEK_END ); 301 long nSize = ftell( f ); 302 fseek( f, 0, SEEK_SET ); 303 304 if ( nSize <= 0 ) 305 return 3; 306 307 if ( g_eMode == enum_Mode_Default ) 308 printf( "File size is %d (dec)\n", nSize ); 309 310 unsigned char* buf = new unsigned char[nSize+1]; 311 if ( !buf ) 312 return 4; 313 314 buf[nSize]=0; 315 int nRet = ProcessBuffer( f, buf, nSize ); 316 317 delete buf; 318 return nRet; 319} 320 321/////////////////////////////////////////////////////////////// 322static void Usage() 323{ 324 printf("Simple reader and verifier for binary MDF files\n" 325 "always return 0 code for valid file and non zero for corrupted file\n" 326 "usage: bmdf_reader [-q] [-mdf] <bmdf file name>\n" 327 "-q -- quiet mode, return only error code (0 valid file, not 0 - invalid file)\n" 328 "-mdf -- generate text mdf\n" 329 ); 330} 331 332/////////////////////////////////////////////////////////////// 333static const char* ParseCmdLineOptions(int argc, char** argv) 334{ 335 const char* szFileName = NULL; 336 337 for ( int i = 1; i < argc; i++ ){ 338 if ( strcasecmp( argv[i], "-q") == 0 ) 339 g_eMode = enum_Mode_Quiet; 340 else if ( strcasecmp( argv[i], "-mdf") == 0 ) 341 g_eMode = enum_Mode_MDF; 342 else { 343 szFileName = argv[i]; 344 break; 345 } 346 } 347 348 return szFileName; 349} 350 351/////////////////////////////////////////////////////////////// 352int main(int argc, char** argv) 353{ 354 const char* szFileName = ParseCmdLineOptions( argc, argv ); 355 356 if ( !szFileName ){ 357 Usage(); 358 return 1; 359 } 360 361 FILE* f = fopen( szFileName, "r" ); 362 363 if ( !f ){ 364 printf("unable to open file %s\n", szFileName ); 365 return 2; 366 } 367 368 int nRet = ProcessFile( f ); 369 fclose( f ); 370 371 if ( g_eMode == enum_Mode_Default ) 372 printf( "\ndone, file is %s\n", nRet ? "invalid" : "ok"); 373 374 return nRet; 375} 376