1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % M M AAA GGGG IIIII CCCC % 7 % MM MM A A G I C % 8 % M M M AAAAA G GGG I C % 9 % M M A A G G I C % 10 % M M A A GGGG IIIII CCCC % 11 % % 12 % % 13 % MagickCore Image Magic Methods % 14 % % 15 % Software Design % 16 % Bob Friesenhahn % 17 % July 2000 % 18 % % 19 % % 20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % http://www.imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % 37 */ 38 39 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/blob.h" 45 #include "MagickCore/client.h" 46 #include "MagickCore/configure.h" 47 #include "MagickCore/configure-private.h" 48 #include "MagickCore/exception.h" 49 #include "MagickCore/exception-private.h" 50 #include "MagickCore/linked-list.h" 51 #include "MagickCore/magic.h" 52 #include "MagickCore/magic-private.h" 53 #include "MagickCore/memory_.h" 54 #include "MagickCore/semaphore.h" 55 #include "MagickCore/string_.h" 56 #include "MagickCore/string-private.h" 57 #include "MagickCore/token.h" 58 #include "MagickCore/utility.h" 59 #include "MagickCore/utility-private.h" 60 #include "MagickCore/xml-tree.h" 61 #include "MagickCore/xml-tree-private.h" 62 63 /* 65 Define declarations. 66 */ 67 #define MagicFilename "magic.xml" 68 #define MagicPattern(magic) (const unsigned char *) (magic), sizeof(magic)-1 69 70 /* 72 Typedef declarations. 73 */ 74 typedef struct _MagicMapInfo 75 { 76 const char 77 *name; 78 79 const MagickOffsetType 80 offset; 81 82 const unsigned char 83 *magic; 84 85 const size_t 86 length; 87 } MagicMapInfo; 88 89 /* 91 Static declarations. 92 */ 93 static const MagicMapInfo 94 MagicMap[] = 95 { 96 { "8BIMWTEXT", 0, MagicPattern("8\000B\000I\000M\000#") }, 97 { "8BIMTEXT", 0, MagicPattern("8BIM#") }, 98 { "8BIM", 0, MagicPattern("8BIM") }, 99 { "BMP", 0, MagicPattern("BA") }, 100 { "BMP", 0, MagicPattern("BM") }, 101 { "BMP", 0, MagicPattern("CI") }, 102 { "BMP", 0, MagicPattern("CP") }, 103 { "BMP", 0, MagicPattern("IC") }, 104 { "PICT", 0, MagicPattern("PICT") }, 105 { "BMP", 0, MagicPattern("PI") }, 106 { "CALS", 21, MagicPattern("version: MIL-STD-1840") }, 107 { "CALS", 0, MagicPattern("srcdocid:") }, 108 { "CALS", 9, MagicPattern("srcdocid:") }, 109 { "CALS", 8, MagicPattern("rorient:") }, 110 { "CGM", 0, MagicPattern("BEGMF") }, 111 { "CIN", 0, MagicPattern("\200\052\137\327") }, 112 { "CRW", 0, MagicPattern("II\x1a\x00\x00\x00HEAPCCDR") }, 113 { "DCM", 128, MagicPattern("DICM") }, 114 { "DCX", 0, MagicPattern("\261\150\336\72") }, 115 { "DIB", 0, MagicPattern("\050\000") }, 116 { "DDS", 0, MagicPattern("DDS ") }, 117 { "DJVU", 0, MagicPattern("AT&TFORM") }, 118 { "DOT", 0, MagicPattern("digraph") }, 119 { "DPX", 0, MagicPattern("SDPX") }, 120 { "DPX", 0, MagicPattern("XPDS") }, 121 { "EMF", 40, MagicPattern("\040\105\115\106\000\000\001\000") }, 122 { "EPT", 0, MagicPattern("\305\320\323\306") }, 123 { "EXR", 0, MagicPattern("\166\057\061\001") }, 124 { "FAX", 0, MagicPattern("DFAX") }, 125 { "FIG", 0, MagicPattern("#FIG") }, 126 { "FITS", 0, MagicPattern("IT0") }, 127 { "FITS", 0, MagicPattern("SIMPLE") }, 128 { "FLIF", 0, MagicPattern("FLIF") }, 129 { "GIF", 0, MagicPattern("GIF8") }, 130 { "GPLT", 0, MagicPattern("#!/usr/local/bin/gnuplot") }, 131 { "HDF", 1, MagicPattern("HDF") }, 132 { "HDR", 0, MagicPattern("#?RADIANCE") }, 133 { "HDR", 0, MagicPattern("#?RGBE") }, 134 { "HPGL", 0, MagicPattern("IN;") }, 135 { "HTML", 1, MagicPattern("HTML") }, 136 { "HTML", 1, MagicPattern("html") }, 137 { "ILBM", 8, MagicPattern("ILBM") }, 138 { "IPTCWTEXT", 0, MagicPattern("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") }, 139 { "IPTCTEXT", 0, MagicPattern("2#0=\042�\042") }, 140 { "IPTC", 0, MagicPattern("\034\002") }, 141 { "JNG", 0, MagicPattern("\213JNG\r\n\032\n") }, 142 { "JPEG", 0, MagicPattern("\377\330\377") }, 143 { "J2K", 0, MagicPattern("\xff\x4f\xff\x51") }, 144 { "JPC", 0, MagicPattern("\x0d\x0a\x87\x0a") }, 145 { "JP2", 0, MagicPattern("\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a") }, 146 { "MAT", 0, MagicPattern("MATLAB 5.0 MAT-file,") }, 147 { "MIFF", 0, MagicPattern("Id=ImageMagick") }, 148 { "MIFF", 0, MagicPattern("id=ImageMagick") }, 149 { "MNG", 0, MagicPattern("\212MNG\r\n\032\n") }, 150 { "MPC", 0, MagicPattern("id=MagickCache") }, 151 { "MPEG", 0, MagicPattern("\000\000\001\263") }, 152 { "MRW", 0, MagicPattern("\x00MRM") }, 153 { "ORF", 0, MagicPattern("IIRO\x08\x00\x00\x00") }, 154 { "PCD", 2048, MagicPattern("PCD_") }, 155 { "PCL", 0, MagicPattern("\033E\033") }, 156 { "PCX", 0, MagicPattern("\012\002") }, 157 { "PCX", 0, MagicPattern("\012\005") }, 158 { "PDB", 60, MagicPattern("vIMGView") }, 159 { "PDF", 0, MagicPattern("%PDF-") }, 160 { "PES", 0, MagicPattern("#PES") }, 161 { "PFA", 0, MagicPattern("%!PS-AdobeFont-1.0") }, 162 { "PFB", 6, MagicPattern("%!PS-AdobeFont-1.0") }, 163 { "PGX", 0, MagicPattern("\050\107\020\115\046") }, 164 { "PICT", 522, MagicPattern("\000\021\002\377\014\000") }, 165 { "PNG", 0, MagicPattern("\211PNG\r\n\032\n") }, 166 { "PBM", 0, MagicPattern("P1") }, 167 { "PGM", 0, MagicPattern("P2") }, 168 { "PPM", 0, MagicPattern("P3") }, 169 { "PBM", 0, MagicPattern("P4") }, 170 { "PGM", 0, MagicPattern("P5") }, 171 { "PPM", 0, MagicPattern("P6") }, 172 { "PAM", 0, MagicPattern("P7") }, 173 { "PFM", 0, MagicPattern("PF") }, 174 { "PFM", 0, MagicPattern("Pf") }, 175 { "PS", 0, MagicPattern("%!") }, 176 { "PS", 0, MagicPattern("\004%!") }, 177 { "PS", 0, MagicPattern("\305\320\323\306") }, 178 { "PSB", 0, MagicPattern("8BPB") }, 179 { "PSD", 0, MagicPattern("8BPS") }, 180 { "PWP", 0, MagicPattern("SFW95") }, 181 { "RAF", 0, MagicPattern("FUJIFILMCCD-RAW ") }, 182 { "RLE", 0, MagicPattern("\122\314") }, 183 { "SCT", 0, MagicPattern("CT") }, 184 { "SFW", 0, MagicPattern("SFW94") }, 185 { "SGI", 0, MagicPattern("\001\332") }, 186 { "SUN", 0, MagicPattern("\131\246\152\225") }, 187 { "SVG", 1, MagicPattern("?XML") }, 188 { "SVG", 1, MagicPattern("?xml") }, 189 { "TIFF", 0, MagicPattern("\115\115\000\052") }, 190 { "TIFF", 0, MagicPattern("\111\111\052\000") }, 191 { "TIFF64", 0, MagicPattern("\115\115\000\053\000\010\000\000") }, 192 { "TIFF64", 0, MagicPattern("\111\111\053\000\010\000\000\000") }, 193 { "TTF", 0, MagicPattern("\000\001\000\000\000") }, 194 { "TXT", 0, MagicPattern("# ImageMagick pixel enumeration:") }, 195 { "VICAR", 0, MagicPattern("LBLSIZE") }, 196 { "VICAR", 0, MagicPattern("NJPL1I") }, 197 { "VIFF", 0, MagicPattern("\253\001") }, 198 { "WEBP", 8, MagicPattern("WEBP") }, 199 { "WMF", 0, MagicPattern("\327\315\306\232") }, 200 { "WMF", 0, MagicPattern("\001\000\011\000") }, 201 { "WPG", 0, MagicPattern("\377WPC") }, 202 { "XBM", 0, MagicPattern("#define") }, 203 { "XCF", 0, MagicPattern("gimp xcf") }, 204 { "XEF", 0, MagicPattern("FOVb") }, 205 { "XPM", 1, MagicPattern("* XPM *") }, 206 { "XWD", 4, MagicPattern("\007\000\000") }, 207 { "XWD", 5, MagicPattern("\000\000\007") } 208 }; 209 210 static LinkedListInfo 211 *magic_cache = (LinkedListInfo *) NULL; 212 213 static SemaphoreInfo 214 *magic_semaphore = (SemaphoreInfo *) NULL; 215 216 /* 218 Forward declarations. 219 */ 220 static MagickBooleanType 221 IsMagicCacheInstantiated(ExceptionInfo *), 222 LoadMagicCache(LinkedListInfo *,const char *,const char *,const size_t, 223 ExceptionInfo *); 224 225 /* 227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 228 % % 229 % % 230 % % 231 % A c q u i r e M a g i c L i s t s % 232 % % 233 % % 234 % % 235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 236 % 237 % AcquireMagicCache() caches one or more magic configurations which provides a 238 % mapping between magic attributes and a magic name. 239 % 240 % The format of the AcquireMagicCache method is: 241 % 242 % LinkedListInfo *AcquireMagicCache(const char *filename, 243 % ExceptionInfo *exception) 244 % 245 % A description of each parameter follows: 246 % 247 % o filename: the font file name. 248 % 249 % o exception: return any errors or warnings in this structure. 250 % 251 */ 252 static int CompareMagickInfoSize(const void *a,const void *b) 253 { 254 MagicInfo 255 *ma, 256 *mb; 257 258 ma=(MagicInfo *) a; 259 mb=(MagicInfo *) b; 260 261 if (ma->offset != mb->offset) 262 return((int) (ma->offset-mb->offset)); 263 264 return((int) (mb->length-ma->length)); 265 } 266 267 static LinkedListInfo *AcquireMagicCache(const char *filename, 268 ExceptionInfo *exception) 269 { 270 LinkedListInfo 271 *cache; 272 273 MagickStatusType 274 status; 275 276 register ssize_t 277 i; 278 279 /* 280 Load external magic map. 281 */ 282 cache=NewLinkedList(0); 283 if (cache == (LinkedListInfo *) NULL) 284 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 285 status=MagickTrue; 286 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT) 287 { 288 char 289 path[MagickPathExtent]; 290 291 const StringInfo 292 *option; 293 294 LinkedListInfo 295 *options; 296 297 *path='\0'; 298 options=GetConfigureOptions(filename,exception); 299 option=(const StringInfo *) GetNextValueInLinkedList(options); 300 while (option != (const StringInfo *) NULL) 301 { 302 (void) CopyMagickString(path,GetStringInfoPath(option),MagickPathExtent); 303 status&=LoadMagicCache(cache,(const char *) 304 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception); 305 option=(const StringInfo *) GetNextValueInLinkedList(options); 306 } 307 options=DestroyConfigureOptions(options); 308 } 309 #endif 310 /* 311 Load built-in magic map. 312 */ 313 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++) 314 { 315 MagicInfo 316 *magic_info; 317 318 register const MagicMapInfo 319 *p; 320 321 p=MagicMap+i; 322 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info)); 323 if (magic_info == (MagicInfo *) NULL) 324 { 325 (void) ThrowMagickException(exception,GetMagickModule(), 326 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name); 327 continue; 328 } 329 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info)); 330 magic_info->path=(char *) "[built-in]"; 331 magic_info->name=(char *) p->name; 332 magic_info->offset=p->offset; 333 magic_info->target=(char *) p->magic; 334 magic_info->magic=(unsigned char *) p->magic; 335 magic_info->length=p->length; 336 magic_info->exempt=MagickTrue; 337 magic_info->signature=MagickCoreSignature; 338 status&=InsertValueInSortedLinkedList(cache,CompareMagickInfoSize, 339 NULL,magic_info); 340 if (status == MagickFalse) 341 (void) ThrowMagickException(exception,GetMagickModule(), 342 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name); 343 } 344 return(cache); 345 } 346 347 /* 349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 350 % % 351 % % 352 % % 353 % G e t M a g i c I n f o % 354 % % 355 % % 356 % % 357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 358 % 359 % GetMagicInfo() searches the magic list for the specified name and if found 360 % returns attributes for that magic. 361 % 362 % The format of the GetMagicInfo method is: 363 % 364 % const MagicInfo *GetMagicInfo(const unsigned char *magic, 365 % const size_t length,ExceptionInfo *exception) 366 % 367 % A description of each parameter follows: 368 % 369 % o magic: A binary string generally representing the first few characters 370 % of the image file or blob. 371 % 372 % o length: the length of the binary signature. 373 % 374 % o exception: return any errors or warnings in this structure. 375 % 376 */ 377 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic, 378 const size_t length,ExceptionInfo *exception) 379 { 380 register const MagicInfo 381 *p; 382 383 assert(exception != (ExceptionInfo *) NULL); 384 if (IsMagicCacheInstantiated(exception) == MagickFalse) 385 return((const MagicInfo *) NULL); 386 /* 387 Search for magic tag. 388 */ 389 LockSemaphoreInfo(magic_semaphore); 390 ResetLinkedListIterator(magic_cache); 391 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 392 if (magic == (const unsigned char *) NULL) 393 { 394 UnlockSemaphoreInfo(magic_semaphore); 395 return(p); 396 } 397 while (p != (const MagicInfo *) NULL) 398 { 399 assert(p->offset >= 0); 400 if (((size_t) (p->offset+p->length) <= length) && 401 (memcmp(magic+p->offset,p->magic,p->length) == 0)) 402 break; 403 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 404 } 405 if (p != (const MagicInfo *) NULL) 406 (void) InsertValueInLinkedList(magic_cache,0, 407 RemoveElementByValueFromLinkedList(magic_cache,p)); 408 UnlockSemaphoreInfo(magic_semaphore); 409 return(p); 410 } 411 412 /* 413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 414 % % 415 % % 416 % % 417 % G e t M a g i c P a t t e r n E x t e n t % 418 % % 419 % % 420 % % 421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 422 % 423 % GetMagicPatternExtent() returns the the extent of the buffer that is 424 % required to check all the MagickInfos. It returns zero if the list is empty. 425 % 426 % The format of the GetMagicPatternExtent method is: 427 % 428 % size_t GetMagicPatternExtent(ExceptionInfo *exception) 429 % 430 % A description of each parameter follows: 431 % 432 % o exception: return any errors or warnings in this structure. 433 % 434 */ 435 MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception) 436 { 437 register const MagicInfo 438 *p; 439 440 size_t 441 magickSize, 442 max; 443 444 static size_t 445 size=0; 446 447 assert(exception != (ExceptionInfo *) NULL); 448 if ((size != 0) || (IsMagicCacheInstantiated(exception) == MagickFalse)) 449 return(size); 450 LockSemaphoreInfo(magic_semaphore); 451 ResetLinkedListIterator(magic_cache); 452 max=0; 453 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 454 while (p != (const MagicInfo *) NULL) 455 { 456 magickSize=(size_t) (p->offset+p->length); 457 if (magickSize > max) 458 max=magickSize; 459 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 460 } 461 size=max; 462 UnlockSemaphoreInfo(magic_semaphore); 463 return(size); 464 } 465 466 /* 468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 469 % % 470 % % 471 % % 472 % G e t M a g i c I n f o L i s t % 473 % % 474 % % 475 % % 476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 477 % 478 % GetMagicInfoList() returns any image aliases that match the specified 479 % pattern. 480 % 481 % The magic of the GetMagicInfoList function is: 482 % 483 % const MagicInfo **GetMagicInfoList(const char *pattern, 484 % size_t *number_aliases,ExceptionInfo *exception) 485 % 486 % A description of each parameter follows: 487 % 488 % o pattern: Specifies a pointer to a text string containing a pattern. 489 % 490 % o number_aliases: This integer returns the number of aliases in the list. 491 % 492 % o exception: return any errors or warnings in this structure. 493 % 494 */ 495 496 #if defined(__cplusplus) || defined(c_plusplus) 497 extern "C" { 498 #endif 499 500 static int MagicInfoCompare(const void *x,const void *y) 501 { 502 const MagicInfo 503 **p, 504 **q; 505 506 p=(const MagicInfo **) x, 507 q=(const MagicInfo **) y; 508 if (LocaleCompare((*p)->path,(*q)->path) == 0) 509 return(LocaleCompare((*p)->name,(*q)->name)); 510 return(LocaleCompare((*p)->path,(*q)->path)); 511 } 512 513 #if defined(__cplusplus) || defined(c_plusplus) 514 } 515 #endif 516 517 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern, 518 size_t *number_aliases,ExceptionInfo *exception) 519 { 520 const MagicInfo 521 **aliases; 522 523 register const MagicInfo 524 *p; 525 526 register ssize_t 527 i; 528 529 /* 530 Allocate magic list. 531 */ 532 assert(pattern != (char *) NULL); 533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 534 assert(number_aliases != (size_t *) NULL); 535 *number_aliases=0; 536 p=GetMagicInfo((const unsigned char *) NULL,0,exception); 537 if (p == (const MagicInfo *) NULL) 538 return((const MagicInfo **) NULL); 539 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t) 540 GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases)); 541 if (aliases == (const MagicInfo **) NULL) 542 return((const MagicInfo **) NULL); 543 /* 544 Generate magic list. 545 */ 546 LockSemaphoreInfo(magic_semaphore); 547 ResetLinkedListIterator(magic_cache); 548 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 549 for (i=0; p != (const MagicInfo *) NULL; ) 550 { 551 if ((p->stealth == MagickFalse) && 552 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)) 553 aliases[i++]=p; 554 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 555 } 556 UnlockSemaphoreInfo(magic_semaphore); 557 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare); 558 aliases[i]=(MagicInfo *) NULL; 559 *number_aliases=(size_t) i; 560 return(aliases); 561 } 562 563 /* 565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 566 % % 567 % % 568 % % 569 % G e t M a g i c L i s t % 570 % % 571 % % 572 % % 573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 574 % 575 % GetMagicList() returns any image format aliases that match the specified 576 % pattern. 577 % 578 % The format of the GetMagicList function is: 579 % 580 % char **GetMagicList(const char *pattern,size_t *number_aliases, 581 % ExceptionInfo *exception) 582 % 583 % A description of each parameter follows: 584 % 585 % o pattern: Specifies a pointer to a text string containing a pattern. 586 % 587 % o number_aliases: This integer returns the number of image format aliases 588 % in the list. 589 % 590 % o exception: return any errors or warnings in this structure. 591 % 592 */ 593 594 #if defined(__cplusplus) || defined(c_plusplus) 595 extern "C" { 596 #endif 597 598 static int MagicCompare(const void *x,const void *y) 599 { 600 register const char 601 *p, 602 *q; 603 604 p=(const char *) x; 605 q=(const char *) y; 606 return(LocaleCompare(p,q)); 607 } 608 609 #if defined(__cplusplus) || defined(c_plusplus) 610 } 611 #endif 612 613 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases, 614 ExceptionInfo *exception) 615 { 616 char 617 **aliases; 618 619 register const MagicInfo 620 *p; 621 622 register ssize_t 623 i; 624 625 /* 626 Allocate configure list. 627 */ 628 assert(pattern != (char *) NULL); 629 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 630 assert(number_aliases != (size_t *) NULL); 631 *number_aliases=0; 632 p=GetMagicInfo((const unsigned char *) NULL,0,exception); 633 if (p == (const MagicInfo *) NULL) 634 return((char **) NULL); 635 aliases=(char **) AcquireQuantumMemory((size_t) 636 GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases)); 637 if (aliases == (char **) NULL) 638 return((char **) NULL); 639 LockSemaphoreInfo(magic_semaphore); 640 ResetLinkedListIterator(magic_cache); 641 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 642 for (i=0; p != (const MagicInfo *) NULL; ) 643 { 644 if ((p->stealth == MagickFalse) && 645 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)) 646 aliases[i++]=ConstantString(p->name); 647 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache); 648 } 649 UnlockSemaphoreInfo(magic_semaphore); 650 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare); 651 aliases[i]=(char *) NULL; 652 *number_aliases=(size_t) i; 653 return(aliases); 654 } 655 656 /* 658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 659 % % 660 % % 661 % % 662 % G e t M a g i c N a m e % 663 % % 664 % % 665 % % 666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 667 % 668 % GetMagicName() returns the name associated with the magic. 669 % 670 % The format of the GetMagicName method is: 671 % 672 % const char *GetMagicName(const MagicInfo *magic_info) 673 % 674 % A description of each parameter follows: 675 % 676 % o magic_info: The magic info. 677 % 678 */ 679 MagickExport const char *GetMagicName(const MagicInfo *magic_info) 680 { 681 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 682 assert(magic_info != (MagicInfo *) NULL); 683 assert(magic_info->signature == MagickCoreSignature); 684 return(magic_info->name); 685 } 686 687 /* 689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 690 % % 691 % % 692 % % 693 + I s M a g i c C a c h e I n s t a n t i a t e d % 694 % % 695 % % 696 % % 697 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 698 % 699 % IsMagicCacheInstantiated() determines if the magic list is instantiated. 700 % If not, it instantiates the list and returns it. 701 % 702 % The format of the IsMagicInstantiated method is: 703 % 704 % MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception) 705 % 706 % A description of each parameter follows. 707 % 708 % o exception: return any errors or warnings in this structure. 709 % 710 */ 711 static MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception) 712 { 713 if (magic_cache == (LinkedListInfo *) NULL) 714 { 715 if (magic_semaphore == (SemaphoreInfo *) NULL) 716 ActivateSemaphoreInfo(&magic_semaphore); 717 LockSemaphoreInfo(magic_semaphore); 718 if (magic_cache == (LinkedListInfo *) NULL) 719 magic_cache=AcquireMagicCache(MagicFilename,exception); 720 UnlockSemaphoreInfo(magic_semaphore); 721 } 722 return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse); 723 } 724 725 /* 727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 728 % % 729 % % 730 % % 731 % L i s t M a g i c I n f o % 732 % % 733 % % 734 % % 735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 736 % 737 % ListMagicInfo() lists the magic info to a file. 738 % 739 % The format of the ListMagicInfo method is: 740 % 741 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception) 742 % 743 % A description of each parameter follows. 744 % 745 % o file: An pointer to a FILE. 746 % 747 % o exception: return any errors or warnings in this structure. 748 % 749 */ 750 MagickExport MagickBooleanType ListMagicInfo(FILE *file, 751 ExceptionInfo *exception) 752 { 753 const char 754 *path; 755 756 const MagicInfo 757 **magic_info; 758 759 register ssize_t 760 i; 761 762 size_t 763 number_aliases; 764 765 ssize_t 766 j; 767 768 if (file == (const FILE *) NULL) 769 file=stdout; 770 magic_info=GetMagicInfoList("*",&number_aliases,exception); 771 if (magic_info == (const MagicInfo **) NULL) 772 return(MagickFalse); 773 j=0; 774 path=(const char *) NULL; 775 for (i=0; i < (ssize_t) number_aliases; i++) 776 { 777 if (magic_info[i]->stealth != MagickFalse) 778 continue; 779 if ((path == (const char *) NULL) || 780 (LocaleCompare(path,magic_info[i]->path) != 0)) 781 { 782 if (magic_info[i]->path != (char *) NULL) 783 (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path); 784 (void) FormatLocaleFile(file,"Name Offset Target\n"); 785 (void) FormatLocaleFile(file, 786 "-------------------------------------------------" 787 "------------------------------\n"); 788 } 789 path=magic_info[i]->path; 790 (void) FormatLocaleFile(file,"%s",magic_info[i]->name); 791 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++) 792 (void) FormatLocaleFile(file," "); 793 (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset); 794 if (magic_info[i]->target != (char *) NULL) 795 { 796 register ssize_t 797 j; 798 799 for (j=0; magic_info[i]->target[j] != '\0'; j++) 800 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0) 801 (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]); 802 else 803 (void) FormatLocaleFile(file,"\\%03o",(unsigned int) 804 ((unsigned char) magic_info[i]->target[j])); 805 } 806 (void) FormatLocaleFile(file,"\n"); 807 } 808 (void) fflush(file); 809 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info); 810 return(MagickTrue); 811 } 812 813 /* 815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 816 % % 817 % % 818 % % 819 + L o a d M a g i c C a c h e % 820 % % 821 % % 822 % % 823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 824 % 825 % LoadMagicCache() loads the magic configurations which provides a mapping 826 % between magic attributes and a magic name. 827 % 828 % The format of the LoadMagicCache method is: 829 % 830 % MagickBooleanType LoadMagicCache(LinkedListInfo *cache,const char *xml, 831 % const char *filename,const size_t depth,ExceptionInfo *exception) 832 % 833 % A description of each parameter follows: 834 % 835 % o xml: The magic list in XML format. 836 % 837 % o filename: The magic list filename. 838 % 839 % o depth: depth of <include /> statements. 840 % 841 % o exception: return any errors or warnings in this structure. 842 % 843 */ 844 static MagickBooleanType LoadMagicCache(LinkedListInfo *cache,const char *xml, 845 const char *filename,const size_t depth,ExceptionInfo *exception) 846 { 847 char 848 keyword[MagickPathExtent], 849 *token; 850 851 const char 852 *q; 853 854 MagicInfo 855 *magic_info; 856 857 MagickStatusType 858 status; 859 860 size_t 861 extent; 862 863 /* 864 Load the magic map file. 865 */ 866 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), 867 "Loading magic configure file \"%s\" ...",filename); 868 if (xml == (char *) NULL) 869 return(MagickFalse); 870 status=MagickTrue; 871 magic_info=(MagicInfo *) NULL; 872 token=AcquireString(xml); 873 extent=strlen(token)+MagickPathExtent; 874 for (q=(char *) xml; *q != '\0'; ) 875 { 876 /* 877 Interpret XML. 878 */ 879 GetNextToken(q,&q,extent,token); 880 if (*token == '\0') 881 break; 882 (void) CopyMagickString(keyword,token,MagickPathExtent); 883 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0) 884 { 885 /* 886 Doctype element. 887 */ 888 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0')) 889 GetNextToken(q,&q,extent,token); 890 continue; 891 } 892 if (LocaleNCompare(keyword,"<!--",4) == 0) 893 { 894 /* 895 Comment element. 896 */ 897 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0')) 898 GetNextToken(q,&q,extent,token); 899 continue; 900 } 901 if (LocaleCompare(keyword,"<include") == 0) 902 { 903 /* 904 Include element. 905 */ 906 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0')) 907 { 908 (void) CopyMagickString(keyword,token,MagickPathExtent); 909 GetNextToken(q,&q,extent,token); 910 if (*token != '=') 911 continue; 912 GetNextToken(q,&q,extent,token); 913 if (LocaleCompare(keyword,"file") == 0) 914 { 915 if (depth > 200) 916 (void) ThrowMagickException(exception,GetMagickModule(), 917 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token); 918 else 919 { 920 char 921 path[MagickPathExtent], 922 *file_xml; 923 924 GetPathComponent(filename,HeadPath,path); 925 if (*path != '\0') 926 (void) ConcatenateMagickString(path,DirectorySeparator, 927 MagickPathExtent); 928 if (*token == *DirectorySeparator) 929 (void) CopyMagickString(path,token,MagickPathExtent); 930 else 931 (void) ConcatenateMagickString(path,token,MagickPathExtent); 932 file_xml=FileToXML(path,~0UL); 933 if (xml != (char *) NULL) 934 { 935 status&=LoadMagicCache(cache,file_xml,path,depth+1, 936 exception); 937 file_xml=DestroyString(file_xml); 938 } 939 } 940 } 941 } 942 continue; 943 } 944 if (LocaleCompare(keyword,"<magic") == 0) 945 { 946 /* 947 Magic element. 948 */ 949 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info)); 950 if (magic_info == (MagicInfo *) NULL) 951 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 952 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info)); 953 magic_info->path=ConstantString(filename); 954 magic_info->exempt=MagickFalse; 955 magic_info->signature=MagickCoreSignature; 956 continue; 957 } 958 if (magic_info == (MagicInfo *) NULL) 959 continue; 960 if (LocaleCompare(keyword,"/>") == 0) 961 { 962 status=InsertValueInSortedLinkedList(cache,CompareMagickInfoSize, 963 NULL,magic_info); 964 if (status == MagickFalse) 965 (void) ThrowMagickException(exception,GetMagickModule(), 966 ResourceLimitError,"MemoryAllocationFailed","`%s'", 967 magic_info->name); 968 magic_info=(MagicInfo *) NULL; 969 continue; 970 } 971 GetNextToken(q,(const char **) NULL,extent,token); 972 if (*token != '=') 973 continue; 974 GetNextToken(q,&q,extent,token); 975 GetNextToken(q,&q,extent,token); 976 switch (*keyword) 977 { 978 case 'N': 979 case 'n': 980 { 981 if (LocaleCompare((char *) keyword,"name") == 0) 982 { 983 magic_info->name=ConstantString(token); 984 break; 985 } 986 break; 987 } 988 case 'O': 989 case 'o': 990 { 991 if (LocaleCompare((char *) keyword,"offset") == 0) 992 { 993 magic_info->offset=(MagickOffsetType) StringToLong(token); 994 break; 995 } 996 break; 997 } 998 case 'S': 999 case 's': 1000 { 1001 if (LocaleCompare((char *) keyword,"stealth") == 0) 1002 { 1003 magic_info->stealth=IsStringTrue(token); 1004 break; 1005 } 1006 break; 1007 } 1008 case 'T': 1009 case 't': 1010 { 1011 if (LocaleCompare((char *) keyword,"target") == 0) 1012 { 1013 char 1014 *p; 1015 1016 register unsigned char 1017 *q; 1018 1019 size_t 1020 length; 1021 1022 length=strlen(token); 1023 magic_info->target=ConstantString(token); 1024 magic_info->magic=(unsigned char *) ConstantString(token); 1025 q=magic_info->magic; 1026 for (p=magic_info->target; *p != '\0'; ) 1027 { 1028 if (*p == '\\') 1029 { 1030 p++; 1031 if (isdigit((int) ((unsigned char) *p)) != 0) 1032 { 1033 char 1034 *end; 1035 1036 *q++=(unsigned char) strtol(p,&end,8); 1037 p+=(end-p); 1038 magic_info->length++; 1039 continue; 1040 } 1041 switch (*p) 1042 { 1043 case 'b': *q='\b'; break; 1044 case 'f': *q='\f'; break; 1045 case 'n': *q='\n'; break; 1046 case 'r': *q='\r'; break; 1047 case 't': *q='\t'; break; 1048 case 'v': *q='\v'; break; 1049 case 'a': *q='a'; break; 1050 case '?': *q='\?'; break; 1051 default: *q=(unsigned char) (*p); break; 1052 } 1053 p++; 1054 q++; 1055 magic_info->length++; 1056 continue; 1057 } 1058 else 1059 if (LocaleNCompare(p,"&",5) == 0) 1060 (void) CopyMagickString(p+1,p+5,length-magic_info->length); 1061 *q++=(unsigned char) (*p++); 1062 magic_info->length++; 1063 } 1064 break; 1065 } 1066 break; 1067 } 1068 default: 1069 break; 1070 } 1071 } 1072 token=(char *) RelinquishMagickMemory(token); 1073 return(status != 0 ? MagickTrue : MagickFalse); 1074 } 1075 1076 /* 1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1079 % % 1080 % % 1081 % % 1082 + M a g i c C o m p o n e n t G e n e s i s % 1083 % % 1084 % % 1085 % % 1086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1087 % 1088 % MagicComponentGenesis() instantiates the magic component. 1089 % 1090 % The format of the MagicComponentGenesis method is: 1091 % 1092 % MagickBooleanType MagicComponentGenesis(void) 1093 % 1094 */ 1095 MagickPrivate MagickBooleanType MagicComponentGenesis(void) 1096 { 1097 if (magic_semaphore == (SemaphoreInfo *) NULL) 1098 magic_semaphore=AcquireSemaphoreInfo(); 1099 return(MagickTrue); 1100 } 1101 1102 /* 1104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1105 % % 1106 % % 1107 % % 1108 + M a g i c C o m p o n e n t T e r m i n u s % 1109 % % 1110 % % 1111 % % 1112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1113 % 1114 % MagicComponentTerminus() destroys the magic component. 1115 % 1116 % The format of the MagicComponentTerminus method is: 1117 % 1118 % MagicComponentTerminus(void) 1119 % 1120 */ 1121 1122 static void *DestroyMagicElement(void *magic_info) 1123 { 1124 register MagicInfo 1125 *p; 1126 1127 p=(MagicInfo *) magic_info; 1128 if (p->exempt == MagickFalse) 1129 { 1130 if (p->path != (char *) NULL) 1131 p->path=DestroyString(p->path); 1132 if (p->name != (char *) NULL) 1133 p->name=DestroyString(p->name); 1134 if (p->target != (char *) NULL) 1135 p->target=DestroyString(p->target); 1136 if (p->magic != (unsigned char *) NULL) 1137 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic); 1138 } 1139 p=(MagicInfo *) RelinquishMagickMemory(p); 1140 return((void *) NULL); 1141 } 1142 1143 MagickPrivate void MagicComponentTerminus(void) 1144 { 1145 if (magic_semaphore == (SemaphoreInfo *) NULL) 1146 ActivateSemaphoreInfo(&magic_semaphore); 1147 LockSemaphoreInfo(magic_semaphore); 1148 if (magic_cache != (LinkedListInfo *) NULL) 1149 magic_cache=DestroyLinkedList(magic_cache,DestroyMagicElement); 1150 UnlockSemaphoreInfo(magic_semaphore); 1151 RelinquishSemaphoreInfo(&magic_semaphore); 1152 } 1153