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/linked-list-private.h"
51#include "MagickCore/magic.h"
52#include "MagickCore/magic-private.h"
53#include "MagickCore/memory_.h"
54#include "MagickCore/memory-private.h"
55#include "MagickCore/semaphore.h"
56#include "MagickCore/string_.h"
57#include "MagickCore/string-private.h"
58#include "MagickCore/token.h"
59#include "MagickCore/utility.h"
60#include "MagickCore/utility-private.h"
61#include "coders/coders.h"
66#define AddMagickCoder(coder) Magick ## coder ## Headers
76 const MagickOffsetType
85 const MagickBooleanType
116 #include "coders/coders-list.h"
117 MagickCoderHeader(
"CGM", 0,
"BEGMF")
118 MagickCoderHeader("FIG", 0, "
#FIG")
119 MagickCoderHeader("HPGL", 0, "IN;")
120 MagickCoderHeader("ILBM", 8, "ILBM")
124 *magic_cache = (LinkedListInfo *) NULL,
125 *magic_list = (LinkedListInfo *) NULL;
128 *magic_cache_semaphore = (SemaphoreInfo *) NULL,
129 *magic_list_semaphore = (SemaphoreInfo *) NULL;
132 Forward declarations.
134static MagickBooleanType
135 IsMagicListInstantiated(ExceptionInfo *);
138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142% A c q u i r e M a g i c L i s t %
146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148% AcquireMagicList() caches one or more magic configurations which provides a
149% mapping between magic attributes and a magic name.
151% The format of the AcquireMagicList method is:
153% LinkedListInfo *AcquireMagicList(ExceptionInfo *exception)
155% A description of each parameter follows:
157% o filename: the font file name.
159% o exception: return any errors or warnings in this structure.
163static int CompareMagickInfoExtent(const void *a,const void *b)
174 delta=(MagickOffsetType) mb->length-(MagickOffsetType) ma->length;
175 if (ma->offset != mb->offset)
178 Offset is near the start? Let's search a bit further in the stream.
180 delta=ma->offset-mb->offset;
181 if ((ma->offset > mb->offset ? ma->offset : mb->offset) <= 10)
182 delta=mb->offset-ma->offset;
184 return(delta > INT_MAX ? 0 : (int) delta);
187static 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++)
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->name=(char *) p->name;
221 magic_info->offset=p->offset;
222 magic_info->magic=(unsigned char *) p->magic;
223 magic_info->length=p->length;
224 magic_info->skip_spaces=p->skip_spaces;
225 magic_info->signature=MagickCoreSignature;
226 status&=(MagickStatusType) InsertValueInSortedLinkedList(list,
227 CompareMagickInfoExtent,NULL,magic_info);
228 if (status == MagickFalse)
229 (void) ThrowMagickException(exception,GetMagickModule(),
230 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240% G e t M a g i c I n f o %
244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246% GetMagicInfo() searches the magic list for the specified name and if found
247% returns attributes for that magic.
249% The format of the GetMagicInfo method is:
251% const MagicInfo *GetMagicInfo(const unsigned char *magic,
252% const size_t length,ExceptionInfo *exception)
254% A description of each parameter follows:
256% o magic: A binary string generally representing the first few characters
257% of the image file or blob.
259% o length: the length of the binary signature.
261% o exception: return any errors or warnings in this structure.
265static inline MagickBooleanType CompareMagic(const unsigned char *magic,
266 const size_t length,const MagicInfo *magic_info)
274 assert(magic_info->offset >= 0);
275 q=magic+magic_info->offset;
276 remaining=(MagickOffsetType) length-magic_info->offset;
277 if (magic_info->skip_spaces != MagickFalse)
278 while ((remaining > 0) && (isspace(*q) != 0))
283 if ((remaining >= (MagickOffsetType) magic_info->length) &&
284 (memcmp(q,magic_info->magic,magic_info->length) == 0))
289static MagickBooleanType IsMagicCacheInstantiated(void)
291 if (magic_cache == (LinkedListInfo *) NULL)
293 if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
294 ActivateSemaphoreInfo(&magic_cache_semaphore);
295 LockSemaphoreInfo(magic_cache_semaphore);
296 if (magic_cache == (LinkedListInfo *) NULL)
297 magic_cache=NewLinkedList(0);
298 UnlockSemaphoreInfo(magic_cache_semaphore);
300 return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
303MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
304 const size_t length,ExceptionInfo *exception)
312 assert(exception != (ExceptionInfo *) NULL);
313 if (IsMagicListInstantiated(exception) == MagickFalse)
314 return((const MagicInfo *) NULL);
315 if (IsMagicCacheInstantiated() == MagickFalse)
316 return((const MagicInfo *) NULL);
318 Search for cached entries.
320 magic_info=(const MagicInfo *) NULL;
321 if (magic != (const unsigned char *) NULL)
323 LockSemaphoreInfo(magic_cache_semaphore);
324 p=GetHeadElementInLinkedList(magic_cache);
325 while (p != (ElementInfo *) NULL)
327 magic_info=(const MagicInfo *) p->value;
328 if (CompareMagic(magic,length,magic_info) != MagickFalse)
332 UnlockSemaphoreInfo(magic_cache_semaphore);
333 if (p != (ElementInfo *) NULL)
337 Search for magic tag.
339 LockSemaphoreInfo(magic_list_semaphore);
340 p=GetHeadElementInLinkedList(magic_list);
341 if (magic == (const unsigned char *) NULL)
343 UnlockSemaphoreInfo(magic_list_semaphore);
344 if (p != (ElementInfo *) NULL)
345 magic_info=(const MagicInfo *) p->value;
348 while (p != (ElementInfo *) NULL)
350 magic_info=(const MagicInfo *) p->value;
351 if (CompareMagic(magic,length,magic_info) != MagickFalse)
355 UnlockSemaphoreInfo(magic_list_semaphore);
356 if (p == (ElementInfo *) NULL)
357 magic_info=(const MagicInfo *) NULL;
360 LockSemaphoreInfo(magic_cache_semaphore);
361 (void) InsertValueInSortedLinkedList(magic_cache,CompareMagickInfoExtent,
363 UnlockSemaphoreInfo(magic_cache_semaphore);
369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373% G e t M a g i c P a t t e r n E x t e n t %
377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379% GetMagicPatternExtent() returns the extent of the buffer that is
380% required to check all the MagickInfos. It returns zero if the list is empty.
382% The format of the GetMagicPatternExtent method is:
384% size_t GetMagicPatternExtent(ExceptionInfo *exception)
386% A description of each parameter follows:
388% o exception: return any errors or warnings in this structure.
391MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
403 assert(exception != (ExceptionInfo *) NULL);
404 if ((extent != 0) || (IsMagicListInstantiated(exception) == MagickFalse))
406 LockSemaphoreInfo(magic_list_semaphore);
407 p=GetHeadElementInLinkedList(magic_list);
408 for (max_offset=0; p != (ElementInfo *) NULL; )
413 magic_info=(const MagicInfo *) p->value;
414 offset=magic_info->offset+(MagickOffsetType) magic_info->length;
415 if (offset > max_offset)
419 UnlockSemaphoreInfo(magic_list_semaphore);
420 if (max_offset > (MagickOffsetType) (MAGICK_SSIZE_MAX/2))
422 extent=(size_t) max_offset;
427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431% G e t M a g i c I n f o L i s t %
435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437% GetMagicInfoList() returns any image aliases that match the specified
440% The magic of the GetMagicInfoList function is:
442% const MagicInfo **GetMagicInfoList(const char *pattern,
443% size_t *number_aliases,ExceptionInfo *exception)
445% A description of each parameter follows:
447% o pattern: Specifies a pointer to a text string containing a pattern.
449% o number_aliases: This integer returns the number of aliases in the list.
451% o exception: return any errors or warnings in this structure.
455#if defined(__cplusplus) || defined(c_plusplus)
459static int MagicInfoCompare(const void *x,const void *y)
465 p=(const MagicInfo **) x,
466 q=(const MagicInfo **) y;
467 return(LocaleCompare((*p)->name,(*q)->name));
470#if defined(__cplusplus) || defined(c_plusplus)
474MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
475 size_t *number_aliases,ExceptionInfo *magick_unused(exception))
486 magick_unreferenced(exception);
487 assert(pattern != (char *) NULL);
488 assert(number_aliases != (size_t *) NULL);
489 if (IsEventLogging() != MagickFalse)
490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
492 if (IsMagicCacheInstantiated() == MagickFalse)
493 return((const MagicInfo **) NULL);
494 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
495 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
496 if (aliases == (const MagicInfo **) NULL)
497 return((const MagicInfo **) NULL);
498 LockSemaphoreInfo(magic_list_semaphore);
499 p=GetHeadElementInLinkedList(magic_list);
500 for (i=0; p != (ElementInfo *) NULL; )
505 magic_info=(const MagicInfo *) p->value;
506 if (GlobExpression(magic_info->name,pattern,MagickFalse) != MagickFalse)
507 aliases[i++]=magic_info;
510 UnlockSemaphoreInfo(magic_list_semaphore);
512 aliases=(const MagicInfo **) RelinquishMagickMemory((void*) aliases);
515 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
516 aliases[i]=(MagicInfo *) NULL;
518 *number_aliases=(size_t) i;
523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527% G e t M a g i c L i s t %
531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533% GetMagicList() returns any image format aliases that match the specified
536% The format of the GetMagicList function is:
538% char **GetMagicList(const char *pattern,size_t *number_aliases,
539% ExceptionInfo *exception)
541% A description of each parameter follows:
543% o pattern: Specifies a pointer to a text string containing a pattern.
545% o number_aliases: This integer returns the number of image format aliases
548% o exception: return any errors or warnings in this structure.
552#if defined(__cplusplus) || defined(c_plusplus)
556static int MagicCompare(const void *x,const void *y)
564 return(LocaleCompare(p,q));
567#if defined(__cplusplus) || defined(c_plusplus)
571MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
572 ExceptionInfo *magick_unused(exception))
583 magick_unreferenced(exception);
584 assert(pattern != (char *) NULL);
585 assert(number_aliases != (size_t *) NULL);
586 if (IsEventLogging() != MagickFalse)
587 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
589 if (IsMagicCacheInstantiated() == MagickFalse)
590 return((char **) NULL);
591 aliases=(char **) AcquireQuantumMemory((size_t)
592 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
593 if (aliases == (char **) NULL)
594 return((char **) NULL);
595 LockSemaphoreInfo(magic_list_semaphore);
596 p=GetHeadElementInLinkedList(magic_list);
597 for (i=0; p != (ElementInfo *) NULL; )
602 magic_info=(const MagicInfo *) p->value;
603 if (GlobExpression(magic_info->name,pattern,MagickFalse) != MagickFalse)
604 aliases[i++]=ConstantString(magic_info->name);
607 UnlockSemaphoreInfo(magic_list_semaphore);
609 aliases=(char **) RelinquishMagickMemory(aliases);
612 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
613 aliases[i]=(char *) NULL;
615 *number_aliases=(size_t) i;
620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624% G e t M a g i c N a m e %
628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630% GetMagicName() returns the name associated with the magic.
632% The format of the GetMagicName method is:
634% const char *GetMagicName(const MagicInfo *magic_info)
636% A description of each parameter follows:
638% o magic_info: The magic info.
641MagickExport const char *GetMagicName(const MagicInfo *magic_info)
643 assert(magic_info != (MagicInfo *) NULL);
644 assert(magic_info->signature == MagickCoreSignature);
645 if (IsEventLogging() != MagickFalse)
646 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
647 return(magic_info->name);
651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655+ I s M a g i c L i s t I n s t a n t i a t e d %
659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661% IsMagicListInstantiated() determines if the magic list is instantiated.
662% If not, it instantiates the list and returns it.
664% The format of the IsMagicListInstantiated method is:
666% MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
668% A description of each parameter follows.
670% o exception: return any errors or warnings in this structure.
673static MagickBooleanType IsMagicListInstantiated(ExceptionInfo *exception)
675 if (magic_list == (LinkedListInfo *) NULL)
677 if (magic_list_semaphore == (SemaphoreInfo *) NULL)
678 ActivateSemaphoreInfo(&magic_list_semaphore);
679 LockSemaphoreInfo(magic_list_semaphore);
680 if (magic_list == (LinkedListInfo *) NULL)
681 magic_list=AcquireMagicList(exception);
682 UnlockSemaphoreInfo(magic_list_semaphore);
684 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692% L i s t M a g i c I n f o %
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698% ListMagicInfo() lists the magic info to a file.
700% The format of the ListMagicInfo method is:
702% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
704% A description of each parameter follows.
706% o file: An pointer to a FILE.
708% o exception: return any errors or warnings in this structure.
711MagickExport MagickBooleanType ListMagicInfo(FILE *file,
712 ExceptionInfo *exception)
726 if (file == (const FILE *) NULL)
728 magic_info=GetMagicInfoList("*",&number_aliases,exception);
729 if (magic_info == (const MagicInfo **) NULL)
731 (void) FormatLocaleFile(file,"Name Offset Target\n");
732 (void) FormatLocaleFile(file,
733 "-------------------------------------------------"
734 "------------------------------\n");
735 for (i=0; i < (ssize_t) number_aliases; i++)
737 (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
738 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
739 (void) FormatLocaleFile(file," ");
740 (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
741 if (magic_info[i]->magic != (unsigned char *) NULL)
743 for (j=0; magic_info[i]->magic[j] != '\0'; j++)
744 if (isprint((int) (magic_info[i]->magic[j])) != 0)
745 (void) FormatLocaleFile(file,"%c",magic_info[i]->magic[j]);
747 (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
748 ((unsigned char) magic_info[i]->magic[j]));
750 (void) FormatLocaleFile(file,"\n");
753 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762+ M a g i c C o m p o n e n t G e n e s i s %
766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768% MagicComponentGenesis() instantiates the magic component.
770% The format of the MagicComponentGenesis method is:
772% MagickBooleanType MagicComponentGenesis(void)
775MagickPrivate MagickBooleanType MagicComponentGenesis(void)
777 if (magic_list_semaphore == (SemaphoreInfo *) NULL)
778 magic_list_semaphore=AcquireSemaphoreInfo();
783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787+ M a g i c C o m p o n e n t T e r m i n u s %
791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793% MagicComponentTerminus() destroys the magic component.
795% The format of the MagicComponentTerminus method is:
797% MagicComponentTerminus(void)
801static void *DestroyMagicElement(void *magic_info)
803 RelinquishMagickMemory((MagicInfo *) magic_info);
804 return((void *) NULL);
807MagickPrivate void MagicComponentTerminus(void)
809 if (magic_list_semaphore == (SemaphoreInfo *) NULL)
810 ActivateSemaphoreInfo(&magic_list_semaphore);
811 LockSemaphoreInfo(magic_list_semaphore);
812 if (magic_list != (LinkedListInfo *) NULL)
813 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
814 UnlockSemaphoreInfo(magic_list_semaphore);
815 RelinquishSemaphoreInfo(&magic_list_semaphore);
816 if (magic_cache_semaphore == (SemaphoreInfo *) NULL)
817 ActivateSemaphoreInfo(&magic_cache_semaphore);
818 LockSemaphoreInfo(magic_cache_semaphore);
819 if (magic_cache != (LinkedListInfo *) NULL)
820 magic_cache=DestroyLinkedList(magic_cache,(void *(*)(void *)) NULL);
821 UnlockSemaphoreInfo(magic_cache_semaphore);
822 RelinquishSemaphoreInfo(&magic_cache_semaphore);