|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % M M IIIII M M EEEEE % 00006 % MM MM I MM MM E % 00007 % M M M I M M M EEE % 00008 % M M I M M E % 00009 % M M IIIII M M EEEEE % 00010 % % 00011 % % 00012 % MagickCore Mime Methods % 00013 % % 00014 % Software Design % 00015 % July 2000 % 00016 % % 00017 % % 00018 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00019 % dedicated to making software imaging solutions freely available. % 00020 % % 00021 % You may not use this file except in compliance with the License. You may % 00022 % obtain a copy of the License at % 00023 % % 00024 % http://www.imagemagick.org/MagicksToolkit/script/license.php % 00025 % % 00026 % Unless required by applicable law or agreed to in writing, software % 00027 % distributed under the License is distributed on an "AS IS" BASIS, % 00028 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00029 % See the License for the specific language governing permissions and % 00030 % limitations under the License. % 00031 % % 00032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00033 % 00034 % 00035 */ 00036 00037 /* 00038 Include declarations. 00039 */ 00040 #include "MagickCore/studio.h" 00041 #include "MagickCore/blob.h" 00042 #include "MagickCore/client.h" 00043 #include "MagickCore/configure.h" 00044 #include "MagickCore/configure-private.h" 00045 #include "MagickCore/exception.h" 00046 #include "MagickCore/exception-private.h" 00047 #include "MagickCore/hashmap.h" 00048 #include "MagickCore/memory_.h" 00049 #include "MagickCore/mime.h" 00050 #include "MagickCore/mime-private.h" 00051 #include "MagickCore/option.h" 00052 #include "MagickCore/semaphore.h" 00053 #include "MagickCore/string_.h" 00054 #include "MagickCore/token.h" 00055 #include "MagickCore/utility.h" 00056 #include "MagickCore/utility-private.h" 00057 #include "MagickCore/xml-tree.h" 00058 #include "MagickCore/xml-tree-private.h" 00059 00060 /* 00061 Define declarations. 00062 */ 00063 #define MimeFilename "mime.xml" 00064 00065 /* 00066 Typedef declaration. 00067 */ 00068 struct _MimeInfo 00069 { 00070 char 00071 *path, 00072 *type, 00073 *description, 00074 *pattern; 00075 00076 ssize_t 00077 priority; 00078 00079 MagickOffsetType 00080 offset; 00081 00082 size_t 00083 extent; 00084 00085 DataType 00086 data_type; 00087 00088 ssize_t 00089 mask, 00090 value; 00091 00092 EndianType 00093 endian; 00094 00095 size_t 00096 length; 00097 00098 unsigned char 00099 *magic; 00100 00101 MagickBooleanType 00102 stealth; 00103 00104 size_t 00105 signature; 00106 }; 00107 00108 /* 00109 Static declarations. 00110 */ 00111 static const char 00112 *MimeMap = (char *) 00113 "<?xml version=\"1.0\"?>" 00114 "<mimemap>" 00115 "</mimemap>"; 00116 00117 static LinkedListInfo 00118 *mime_list = (LinkedListInfo *) NULL; 00119 00120 static SemaphoreInfo 00121 *mime_semaphore = (SemaphoreInfo *) NULL; 00122 00123 static volatile MagickBooleanType 00124 instantiate_mime = MagickFalse; 00125 00126 /* 00127 Forward declarations. 00128 */ 00129 static MagickBooleanType 00130 InitializeMimeList(ExceptionInfo *); 00131 00132 /* 00133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00134 % % 00135 % % 00136 % % 00137 + G e t M i m e I n f o % 00138 % % 00139 % % 00140 % % 00141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00142 % 00143 % GetMimeInfo() attempts to classify the content to identify which mime type 00144 % is associated with the content, if any. 00145 % 00146 % The format of the GetMimeInfo method is: 00147 % 00148 % const MimeInfo *GetMimeInfo(const char *filename, 00149 % const unsigned char *magic,const size_t length, 00150 % ExceptionInfo *exception) 00151 % 00152 % A description of each parameter follows: 00153 % 00154 % o filename: If we cannot not classify the string, we attempt to classify 00155 % based on the filename (e.g. *.pdf returns application/pdf). 00156 % 00157 % o magic: A binary string generally representing the first few characters 00158 % of the image file or blob. 00159 % 00160 % o length: the length of the binary signature. 00161 % 00162 % o exception: return any errors or warnings in this structure. 00163 % 00164 */ 00165 MagickExport const MimeInfo *GetMimeInfo(const char *filename, 00166 const unsigned char *magic,const size_t length,ExceptionInfo *exception) 00167 { 00168 const MimeInfo 00169 *mime_info; 00170 00171 EndianType 00172 endian; 00173 00174 register const MimeInfo 00175 *p; 00176 00177 register const unsigned char 00178 *q; 00179 00180 register ssize_t 00181 i; 00182 00183 size_t 00184 lsb_first; 00185 00186 ssize_t 00187 value; 00188 00189 assert(exception != (ExceptionInfo *) NULL); 00190 if ((mime_list == (LinkedListInfo *) NULL) || 00191 (instantiate_mime == MagickFalse)) 00192 if (InitializeMimeList(exception) == MagickFalse) 00193 return((const MimeInfo *) NULL); 00194 if ((mime_list == (LinkedListInfo *) NULL) || 00195 (IsLinkedListEmpty(mime_list) != MagickFalse)) 00196 return((const MimeInfo *) NULL); 00197 if ((magic == (const unsigned char *) NULL) || (length == 0)) 00198 return((const MimeInfo *) GetValueFromLinkedList(mime_list,0)); 00199 if (length == 0) 00200 return((const MimeInfo *) NULL); 00201 /* 00202 Search for mime tag. 00203 */ 00204 mime_info=(const MimeInfo *) NULL; 00205 lsb_first=1; 00206 LockSemaphoreInfo(mime_semaphore); 00207 ResetLinkedListIterator(mime_list); 00208 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00209 while (p != (const MimeInfo *) NULL) 00210 { 00211 assert(p->offset >= 0); 00212 if (mime_info != (const MimeInfo *) NULL) 00213 if (p->priority > mime_info->priority) 00214 { 00215 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00216 continue; 00217 } 00218 if ((p->pattern != (char *) NULL) && (filename != (char *) NULL)) 00219 { 00220 if (GlobExpression(filename,p->pattern,MagickFalse) != MagickFalse) 00221 mime_info=p; 00222 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00223 continue; 00224 } 00225 switch (p->data_type) 00226 { 00227 case ByteData: 00228 { 00229 if ((size_t) (p->offset+4) > length) 00230 break; 00231 q=magic+p->offset; 00232 value=(ssize_t) (*q++); 00233 if (p->mask == 0) 00234 { 00235 if (p->value == value) 00236 mime_info=p; 00237 } 00238 else 00239 { 00240 if ((p->value & p->mask) == value) 00241 mime_info=p; 00242 } 00243 break; 00244 } 00245 case ShortData: 00246 { 00247 if ((size_t) (p->offset+4) > length) 00248 break; 00249 q=magic+p->offset; 00250 endian=p->endian; 00251 if (p->endian == UndefinedEndian) 00252 endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian; 00253 if (endian == LSBEndian) 00254 { 00255 value=(ssize_t) (*q++); 00256 value|=(*q++) << 8; 00257 } 00258 else 00259 { 00260 value=(ssize_t) (*q++) << 8; 00261 value|=(*q++); 00262 } 00263 if (p->mask == 0) 00264 { 00265 if (p->value == value) 00266 mime_info=p; 00267 } 00268 else 00269 { 00270 if ((p->value & p->mask) == value) 00271 mime_info=p; 00272 } 00273 break; 00274 } 00275 case LongData: 00276 { 00277 if ((size_t) (p->offset+4) > length) 00278 break; 00279 q=magic+p->offset; 00280 endian=p->endian; 00281 if (p->endian == UndefinedEndian) 00282 endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian; 00283 if (endian == LSBEndian) 00284 { 00285 value=(ssize_t) (*q++); 00286 value|=(*q++) << 8; 00287 value|=(*q++) << 16; 00288 value|=(*q++) << 24; 00289 } 00290 else 00291 { 00292 value=(ssize_t) (*q++) << 24; 00293 value|=(*q++) << 16; 00294 value|=(*q++) << 8; 00295 value|=(*q++); 00296 } 00297 if (p->mask == 0) 00298 { 00299 if (p->value == value) 00300 mime_info=p; 00301 } 00302 else 00303 { 00304 if ((p->value & p->mask) == value) 00305 mime_info=p; 00306 } 00307 break; 00308 } 00309 case StringData: 00310 default: 00311 { 00312 for (i=0; i <= (ssize_t) p->extent; i++) 00313 { 00314 if ((size_t) (p->offset+i+p->length) > length) 00315 break; 00316 if (memcmp(magic+p->offset+i,p->magic,p->length) == 0) 00317 { 00318 mime_info=p; 00319 break; 00320 } 00321 } 00322 break; 00323 } 00324 } 00325 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00326 } 00327 if (p != (const MimeInfo *) NULL) 00328 (void) InsertValueInLinkedList(mime_list,0, 00329 RemoveElementByValueFromLinkedList(mime_list,p)); 00330 UnlockSemaphoreInfo(mime_semaphore); 00331 return(mime_info); 00332 } 00333 00334 /* 00335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00336 % % 00337 % % 00338 % % 00339 % G e t M i m e I n f o L i s t % 00340 % % 00341 % % 00342 % % 00343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00344 % 00345 % GetMimeInfoList() returns any image aliases that match the specified 00346 % pattern. 00347 % 00348 % The magic of the GetMimeInfoList function is: 00349 % 00350 % const MimeInfo **GetMimeInfoList(const char *pattern, 00351 % size_t *number_aliases,ExceptionInfo *exception) 00352 % 00353 % A description of each parameter follows: 00354 % 00355 % o pattern: Specifies a pointer to a text string containing a pattern. 00356 % 00357 % o number_aliases: This integer returns the number of magics in the 00358 % list. 00359 % 00360 % o exception: return any errors or warnings in this structure. 00361 % 00362 */ 00363 00364 #if defined(__cplusplus) || defined(c_plusplus) 00365 extern "C" { 00366 #endif 00367 00368 static int MimeInfoCompare(const void *x,const void *y) 00369 { 00370 const MimeInfo 00371 **p, 00372 **q; 00373 00374 p=(const MimeInfo **) x, 00375 q=(const MimeInfo **) y; 00376 if (strcasecmp((*p)->path,(*q)->path) == 0) 00377 return(strcasecmp((*p)->type,(*q)->type)); 00378 return(strcasecmp((*p)->path,(*q)->path)); 00379 } 00380 00381 #if defined(__cplusplus) || defined(c_plusplus) 00382 } 00383 #endif 00384 00385 MagickExport const MimeInfo **GetMimeInfoList(const char *pattern, 00386 size_t *number_aliases,ExceptionInfo *exception) 00387 { 00388 const MimeInfo 00389 **aliases; 00390 00391 register const MimeInfo 00392 *p; 00393 00394 register ssize_t 00395 i; 00396 00397 /* 00398 Allocate mime list. 00399 */ 00400 assert(pattern != (char *) NULL); 00401 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 00402 assert(number_aliases != (size_t *) NULL); 00403 *number_aliases=0; 00404 p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception); 00405 if (p == (const MimeInfo *) NULL) 00406 return((const MimeInfo **) NULL); 00407 aliases=(const MimeInfo **) AcquireQuantumMemory((size_t) 00408 GetNumberOfElementsInLinkedList(mime_list)+1UL,sizeof(*aliases)); 00409 if (aliases == (const MimeInfo **) NULL) 00410 return((const MimeInfo **) NULL); 00411 /* 00412 Generate mime list. 00413 */ 00414 LockSemaphoreInfo(mime_semaphore); 00415 ResetLinkedListIterator(mime_list); 00416 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00417 for (i=0; p != (const MimeInfo *) NULL; ) 00418 { 00419 if ((p->stealth == MagickFalse) && 00420 (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse)) 00421 aliases[i++]=p; 00422 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00423 } 00424 UnlockSemaphoreInfo(mime_semaphore); 00425 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeInfoCompare); 00426 aliases[i]=(MimeInfo *) NULL; 00427 *number_aliases=(size_t) i; 00428 return(aliases); 00429 } 00430 00431 /* 00432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00433 % % 00434 % % 00435 % % 00436 % G e t M i m e L i s t % 00437 % % 00438 % % 00439 % % 00440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00441 % 00442 % GetMimeList() returns any image format alias that matches the specified 00443 % pattern. 00444 % 00445 % The format of the GetMimeList function is: 00446 % 00447 % char **GetMimeList(const char *pattern,size_t *number_aliases, 00448 % ExceptionInfo *exception) 00449 % 00450 % A description of each parameter follows: 00451 % 00452 % o pattern: Specifies a pointer to a text string containing a pattern. 00453 % 00454 % o number_aliases: This integer returns the number of image format aliases 00455 % in the list. 00456 % 00457 % o exception: return any errors or warnings in this structure. 00458 % 00459 */ 00460 00461 #if defined(__cplusplus) || defined(c_plusplus) 00462 extern "C" { 00463 #endif 00464 00465 static int MimeCompare(const void *x,const void *y) 00466 { 00467 register char 00468 *p, 00469 *q; 00470 00471 p=(char *) x; 00472 q=(char *) y; 00473 return(strcasecmp(p,q)); 00474 } 00475 00476 #if defined(__cplusplus) || defined(c_plusplus) 00477 } 00478 #endif 00479 00480 MagickExport char **GetMimeList(const char *pattern, 00481 size_t *number_aliases,ExceptionInfo *exception) 00482 { 00483 char 00484 **aliases; 00485 00486 register const MimeInfo 00487 *p; 00488 00489 register ssize_t 00490 i; 00491 00492 /* 00493 Allocate configure list. 00494 */ 00495 assert(pattern != (char *) NULL); 00496 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 00497 assert(number_aliases != (size_t *) NULL); 00498 *number_aliases=0; 00499 p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception); 00500 if (p == (const MimeInfo *) NULL) 00501 return((char **) NULL); 00502 aliases=(char **) AcquireQuantumMemory((size_t) 00503 GetNumberOfElementsInLinkedList(mime_list)+1UL,sizeof(*aliases)); 00504 if (aliases == (char **) NULL) 00505 return((char **) NULL); 00506 LockSemaphoreInfo(mime_semaphore); 00507 ResetLinkedListIterator(mime_list); 00508 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00509 for (i=0; p != (const MimeInfo *) NULL; ) 00510 { 00511 if ((p->stealth == MagickFalse) && 00512 (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse)) 00513 aliases[i++]=ConstantString(p->type); 00514 p=(const MimeInfo *) GetNextValueInLinkedList(mime_list); 00515 } 00516 UnlockSemaphoreInfo(mime_semaphore); 00517 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeCompare); 00518 aliases[i]=(char *) NULL; 00519 *number_aliases=(size_t) i; 00520 return(aliases); 00521 } 00522 00523 /* 00524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00525 % % 00526 % % 00527 % % 00528 % G e t M i m e D e s c r i p t i o n % 00529 % % 00530 % % 00531 % % 00532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00533 % 00534 % GetMimeDescription() returns the mime type description. 00535 % 00536 % The format of the GetMimeDescription method is: 00537 % 00538 % const char *GetMimeDescription(const MimeInfo *mime_info) 00539 % 00540 % A description of each parameter follows: 00541 % 00542 % o mime_info: The magic info. 00543 % 00544 */ 00545 MagickExport const char *GetMimeDescription(const MimeInfo *mime_info) 00546 { 00547 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00548 assert(mime_info != (MimeInfo *) NULL); 00549 assert(mime_info->signature == MagickSignature); 00550 return(mime_info->description); 00551 } 00552 00553 /* 00554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00555 % % 00556 % % 00557 % % 00558 % G e t M i m e T y p e % 00559 % % 00560 % % 00561 % % 00562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00563 % 00564 % GetMimeType() returns the mime type. 00565 % 00566 % The format of the GetMimeType method is: 00567 % 00568 % const char *GetMimeType(const MimeInfo *mime_info) 00569 % 00570 % A description of each parameter follows: 00571 % 00572 % o mime_info: The magic info. 00573 % 00574 */ 00575 MagickExport const char *GetMimeType(const MimeInfo *mime_info) 00576 { 00577 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"..."); 00578 assert(mime_info != (MimeInfo *) NULL); 00579 assert(mime_info->signature == MagickSignature); 00580 return(mime_info->type); 00581 } 00582 00583 /* 00584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00585 % % 00586 % % 00587 % % 00588 + I n i t i a l i z e M i m e L i s t % 00589 % % 00590 % % 00591 % % 00592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00593 % 00594 % InitializeMimeList() initializes the mime list. 00595 % 00596 % The format of the InitializeMimeList method is: 00597 % 00598 % MagickBooleanType InitializeMimeList(ExceptionInfo *exception) 00599 % 00600 % A description of each parameter follows. 00601 % 00602 % o exception: return any errors or warnings in this structure. 00603 % 00604 */ 00605 static MagickBooleanType InitializeMimeList(ExceptionInfo *exception) 00606 { 00607 if ((mime_list == (LinkedListInfo *) NULL) && 00608 (instantiate_mime == MagickFalse)) 00609 { 00610 if (mime_semaphore == (SemaphoreInfo *) NULL) 00611 AcquireSemaphoreInfo(&mime_semaphore); 00612 LockSemaphoreInfo(mime_semaphore); 00613 if ((mime_list == (LinkedListInfo *) NULL) && 00614 (instantiate_mime == MagickFalse)) 00615 { 00616 (void) LoadMimeLists(MimeFilename,exception); 00617 instantiate_mime=MagickTrue; 00618 } 00619 UnlockSemaphoreInfo(mime_semaphore); 00620 } 00621 return(mime_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse); 00622 } 00623 00624 /* 00625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00626 % % 00627 % % 00628 % % 00629 % L i s t M i m e I n f o % 00630 % % 00631 % % 00632 % % 00633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00634 % 00635 % ListMimeInfo() lists the magic info to a file. 00636 % 00637 % The format of the ListMimeInfo method is: 00638 % 00639 % MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception) 00640 % 00641 % A description of each parameter follows. 00642 % 00643 % o file: An pointer to a FILE. 00644 % 00645 % o exception: return any errors or warnings in this structure. 00646 % 00647 */ 00648 MagickExport MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception) 00649 { 00650 const char 00651 *path; 00652 00653 const MimeInfo 00654 **mime_info; 00655 00656 register ssize_t 00657 i; 00658 00659 size_t 00660 number_aliases; 00661 00662 ssize_t 00663 j; 00664 00665 if (file == (const FILE *) NULL) 00666 file=stdout; 00667 mime_info=GetMimeInfoList("*",&number_aliases,exception); 00668 if (mime_info == (const MimeInfo **) NULL) 00669 return(MagickFalse); 00670 j=0; 00671 path=(const char *) NULL; 00672 for (i=0; i < (ssize_t) number_aliases; i++) 00673 { 00674 if (mime_info[i]->stealth != MagickFalse) 00675 continue; 00676 if ((path == (const char *) NULL) || 00677 (strcasecmp(path,mime_info[i]->path) != 0)) 00678 { 00679 if (mime_info[i]->path != (char *) NULL) 00680 (void) FormatLocaleFile(file,"\nPath: %s\n\n",mime_info[i]->path); 00681 (void) FormatLocaleFile(file,"Type Description\n"); 00682 (void) FormatLocaleFile(file, 00683 "-------------------------------------------------" 00684 "------------------------------\n"); 00685 } 00686 path=mime_info[i]->path; 00687 (void) FormatLocaleFile(file,"%s",mime_info[i]->type); 00688 if (strlen(mime_info[i]->type) <= 25) 00689 { 00690 for (j=(ssize_t) strlen(mime_info[i]->type); j <= 27; j++) 00691 (void) FormatLocaleFile(file," "); 00692 } 00693 else 00694 { 00695 (void) FormatLocaleFile(file,"\n"); 00696 for (j=0; j <= 27; j++) 00697 (void) FormatLocaleFile(file," "); 00698 } 00699 if (mime_info[i]->description != (char *) NULL) 00700 (void) FormatLocaleFile(file,"%s",mime_info[i]->description); 00701 (void) FormatLocaleFile(file,"\n"); 00702 } 00703 (void) fflush(file); 00704 mime_info=(const MimeInfo **) RelinquishMagickMemory((void *) mime_info); 00705 return(MagickTrue); 00706 } 00707 00708 /* 00709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00710 % % 00711 % % 00712 % % 00713 + L o a d M i m e L i s t % 00714 % % 00715 % % 00716 % % 00717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00718 % 00719 % LoadMimeList() loads the magic configuration file which provides a mapping 00720 % between magic attributes and a magic name. 00721 % 00722 % The format of the LoadMimeList method is: 00723 % 00724 % MagickBooleanType LoadMimeList(const char *xml,const char *filename, 00725 % const size_t depth,ExceptionInfo *exception) 00726 % 00727 % A description of each parameter follows: 00728 % 00729 % o xml: The mime list in XML format. 00730 % 00731 % o filename: The mime list filename. 00732 % 00733 % o depth: depth of <include /> statements. 00734 % 00735 % o exception: return any errors or warnings in this structure. 00736 % 00737 */ 00738 static MagickBooleanType LoadMimeList(const char *xml,const char *filename, 00739 const size_t depth,ExceptionInfo *exception) 00740 { 00741 const char 00742 *attribute; 00743 00744 MimeInfo 00745 *mime_info = (MimeInfo *) NULL; 00746 00747 MagickBooleanType 00748 status; 00749 00750 XMLTreeInfo 00751 *mime, 00752 *mime_map, 00753 *include; 00754 00755 /* 00756 Load the mime map file. 00757 */ 00758 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(), 00759 "Loading mime map \"%s\" ...",filename); 00760 if (xml == (const char *) NULL) 00761 return(MagickFalse); 00762 if (mime_list == (LinkedListInfo *) NULL) 00763 { 00764 mime_list=NewLinkedList(0); 00765 if (mime_list == (LinkedListInfo *) NULL) 00766 { 00767 ThrowFileException(exception,ResourceLimitError, 00768 "MemoryAllocationFailed",filename); 00769 return(MagickFalse); 00770 } 00771 } 00772 mime_map=NewXMLTree(xml,exception); 00773 if (mime_map == (XMLTreeInfo *) NULL) 00774 return(MagickFalse); 00775 status=MagickTrue; 00776 include=GetXMLTreeChild(mime_map,"include"); 00777 while (include != (XMLTreeInfo *) NULL) 00778 { 00779 /* 00780 Process include element. 00781 */ 00782 attribute=GetXMLTreeAttribute(include,"file"); 00783 if (attribute != (const char *) NULL) 00784 { 00785 if (depth > 200) 00786 (void) ThrowMagickException(exception,GetMagickModule(), 00787 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",filename); 00788 else 00789 { 00790 char 00791 path[MaxTextExtent], 00792 *xml; 00793 00794 GetPathComponent(filename,HeadPath,path); 00795 if (*path != '\0') 00796 (void) ConcatenateMagickString(path,DirectorySeparator, 00797 MaxTextExtent); 00798 if (*attribute == *DirectorySeparator) 00799 (void) CopyMagickString(path,attribute,MaxTextExtent); 00800 else 00801 (void) ConcatenateMagickString(path,attribute,MaxTextExtent); 00802 xml=FileToString(path,~0,exception); 00803 if (xml != (char *) NULL) 00804 { 00805 status=LoadMimeList(xml,path,depth+1,exception); 00806 xml=DestroyString(xml); 00807 } 00808 } 00809 } 00810 include=GetNextXMLTreeTag(include); 00811 } 00812 mime=GetXMLTreeChild(mime_map,"mime"); 00813 while (mime != (XMLTreeInfo *) NULL) 00814 { 00815 const char 00816 *attribute; 00817 00818 /* 00819 Process mime element. 00820 */ 00821 mime_info=(MimeInfo *) AcquireMagickMemory(sizeof(*mime_info)); 00822 if (mime_info == (MimeInfo *) NULL) 00823 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00824 (void) ResetMagickMemory(mime_info,0,sizeof(*mime_info)); 00825 mime_info->path=ConstantString(filename); 00826 mime_info->signature=MagickSignature; 00827 attribute=GetXMLTreeAttribute(mime,"data-type"); 00828 if (attribute != (const char *) NULL) 00829 mime_info->data_type=(DataType) ParseCommandOption(MagickDataTypeOptions, 00830 MagickTrue,attribute); 00831 attribute=GetXMLTreeAttribute(mime,"description"); 00832 if (attribute != (const char *) NULL) 00833 mime_info->description=ConstantString(attribute); 00834 attribute=GetXMLTreeAttribute(mime,"endian"); 00835 if (attribute != (const char *) NULL) 00836 mime_info->endian=(EndianType) ParseCommandOption(MagickEndianOptions, 00837 MagickTrue,attribute); 00838 attribute=GetXMLTreeAttribute(mime,"magic"); 00839 if (attribute != (const char *) NULL) 00840 { 00841 char 00842 *token; 00843 00844 const char 00845 *p; 00846 00847 register unsigned char 00848 *q; 00849 00850 token=AcquireString(attribute); 00851 (void) SubstituteString((char **) &token,"<","<"); 00852 (void) SubstituteString((char **) &token,"&","&"); 00853 (void) SubstituteString((char **) &token,""","\""); 00854 mime_info->magic=(unsigned char *) AcquireString(token); 00855 q=mime_info->magic; 00856 for (p=token; *p != '\0'; ) 00857 { 00858 if (*p == '\\') 00859 { 00860 p++; 00861 if (isdigit((int) ((unsigned char) *p)) != 0) 00862 { 00863 char 00864 *end; 00865 00866 *q++=(unsigned char) strtol(p,&end,8); 00867 p+=(end-p); 00868 mime_info->length++; 00869 continue; 00870 } 00871 switch (*p) 00872 { 00873 case 'b': *q='\b'; break; 00874 case 'f': *q='\f'; break; 00875 case 'n': *q='\n'; break; 00876 case 'r': *q='\r'; break; 00877 case 't': *q='\t'; break; 00878 case 'v': *q='\v'; break; 00879 case 'a': *q='a'; break; 00880 case '?': *q='\?'; break; 00881 default: *q=(unsigned char) (*p); break; 00882 } 00883 p++; 00884 q++; 00885 mime_info->length++; 00886 continue; 00887 } 00888 *q++=(unsigned char) (*p++); 00889 mime_info->length++; 00890 } 00891 token=DestroyString(token); 00892 if (mime_info->data_type != StringData) 00893 mime_info->value=(ssize_t) strtoul((char *) mime_info->magic, 00894 (char **) NULL,0); 00895 } 00896 attribute=GetXMLTreeAttribute(mime,"mask"); 00897 if (attribute != (const char *) NULL) 00898 mime_info->mask=(ssize_t) strtoul(attribute,(char **) NULL,0); 00899 attribute=GetXMLTreeAttribute(mime,"offset"); 00900 if (attribute != (const char *) NULL) 00901 { 00902 char 00903 *c; 00904 00905 mime_info->offset=(MagickOffsetType) strtol(attribute,&c,0); 00906 if (*c == ':') 00907 mime_info->extent=(size_t) strtol(c+1,(char **) NULL,0); 00908 } 00909 attribute=GetXMLTreeAttribute(mime,"pattern"); 00910 if (attribute != (const char *) NULL) 00911 mime_info->pattern=ConstantString(attribute); 00912 attribute=GetXMLTreeAttribute(mime,"priority"); 00913 if (attribute != (const char *) NULL) 00914 mime_info->priority=(ssize_t) strtol(attribute,(char **) NULL,0); 00915 attribute=GetXMLTreeAttribute(mime,"stealth"); 00916 if (attribute != (const char *) NULL) 00917 mime_info->stealth=IsMagickTrue(attribute); 00918 attribute=GetXMLTreeAttribute(mime,"type"); 00919 if (attribute != (const char *) NULL) 00920 mime_info->type=ConstantString(attribute); 00921 status=AppendValueToLinkedList(mime_list,mime_info); 00922 if (status == MagickFalse) 00923 (void) ThrowMagickException(exception,GetMagickModule(), 00924 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename); 00925 mime=GetNextXMLTreeTag(mime); 00926 } 00927 mime_map=DestroyXMLTree(mime_map); 00928 return(status); 00929 } 00930 00931 /* 00932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00933 % % 00934 % % 00935 % % 00936 % L o a d M i m e L i s t s % 00937 % % 00938 % % 00939 % % 00940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00941 % 00942 % LoadMimeList() loads one or more magic configuration file which provides a 00943 % mapping between magic attributes and a magic name. 00944 % 00945 % The format of the LoadMimeLists method is: 00946 % 00947 % MagickBooleanType LoadMimeLists(const char *filename, 00948 % ExceptionInfo *exception) 00949 % 00950 % A description of each parameter follows: 00951 % 00952 % o filename: the font file name. 00953 % 00954 % o exception: return any errors or warnings in this structure. 00955 % 00956 */ 00957 MagickExport MagickBooleanType LoadMimeLists(const char *filename, 00958 ExceptionInfo *exception) 00959 { 00960 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT) 00961 return(LoadMimeList(MimeMap,"built-in",0,exception)); 00962 #else 00963 const StringInfo 00964 *option; 00965 00966 LinkedListInfo 00967 *options; 00968 00969 MagickStatusType 00970 status; 00971 00972 status=MagickFalse; 00973 options=GetConfigureOptions(filename,exception); 00974 option=(const StringInfo *) GetNextValueInLinkedList(options); 00975 while (option != (const StringInfo *) NULL) 00976 { 00977 status|=LoadMimeList((const char *) GetStringInfoDatum(option), 00978 GetStringInfoPath(option),0,exception); 00979 option=(const StringInfo *) GetNextValueInLinkedList(options); 00980 } 00981 options=DestroyConfigureOptions(options); 00982 if ((mime_list == (LinkedListInfo *) NULL) || 00983 (IsLinkedListEmpty(mime_list) != MagickFalse)) 00984 status|=LoadMimeList(MimeMap,"built-in",0,exception); 00985 else 00986 ClearMagickException(exception); 00987 return(status != 0 ? MagickTrue : MagickFalse); 00988 #endif 00989 } 00990 00991 /* 00992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00993 % % 00994 % % 00995 % % 00996 + M a g i c k T o M i m e % 00997 % % 00998 % % 00999 % % 01000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01001 % 01002 % MagickToMime() returns the officially registered (or de facto) MIME 01003 % media-type corresponding to a magick string. If there is no registered 01004 % media-type, then the string "image/x-magick" (all lower case) is returned. 01005 % The returned string must be deallocated by the user. 01006 % 01007 % The format of the MagickToMime method is: 01008 % 01009 % char *MagickToMime(const char *magick) 01010 % 01011 % A description of each parameter follows. 01012 % 01013 % o magick: ImageMagick format specification "magick" tag. 01014 % 01015 */ 01016 MagickExport char *MagickToMime(const char *magick) 01017 { 01018 char 01019 filename[MaxTextExtent], 01020 media[MaxTextExtent]; 01021 01022 const MimeInfo 01023 *mime_info; 01024 01025 ExceptionInfo 01026 *exception; 01027 01028 (void) FormatLocaleString(filename,MaxTextExtent,"file.%s",magick); 01029 LocaleLower(filename); 01030 exception=AcquireExceptionInfo(); 01031 mime_info=GetMimeInfo(filename,(unsigned char *) " ",1,exception); 01032 exception=DestroyExceptionInfo(exception); 01033 if (mime_info != (const MimeInfo *) NULL) 01034 return(ConstantString(GetMimeType(mime_info))); 01035 (void) FormatLocaleString(media,MaxTextExtent,"image/x-%s",magick); 01036 LocaleLower(media+8); 01037 return(ConstantString(media)); 01038 } 01039 01040 /* 01041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01042 % % 01043 % % 01044 % % 01045 + M i m e C o m p o n e n t G e n e s i s % 01046 % % 01047 % % 01048 % % 01049 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01050 % 01051 % MimeComponentGenesis() instantiates the mime component. 01052 % 01053 % The format of the MimeComponentGenesis method is: 01054 % 01055 % MagickBooleanType MimeComponentGenesis(void) 01056 % 01057 */ 01058 MagickPrivate MagickBooleanType MimeComponentGenesis(void) 01059 { 01060 AcquireSemaphoreInfo(&mime_semaphore); 01061 return(MagickTrue); 01062 } 01063 01064 /* 01065 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01066 % % 01067 % % 01068 % % 01069 + M i m e C o m p o n e n t T e r m i n u s % 01070 % % 01071 % % 01072 % % 01073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01074 % 01075 % MimeComponentTerminus() destroys the mime component. 01076 % 01077 % The format of the MimeComponentTerminus method is: 01078 % 01079 % MimeComponentTerminus(void) 01080 % 01081 */ 01082 01083 static void *DestroyMimeElement(void *mime_info) 01084 { 01085 register MimeInfo 01086 *p; 01087 01088 p=(MimeInfo *) mime_info; 01089 if (p->magic != (unsigned char *) NULL) 01090 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic); 01091 if (p->pattern != (char *) NULL) 01092 p->pattern=DestroyString(p->pattern); 01093 if (p->description != (char *) NULL) 01094 p->description=DestroyString(p->description); 01095 if (p->type != (char *) NULL) 01096 p->type=DestroyString(p->type); 01097 if (p->path != (char *) NULL) 01098 p->path=DestroyString(p->path); 01099 p=(MimeInfo *) RelinquishMagickMemory(p); 01100 return((void *) NULL); 01101 } 01102 01103 MagickPrivate void MimeComponentTerminus(void) 01104 { 01105 if (mime_semaphore == (SemaphoreInfo *) NULL) 01106 AcquireSemaphoreInfo(&mime_semaphore); 01107 LockSemaphoreInfo(mime_semaphore); 01108 if (mime_list != (LinkedListInfo *) NULL) 01109 mime_list=DestroyLinkedList(mime_list,DestroyMimeElement); 01110 instantiate_mime=MagickFalse; 01111 UnlockSemaphoreInfo(mime_semaphore); 01112 DestroySemaphoreInfo(&mime_semaphore); 01113 }