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