2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M AAA GGGG IIIII CCCC %
8 % M M M AAAAA G GGG I C %
10 % M M A A GGGG IIIII CCCC %
13 % MagickCore Image Magic Methods %
20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % https://imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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/memory-private.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 "coders/coders.h"
65 #define AddMagickCoder(coder) Magick ## coder ## Headers
70 typedef struct _MagicMapInfo
75 const MagickOffsetType
112 static const MagicMapInfo
115 #include "coders/coders-list.h"
116 MagickCoderHeader("CGM", 0, "BEGMF")
117 MagickCoderHeader("FIG", 0, "#FIG")
118 MagickCoderHeader("HPGL", 0, "IN;")
119 MagickCoderHeader("ILBM", 8, "ILBM")
122 static LinkedListInfo
123 *magic_cache = (LinkedListInfo *) NULL,
124 *magic_list = (LinkedListInfo *) NULL;
127 *magic_cache_semaphore = (SemaphoreInfo *) NULL,
128 *magic_list_semaphore = (SemaphoreInfo *) NULL;
131 Forward declarations.
133 static MagickBooleanType
134 IsMagicListInstantiated(ExceptionInfo *);
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 % A c q u i r e M a g i c L i s t %
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 % AcquireMagicList() caches one or more magic configurations which provides a
148 % mapping between magic attributes and a magic name.
150 % The format of the AcquireMagicList method is:
152 % LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
154 % A description of each parameter follows:
156 % o filename: the font file name.
158 % o exception: return any errors or warnings in this structure.
161 static int CompareMagickInfoSize(const void *a,const void *b)
169 if (ma->offset != mb->offset)
175 When the offset is near the start we first search a bit further
178 max_offset=ma->offset > mb->offset ? ma->offset : mb->offset;
179 if (max_offset <= 10)
180 return((int) (mb->offset-ma->offset));
182 return((int) (ma->offset-mb->offset));
184 return((int) (mb->length-ma->length));
187 static LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
198 list=NewLinkedList(0);
201 Load built-in magic map.
203 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
208 register const MagicMapInfo
212 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
213 if (magic_info == (MagicInfo *) NULL)
215 (void) ThrowMagickException(exception,GetMagickModule(),
216 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
219 (void) memset(magic_info,0,sizeof(*magic_info));
220 magic_info->path=(char *) "[built-in]";
221 magic_info->name=(char *) p->name;
222 magic_info->offset=p->offset;
223 magic_info->target=(char *) p->magic;
224 magic_info->magic=(unsigned char *) p->magic;
225 magic_info->length=p->length;
226 magic_info->exempt=MagickTrue;
227 magic_info->signature=MagickCoreSignature;
228 status&=InsertValueInSortedLinkedList(list,CompareMagickInfoSize,
230 if (status == MagickFalse)
231 (void) ThrowMagickException(exception,GetMagickModule(),
232 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 % G e t M a g i c I n f o %
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 % GetMagicInfo() searches the magic list for the specified name and if found
249 % returns attributes for that magic.
251 % The format of the GetMagicInfo method is:
253 % const MagicInfo *GetMagicInfo(const unsigned char *magic,
254 % const size_t length,ExceptionInfo *exception)
256 % A description of each parameter follows:
258 % o magic: A binary string generally representing the first few characters
259 % of the image file or blob.
261 % o length: the length of the binary signature.
263 % o exception: return any errors or warnings in this structure.
266 static MagickBooleanType IsMagicCacheInstantiated()
268 if (magic_cache == (LinkedListInfo *) NULL)
270 if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
271 ActivateSemaphoreInfo(&magic_cache_semaphore);
272 LockSemaphoreInfo(magic_cache_semaphore);
273 if (magic_cache == (LinkedListInfo *) NULL)
274 magic_cache=NewLinkedList(0);
275 UnlockSemaphoreInfo(magic_cache_semaphore);
277 return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
280 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
281 const size_t length,ExceptionInfo *exception)
283 register const MagicInfo
286 assert(exception != (ExceptionInfo *) NULL);
287 if (IsMagicListInstantiated(exception) == MagickFalse)
288 return((const MagicInfo *) NULL);
289 if (IsMagicCacheInstantiated() == MagickFalse)
290 return((const MagicInfo *) NULL);
292 Search for cached entries.
294 if (magic != (const unsigned char *) NULL)
296 LockSemaphoreInfo(magic_cache_semaphore);
297 ResetLinkedListIterator(magic_cache);
298 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
299 while (p != (const MagicInfo *) NULL)
301 if (((size_t) (p->offset+p->length) <= length) &&
302 (memcmp(magic+p->offset,p->magic,p->length) == 0))
304 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
306 UnlockSemaphoreInfo(magic_cache_semaphore);
307 if (p != (const MagicInfo *) NULL)
311 Search for magic tag.
313 LockSemaphoreInfo(magic_list_semaphore);
314 ResetLinkedListIterator(magic_list);
315 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
316 if (magic == (const unsigned char *) NULL)
318 UnlockSemaphoreInfo(magic_list_semaphore);
321 while (p != (const MagicInfo *) NULL)
323 assert(p->offset >= 0);
324 if (((size_t) (p->offset+p->length) <= length) &&
325 (memcmp(magic+p->offset,p->magic,p->length) == 0))
327 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
329 UnlockSemaphoreInfo(magic_list_semaphore);
330 if (p != (const MagicInfo *) NULL)
332 LockSemaphoreInfo(magic_cache_semaphore);
333 InsertValueInSortedLinkedList(magic_cache,CompareMagickInfoSize,
335 UnlockSemaphoreInfo(magic_cache_semaphore);
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 % G e t M a g i c P a t t e r n E x t e n t %
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351 % GetMagicPatternExtent() returns the the extent of the buffer that is
352 % required to check all the MagickInfos. It returns zero if the list is empty.
354 % The format of the GetMagicPatternExtent method is:
356 % size_t GetMagicPatternExtent(ExceptionInfo *exception)
358 % A description of each parameter follows:
360 % o exception: return any errors or warnings in this structure.
363 MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
365 register const MagicInfo
375 assert(exception != (ExceptionInfo *) NULL);
376 if ((size != 0) || (IsMagicListInstantiated(exception) == MagickFalse))
378 LockSemaphoreInfo(magic_list_semaphore);
379 ResetLinkedListIterator(magic_list);
381 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
382 while (p != (const MagicInfo *) NULL)
384 magickSize=(size_t) (p->offset+p->length);
385 if (magickSize > max)
387 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
390 UnlockSemaphoreInfo(magic_list_semaphore);
395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 % G e t M a g i c I n f o L i s t %
403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 % GetMagicInfoList() returns any image aliases that match the specified
408 % The magic of the GetMagicInfoList function is:
410 % const MagicInfo **GetMagicInfoList(const char *pattern,
411 % size_t *number_aliases,ExceptionInfo *exception)
413 % A description of each parameter follows:
415 % o pattern: Specifies a pointer to a text string containing a pattern.
417 % o number_aliases: This integer returns the number of aliases in the list.
419 % o exception: return any errors or warnings in this structure.
423 #if defined(__cplusplus) || defined(c_plusplus)
427 static int MagicInfoCompare(const void *x,const void *y)
433 p=(const MagicInfo **) x,
434 q=(const MagicInfo **) y;
435 if (LocaleCompare((*p)->path,(*q)->path) == 0)
436 return(LocaleCompare((*p)->name,(*q)->name));
437 return(LocaleCompare((*p)->path,(*q)->path));
440 #if defined(__cplusplus) || defined(c_plusplus)
444 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
445 size_t *number_aliases,ExceptionInfo *exception)
450 register const MagicInfo
459 assert(pattern != (char *) NULL);
460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
461 assert(number_aliases != (size_t *) NULL);
463 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
464 if (p == (const MagicInfo *) NULL)
465 return((const MagicInfo **) NULL);
466 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
467 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
468 if (aliases == (const MagicInfo **) NULL)
469 return((const MagicInfo **) NULL);
473 LockSemaphoreInfo(magic_list_semaphore);
474 ResetLinkedListIterator(magic_list);
475 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
476 for (i=0; p != (const MagicInfo *) NULL; )
478 if ((p->stealth == MagickFalse) &&
479 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
481 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
483 UnlockSemaphoreInfo(magic_list_semaphore);
484 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
485 aliases[i]=(MagicInfo *) NULL;
486 *number_aliases=(size_t) i;
491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
495 % G e t M a g i c L i s t %
499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 % GetMagicList() returns any image format aliases that match the specified
504 % The format of the GetMagicList function is:
506 % char **GetMagicList(const char *pattern,size_t *number_aliases,
507 % ExceptionInfo *exception)
509 % A description of each parameter follows:
511 % o pattern: Specifies a pointer to a text string containing a pattern.
513 % o number_aliases: This integer returns the number of image format aliases
516 % o exception: return any errors or warnings in this structure.
520 #if defined(__cplusplus) || defined(c_plusplus)
524 static int MagicCompare(const void *x,const void *y)
532 return(LocaleCompare(p,q));
535 #if defined(__cplusplus) || defined(c_plusplus)
539 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
540 ExceptionInfo *exception)
545 register const MagicInfo
552 Allocate configure list.
554 assert(pattern != (char *) NULL);
555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
556 assert(number_aliases != (size_t *) NULL);
558 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
559 if (p == (const MagicInfo *) NULL)
560 return((char **) NULL);
561 aliases=(char **) AcquireQuantumMemory((size_t)
562 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
563 if (aliases == (char **) NULL)
564 return((char **) NULL);
565 LockSemaphoreInfo(magic_list_semaphore);
566 ResetLinkedListIterator(magic_list);
567 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
568 for (i=0; p != (const MagicInfo *) NULL; )
570 if ((p->stealth == MagickFalse) &&
571 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
572 aliases[i++]=ConstantString(p->name);
573 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
575 UnlockSemaphoreInfo(magic_list_semaphore);
576 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
577 aliases[i]=(char *) NULL;
578 *number_aliases=(size_t) i;
583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587 % G e t M a g i c N a m e %
591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593 % GetMagicName() returns the name associated with the magic.
595 % The format of the GetMagicName method is:
597 % const char *GetMagicName(const MagicInfo *magic_info)
599 % A description of each parameter follows:
601 % o magic_info: The magic info.
604 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
606 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
607 assert(magic_info != (MagicInfo *) NULL);
608 assert(magic_info->signature == MagickCoreSignature);
609 return(magic_info->name);
613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617 + I s M a g i c L i s t I n s t a n t i a t e d %
621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623 % IsMagicListInstantiated() determines if the magic list is instantiated.
624 % If not, it instantiates the list and returns it.
626 % The format of the IsMagicListInstantiated method is:
628 % MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
630 % A description of each parameter follows.
632 % o exception: return any errors or warnings in this structure.
635 static MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
637 if (magic_list == (LinkedListInfo *) NULL)
639 if (magic_list_semaphore == (SemaphoreInfo *) NULL)
640 ActivateSemaphoreInfo(&magic_list_semaphore);
641 LockSemaphoreInfo(magic_list_semaphore);
642 if (magic_list == (LinkedListInfo *) NULL)
643 magic_list=AcquireMagicList(exception);
644 UnlockSemaphoreInfo(magic_list_semaphore);
646 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 % L i s t M a g i c I n f o %
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660 % ListMagicInfo() lists the magic info to a file.
662 % The format of the ListMagicInfo method is:
664 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
666 % A description of each parameter follows.
668 % o file: An pointer to a FILE.
670 % o exception: return any errors or warnings in this structure.
673 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
674 ExceptionInfo *exception)
691 if (file == (const FILE *) NULL)
693 magic_info=GetMagicInfoList("*",&number_aliases,exception);
694 if (magic_info == (const MagicInfo **) NULL)
696 path=(const char *) NULL;
697 for (i=0; i < (ssize_t) number_aliases; i++)
699 if (magic_info[i]->stealth != MagickFalse)
701 if ((path == (const char *) NULL) ||
702 (LocaleCompare(path,magic_info[i]->path) != 0))
704 if (magic_info[i]->path != (char *) NULL)
705 (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
706 (void) FormatLocaleFile(file,"Name Offset Target\n");
707 (void) FormatLocaleFile(file,
708 "-------------------------------------------------"
709 "------------------------------\n");
711 path=magic_info[i]->path;
712 (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
713 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
714 (void) FormatLocaleFile(file," ");
715 (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
716 if (magic_info[i]->target != (char *) NULL)
718 for (j=0; magic_info[i]->target[j] != '\0'; j++)
719 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
720 (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
722 (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
723 ((unsigned char) magic_info[i]->target[j]));
725 (void) FormatLocaleFile(file,"\n");
728 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 + M a g i c C o m p o n e n t G e n e s i s %
741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
743 % MagicComponentGenesis() instantiates the magic component.
745 % The format of the MagicComponentGenesis method is:
747 % MagickBooleanType MagicComponentGenesis(void)
750 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
752 if (magic_list_semaphore == (SemaphoreInfo *) NULL)
753 magic_list_semaphore=AcquireSemaphoreInfo();
758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 + M a g i c C o m p o n e n t T e r m i n u s %
766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 % MagicComponentTerminus() destroys the magic component.
770 % The format of the MagicComponentTerminus method is:
772 % MagicComponentTerminus(void)
776 static void *DestroyMagicElement(void *magic_info)
781 p=(MagicInfo *) magic_info;
782 if (p->exempt == MagickFalse)
784 if (p->path != (char *) NULL)
785 p->path=DestroyString(p->path);
786 if (p->name != (char *) NULL)
787 p->name=DestroyString(p->name);
788 if (p->target != (char *) NULL)
789 p->target=DestroyString(p->target);
790 if (p->magic != (unsigned char *) NULL)
791 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
793 p=(MagicInfo *) RelinquishMagickMemory(p);
794 return((void *) NULL);
797 MagickPrivate void MagicComponentTerminus(void)
799 if (magic_list_semaphore == (SemaphoreInfo *) NULL)
800 ActivateSemaphoreInfo(&magic_list_semaphore);
801 LockSemaphoreInfo(magic_list_semaphore);
802 if (magic_list != (LinkedListInfo *) NULL)
803 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
804 UnlockSemaphoreInfo(magic_list_semaphore);
805 RelinquishSemaphoreInfo(&magic_list_semaphore);
806 if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
807 ActivateSemaphoreInfo(&magic_cache_semaphore);
808 LockSemaphoreInfo(magic_cache_semaphore);
809 if (magic_cache != (LinkedListInfo *) NULL)
810 magic_cache=DestroyLinkedList(magic_cache,(void *(*)(void *)) NULL);
811 UnlockSemaphoreInfo(magic_cache_semaphore);
812 RelinquishSemaphoreInfo(&magic_cache_semaphore);