MagickCore  6.7.5
delegate.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %           DDDD   EEEEE  L      EEEEE   GGGG   AAA   TTTTT  EEEEE            %
00006 %           D   D  E      L      E      G      A   A    T    E                %
00007 %           D   D  EEE    L      EEE    G  GG  AAAAA    T    EEE              %
00008 %           D   D  E      L      E      G   G  A   A    T    E                %
00009 %           DDDD   EEEEE  LLLLL  EEEEE   GGG   A   A    T    EEEEE            %
00010 %                                                                             %
00011 %                                                                             %
00012 %             MagickCore Methods to Read/Write/Invoke Delegates               %
00013 %                                                                             %
00014 %                             Software Design                                 %
00015 %                               John Cristy                                   %
00016 %                               October 1998                                  %
00017 %                                                                             %
00018 %                                                                             %
00019 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00020 %  dedicated to making software imaging solutions freely available.           %
00021 %                                                                             %
00022 %  You may not use this file except in compliance with the License.  You may  %
00023 %  obtain a copy of the License at                                            %
00024 %                                                                             %
00025 %    http://www.imagemagick.org/script/license.php                            %
00026 %                                                                             %
00027 %  Unless required by applicable law or agreed to in writing, software        %
00028 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00029 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00030 %  See the License for the specific language governing permissions and        %
00031 %  limitations under the License.                                             %
00032 %                                                                             %
00033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00034 %
00035 %  The Delegates methods associate a set of commands with a particular
00036 %  image format.  ImageMagick uses delegates for formats it does not handle
00037 %  directly.
00038 %
00039 %  Thanks to Bob Friesenhahn for the initial inspiration and design of the
00040 %  delegates methods.
00041 %
00042 %
00043 */
00044 
00045 /*
00046   Include declarations.
00047 */
00048 #include "MagickCore/studio.h"
00049 #include "MagickCore/property.h"
00050 #include "MagickCore/blob.h"
00051 #include "MagickCore/client.h"
00052 #include "MagickCore/configure.h"
00053 #include "MagickCore/constitute.h"
00054 #include "MagickCore/delegate.h"
00055 #include "MagickCore/delegate-private.h"
00056 #include "MagickCore/exception.h"
00057 #include "MagickCore/exception-private.h"
00058 #include "MagickCore/hashmap.h"
00059 #include "MagickCore/list.h"
00060 #include "MagickCore/memory_.h"
00061 #include "MagickCore/policy.h"
00062 #include "MagickCore/resource_.h"
00063 #include "MagickCore/semaphore.h"
00064 #include "MagickCore/string_.h"
00065 #include "MagickCore/token.h"
00066 #include "MagickCore/utility.h"
00067 #include "MagickCore/utility-private.h"
00068 #include "MagickCore/xml-tree.h"
00069 
00070 /*
00071   Define declarations.
00072 */
00073 #define DelegateFilename  "delegates.xml"
00074 
00075 /*
00076   Declare delegate map.
00077 */
00078 static const char
00079   *DelegateMap = (const char *)
00080     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
00081     "<delegatemap>"
00082     "  <delegate decode=\"autotrace\" stealth=\"True\" command=\"&quot;autotrace&quot; -output-format svg -output-file &quot;%o&quot; &quot;%i&quot;\"/>"
00083     "  <delegate decode=\"avi:decode\" stealth=\"True\" command=\"&quot;mplayer&quot; &quot;%i&quot; -really-quiet -ao null -vo png:z=3\"/>"
00084     "  <delegate decode=\"browse\" stealth=\"True\" spawn=\"True\" command=\"&quot;xdg-open&quot; http://www.imagemagick.org/\"/>"
00085     "  <delegate decode=\"cgm\" thread-support=\"False\" command=\"&quot;ralcgm&quot; -d ps -oC &lt; &quot;%i&quot; &gt; &quot;%o&quot; 2&gt; &quot;%u&quot;\"/>"
00086     "  <delegate decode=\"dng:decode\" command=\"&quot;/usr/bin/ufraw-batch&quot; --silent --wb=camera --black-point=auto --exposure=auto --create-id=also --out-type=ppm16 &quot;--output=%u.pnm&quot; &quot;%i&quot;\"/>"
00087     "  <delegate decode=\"edit\" stealth=\"True\" command=\"&quot;xterm&quot; -title &quot;Edit Image Comment&quot; -e vi &quot;%o&quot;\"/>"
00088     "  <delegate decode=\"eps\" encode=\"pdf\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pdfwrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
00089     "  <delegate decode=\"eps\" encode=\"ps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
00090     "  <delegate decode=\"fig\" command=\"&quot;fig2dev&quot; -L ps &quot;%i&quot; &quot;%o&quot;\"/>"
00091     "  <delegate decode=\"gplt\" command=\"&quot;echo&quot; &quot;set size 1.25,0.62     set terminal postscript portrait color solid; set output &quot;%o&quot;; load &quot;%i&quot;&quot; &gt; &quot;%u&quot;;&quot;gnuplot&quot; &quot;%u&quot;\"/>"
00092     "  <delegate decode=\"hpg\" command=\"&quot;hp2xx&quot; -q -m eps -f `basename &quot;%o&quot;` &quot;%i&quot;     mv -f `basename &quot;%o&quot;` &quot;%o&quot;\"/>"
00093     "  <delegate decode=\"hpgl\" command=\"if [ -e hp2xx -o -e /usr/bin/hp2xx ]; then     hp2xx -q -m eps -f `basename &quot;%o&quot;` &quot;%i&quot;     mv -f `basename &quot;%o&quot;` &quot;%o   else     echo &quot;You need to install hp2xx to use HPGL files with ImageMagick.&quot;     exit 1   fi\"/>"
00094     "  <delegate decode=\"htm\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
00095     "  <delegate decode=\"html\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
00096     "  <delegate decode=\"https\" command=\"&quot;wget&quot; -q -O &quot;%o&quot; &quot;https:%M&quot;\"/>"
00097     "  <delegate decode=\"ilbm\" command=\"&quot;ilbmtoppm&quot; &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
00098     "  <delegate decode=\"man\" command=\"&quot;groff&quot; -man -Tps &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
00099     "  <delegate decode=\"mpeg:decode\" stealth=\"True\" command=\"&quot;ffmpeg&quot; -i &quot;%i&quot; -vcodec pam -an -f rawvideo -y &quot;%u0.pam&quot; 2;&gt; &quot;%Z&quot;\"/>"
00100     "  <delegate decode=\"null\" encode=\"mpeg:encode\" stealth=\"True\" command=\"&quot;ffmpeg&quot; &quot;%M%%d.jpg&quot; &quot;%u.%m&quot; 2;&gt; &quot;%Z&quot;\"/>"
00101     "  <delegate decode=\"pcl:color\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=ppmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;%s&quot;\"/>"
00102     "  <delegate decode=\"pcl:cmyk\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=bmpsep8&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;%s&quot;\"/>"
00103     "  <delegate decode=\"pcl:mono\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pbmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;%s&quot;\"/>"
00104     "  <delegate decode=\"pdf\" encode=\"eps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=epswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
00105     "  <delegate decode=\"pdf\" encode=\"ps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
00106     "  <delegate decode=\"pnm\" encode=\"ilbm\" mode=\"encode\" command=\"&quot;ppmtoilbm&quot; -24if &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
00107     "  <delegate decode=\"pnm\" encode=\"launch\" mode=\"encode\" command=\"&quot;gimp&quot; &quot;%i&quot;\"/>"
00108     "  <delegate decode=\"pov\" command=\"&quot;povray&quot; &quot;+i&quot;%i&quot;&quot; -D0 +o&quot;%o&quot; +fn%q +w%w +h%h +a -q9 -kfi&quot;%s&quot; -kff&quot;%n&quot;     &quot;convert&quot; -concatenate &quot;%o*.png&quot; &quot;%o&quot;\"/>"
00109     "  <delegate decode=\"ps\" encode=\"eps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=epswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
00110     "  <delegate decode=\"ps\" encode=\"pdf\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pdfwrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
00111     "  <delegate decode=\"ps\" encode=\"print\" mode=\"encode\" command=\"lpr &quot;%i&quot;\"/>"
00112     "  <delegate decode=\"ps:alpha\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pngalpha&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
00113     "  <delegate decode=\"ps:bbox\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=bbox&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
00114     "  <delegate decode=\"ps:cmyk\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=bmpsep8&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
00115     "  <delegate decode=\"ps:color\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pnmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
00116     "  <delegate decode=\"ps:mono\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pnmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
00117     "  <delegate decode=\"rgba\" encode=\"rle\" mode=\"encode\" command=\"&quot;rawtorle&quot; -o &quot;%o&quot; -v &quot;%i&quot;\"/>"
00118     "  <delegate decode=\"scan\" command=\"&quot;scanimage&quot; -d &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
00119     "  <delegate encode=\"show\" spawn=\"True\" command=\"&quot;/usr/local/bin/display&quot; -immutable -delay 0 -window-group %g -title &quot;%l of %f&quot; &quot;temporary:%i&quot;\"/>"
00120     "  <delegate decode=\"shtml\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
00121     "  <delegate decode=\"svg\" command=\"&quot;rsvg&quot; &quot;%i&quot; &quot;%o&quot;\"/>"
00122     "  <delegate decode=\"txt\" encode=\"ps\" mode=\"bi\" command=\"&quot;enscript&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
00123     "  <delegate encode=\"win\" stealth=\"True\" spawn=\"True\" command=\"&quot;/usr/local/bin/display&quot; -immutable -delay 0 -window-group %g -title &quot;%l of %f&quot; &quot;temporary:%i&quot;\"/>"
00124     "  <delegate decode=\"wmf\" command=\"&quot;wmf2eps&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
00125     "</delegatemap>";
00126 
00127 /*
00128   Global declaractions.
00129 */
00130 static LinkedListInfo
00131   *delegate_list = (LinkedListInfo *) NULL;
00132 
00133 static SemaphoreInfo
00134   *delegate_semaphore = (SemaphoreInfo *) NULL;
00135 
00136 static volatile MagickBooleanType
00137   instantiate_delegate = MagickFalse;
00138 
00139 /*
00140   Forward declaractions.
00141 */
00142 static MagickBooleanType
00143   InitializeDelegateList(ExceptionInfo *),
00144   LoadDelegateLists(const char *,ExceptionInfo *);
00145 
00146 /*
00147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00148 %                                                                             %
00149 %                                                                             %
00150 %                                                                             %
00151 +   D e l e g a t e C o m p o n e n t T e r m i n u s                         %
00152 %                                                                             %
00153 %                                                                             %
00154 %                                                                             %
00155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00156 %
00157 %  DelegateComponentGenesis() instantiates the delegate component.
00158 %
00159 %  The format of the DelegateComponentGenesis method is:
00160 %
00161 %      MagickBooleanType DelegateComponentGenesis(void)
00162 %
00163 */
00164 MagickPrivate MagickBooleanType DelegateComponentGenesis(void)
00165 {
00166   AcquireSemaphoreInfo(&delegate_semaphore);
00167   return(MagickTrue);
00168 }
00169 
00170 /*
00171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00172 %                                                                             %
00173 %                                                                             %
00174 %                                                                             %
00175 %   D e l e g a t e C o m p o n e n t T e r m i n u s                         %
00176 %                                                                             %
00177 %                                                                             %
00178 %                                                                             %
00179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00180 %
00181 %  DelegateComponentTerminus() destroys the delegate component.
00182 %
00183 %  The format of the DelegateComponentTerminus method is:
00184 %
00185 %      DelegateComponentTerminus(void)
00186 %
00187 */
00188 
00189 static void *DestroyDelegate(void *delegate_info)
00190 {
00191   register DelegateInfo
00192     *p;
00193 
00194   p=(DelegateInfo *) delegate_info;
00195   if (p->path != (char *) NULL)
00196     p->path=DestroyString(p->path);
00197   if (p->decode != (char *) NULL)
00198     p->decode=DestroyString(p->decode);
00199   if (p->encode != (char *) NULL)
00200     p->encode=DestroyString(p->encode);
00201   if (p->commands != (char *) NULL)
00202     p->commands=DestroyString(p->commands);
00203   p=(DelegateInfo *) RelinquishMagickMemory(p);
00204   return((void *) NULL);
00205 }
00206 
00207 MagickPrivate void DelegateComponentTerminus(void)
00208 {
00209   if (delegate_semaphore == (SemaphoreInfo *) NULL)
00210     AcquireSemaphoreInfo(&delegate_semaphore);
00211   LockSemaphoreInfo(delegate_semaphore);
00212   if (delegate_list != (LinkedListInfo *) NULL)
00213     delegate_list=DestroyLinkedList(delegate_list,DestroyDelegate);
00214   instantiate_delegate=MagickFalse;
00215   UnlockSemaphoreInfo(delegate_semaphore);
00216   DestroySemaphoreInfo(&delegate_semaphore);
00217 }
00218 
00219 /*
00220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00221 %                                                                             %
00222 %                                                                             %
00223 %                                                                             %
00224 %   G e t D e l e g a t e C o m m a n d                                       %
00225 %                                                                             %
00226 %                                                                             %
00227 %                                                                             %
00228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00229 %
00230 %  GetDelegateCommand() replaces any embedded formatting characters with the
00231 %  appropriate image attribute and returns the resulting command.
00232 %
00233 %  The format of the GetDelegateCommand method is:
00234 %
00235 %      char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
00236 %        const char *decode,const char *encode,ExceptionInfo *exception)
00237 %
00238 %  A description of each parameter follows:
00239 %
00240 %    o command: Method GetDelegateCommand returns the command associated
00241 %      with specified delegate tag.
00242 %
00243 %    o image_info: the image info.
00244 %
00245 %    o image: the image.
00246 %
00247 %    o decode: Specifies the decode delegate we are searching for as a
00248 %      character string.
00249 %
00250 %    o encode: Specifies the encode delegate we are searching for as a
00251 %      character string.
00252 %
00253 %    o exception: return any errors or warnings in this structure.
00254 %
00255 */
00256 MagickExport char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
00257   const char *decode,const char *encode,ExceptionInfo *exception)
00258 {
00259   char
00260     *command,
00261     **commands;
00262 
00263   const DelegateInfo
00264     *delegate_info;
00265 
00266   register ssize_t
00267     i;
00268 
00269   assert(image_info != (ImageInfo *) NULL);
00270   assert(image_info->signature == MagickSignature);
00271   assert(image != (Image *) NULL);
00272   assert(image->signature == MagickSignature);
00273   if (image->debug != MagickFalse)
00274     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00275   delegate_info=GetDelegateInfo(decode,encode,exception);
00276   if (delegate_info == (const DelegateInfo *) NULL)
00277     {
00278       (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
00279         "NoTagFound","`%s'",decode ? decode : encode);
00280       return((char *) NULL);
00281     }
00282   commands=StringToList(delegate_info->commands);
00283   if (commands == (char **) NULL)
00284     {
00285       (void) ThrowMagickException(exception,GetMagickModule(),
00286         ResourceLimitError,"MemoryAllocationFailed","`%s'",
00287         decode ? decode : encode);
00288       return((char *) NULL);
00289     }
00290   command=InterpretImageProperties(image_info,image,commands[0],exception);
00291   if (command == (char *) NULL)
00292     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
00293       "MemoryAllocationFailed","`%s'",commands[0]);
00294   /*
00295     Relinquish resources.
00296   */
00297   for (i=0; commands[i] != (char *) NULL; i++)
00298     commands[i]=DestroyString(commands[i]);
00299   commands=(char **) RelinquishMagickMemory(commands);
00300   return(command);
00301 }
00302 
00303 /*
00304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00305 %                                                                             %
00306 %                                                                             %
00307 %                                                                             %
00308 %   G e t D e l e g a t e C o m m a n d s                                     %
00309 %                                                                             %
00310 %                                                                             %
00311 %                                                                             %
00312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00313 %
00314 %  GetDelegateCommands() returns the commands associated with a delegate.
00315 %
00316 %  The format of the GetDelegateCommands method is:
00317 %
00318 %      const char *GetDelegateCommands(const DelegateInfo *delegate_info)
00319 %
00320 %  A description of each parameter follows:
00321 %
00322 %    o delegate_info:  The delegate info.
00323 %
00324 */
00325 MagickExport const char *GetDelegateCommands(const DelegateInfo *delegate_info)
00326 {
00327   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00328   assert(delegate_info != (DelegateInfo *) NULL);
00329   assert(delegate_info->signature == MagickSignature);
00330   return(delegate_info->commands);
00331 }
00332 
00333 /*
00334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00335 %                                                                             %
00336 %                                                                             %
00337 %                                                                             %
00338 %   G e t D e l e g a t e I n f o                                             %
00339 %                                                                             %
00340 %                                                                             %
00341 %                                                                             %
00342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00343 %
00344 %  GetDelegateInfo() returns any delegates associated with the specified tag.
00345 %
00346 %  The format of the GetDelegateInfo method is:
00347 %
00348 %      const DelegateInfo *GetDelegateInfo(const char *decode,
00349 %        const char *encode,ExceptionInfo *exception)
00350 %
00351 %  A description of each parameter follows:
00352 %
00353 %    o decode: Specifies the decode delegate we are searching for as a
00354 %      character string.
00355 %
00356 %    o encode: Specifies the encode delegate we are searching for as a
00357 %      character string.
00358 %
00359 %    o exception: return any errors or warnings in this structure.
00360 %
00361 */
00362 MagickExport const DelegateInfo *GetDelegateInfo(const char *decode,
00363   const char *encode,ExceptionInfo *exception)
00364 {
00365   register const DelegateInfo
00366     *p;
00367 
00368   assert(exception != (ExceptionInfo *) NULL);
00369   if ((delegate_list == (LinkedListInfo *) NULL) ||
00370       (instantiate_delegate == MagickFalse))
00371     if (InitializeDelegateList(exception) == MagickFalse)
00372       return((const DelegateInfo *) NULL);
00373   if ((delegate_list == (LinkedListInfo *) NULL) ||
00374       (IsLinkedListEmpty(delegate_list) != MagickFalse))
00375     return((const DelegateInfo *) NULL);
00376   if ((LocaleCompare(decode,"*") == 0) && (LocaleCompare(encode,"*") == 0))
00377     return((const DelegateInfo *) GetValueFromLinkedList(delegate_list,0));
00378   /*
00379     Search for named delegate.
00380   */
00381   LockSemaphoreInfo(delegate_semaphore);
00382   ResetLinkedListIterator(delegate_list);
00383   p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00384   while (p != (const DelegateInfo *) NULL)
00385   {
00386     if (p->mode > 0)
00387       {
00388         if (LocaleCompare(p->decode,decode) == 0)
00389           break;
00390         p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00391         continue;
00392       }
00393     if (p->mode < 0)
00394       {
00395         if (LocaleCompare(p->encode,encode) == 0)
00396           break;
00397         p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00398         continue;
00399       }
00400     if (LocaleCompare(decode,p->decode) == 0)
00401       if (LocaleCompare(encode,p->encode) == 0)
00402         break;
00403     if (LocaleCompare(decode,"*") == 0)
00404       if (LocaleCompare(encode,p->encode) == 0)
00405         break;
00406     if (LocaleCompare(decode,p->decode) == 0)
00407       if (LocaleCompare(encode,"*") == 0)
00408         break;
00409     p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00410   }
00411   if (p != (const DelegateInfo *) NULL)
00412     (void) InsertValueInLinkedList(delegate_list,0,
00413       RemoveElementByValueFromLinkedList(delegate_list,p));
00414   UnlockSemaphoreInfo(delegate_semaphore);
00415   return(p);
00416 }
00417 
00418 /*
00419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00420 %                                                                             %
00421 %                                                                             %
00422 %                                                                             %
00423 %   G e t D e l e g a t e I n f o L i s t                                     %
00424 %                                                                             %
00425 %                                                                             %
00426 %                                                                             %
00427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00428 %
00429 %  GetDelegateInfoList() returns any delegates that match the specified pattern.
00430 %
00431 %  The delegate of the GetDelegateInfoList function is:
00432 %
00433 %      const DelegateInfo **GetDelegateInfoList(const char *pattern,
00434 %        size_t *number_delegates,ExceptionInfo *exception)
00435 %
00436 %  A description of each parameter follows:
00437 %
00438 %    o pattern: Specifies a pointer to a text string containing a pattern.
00439 %
00440 %    o number_delegates:  This integer returns the number of delegates in the
00441 %      list.
00442 %
00443 %    o exception: return any errors or warnings in this structure.
00444 %
00445 */
00446 
00447 #if defined(__cplusplus) || defined(c_plusplus)
00448 extern "C" {
00449 #endif
00450 
00451 static int DelegateInfoCompare(const void *x,const void *y)
00452 {
00453   const DelegateInfo
00454     **p,
00455     **q;
00456 
00457   p=(const DelegateInfo **) x,
00458   q=(const DelegateInfo **) y;
00459   if (LocaleCompare((*p)->path,(*q)->path) == 0)
00460     {
00461       if ((*p)->decode == (char *) NULL)
00462         if (((*p)->encode != (char *) NULL) &&
00463             ((*q)->encode != (char *) NULL))
00464           return(strcmp((*p)->encode,(*q)->encode));
00465       if (((*p)->decode != (char *) NULL) &&
00466           ((*q)->decode != (char *) NULL))
00467         return(strcmp((*p)->decode,(*q)->decode));
00468     }
00469   return(LocaleCompare((*p)->path,(*q)->path));
00470 }
00471 
00472 #if defined(__cplusplus) || defined(c_plusplus)
00473 }
00474 #endif
00475 
00476 MagickExport const DelegateInfo **GetDelegateInfoList(const char *pattern,
00477   size_t *number_delegates,ExceptionInfo *exception)
00478 {
00479   const DelegateInfo
00480     **delegates;
00481 
00482   register const DelegateInfo
00483     *p;
00484 
00485   register ssize_t
00486     i;
00487 
00488   /*
00489     Allocate delegate list.
00490   */
00491   assert(pattern != (char *) NULL);
00492   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00493   assert(number_delegates != (size_t *) NULL);
00494   *number_delegates=0;
00495   p=GetDelegateInfo("*","*",exception);
00496   if (p == (const DelegateInfo *) NULL)
00497     return((const DelegateInfo **) NULL);
00498   delegates=(const DelegateInfo **) AcquireQuantumMemory((size_t)
00499     GetNumberOfElementsInLinkedList(delegate_list)+1UL,sizeof(*delegates));
00500   if (delegates == (const DelegateInfo **) NULL)
00501     return((const DelegateInfo **) NULL);
00502   /*
00503     Generate delegate list.
00504   */
00505   LockSemaphoreInfo(delegate_semaphore);
00506   ResetLinkedListIterator(delegate_list);
00507   p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00508   for (i=0; p != (const DelegateInfo *) NULL; )
00509   {
00510     if ((p->stealth == MagickFalse) &&
00511         ((GlobExpression(p->decode,pattern,MagickFalse) != MagickFalse) ||
00512          (GlobExpression(p->encode,pattern,MagickFalse) != MagickFalse)))
00513       delegates[i++]=p;
00514     p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00515   }
00516   UnlockSemaphoreInfo(delegate_semaphore);
00517   qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateInfoCompare);
00518   delegates[i]=(DelegateInfo *) NULL;
00519   *number_delegates=(size_t) i;
00520   return(delegates);
00521 }
00522 
00523 /*
00524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00525 %                                                                             %
00526 %                                                                             %
00527 %                                                                             %
00528 %   G e t D e l e g a t e L i s t                                             %
00529 %                                                                             %
00530 %                                                                             %
00531 %                                                                             %
00532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00533 %
00534 %  GetDelegateList() returns any image format delegates that match the
00535 %  specified  pattern.
00536 %
00537 %  The format of the GetDelegateList function is:
00538 %
00539 %      char **GetDelegateList(const char *pattern,
00540 %        size_t *number_delegates,ExceptionInfo *exception)
00541 %
00542 %  A description of each parameter follows:
00543 %
00544 %    o pattern: Specifies a pointer to a text string containing a pattern.
00545 %
00546 %    o number_delegates:  This integer returns the number of delegates
00547 %      in the list.
00548 %
00549 %    o exception: return any errors or warnings in this structure.
00550 %
00551 */
00552 
00553 #if defined(__cplusplus) || defined(c_plusplus)
00554 extern "C" {
00555 #endif
00556 
00557 static int DelegateCompare(const void *x,const void *y)
00558 {
00559   register const char
00560     **p,
00561     **q;
00562 
00563   p=(const char **) x;
00564   q=(const char **) y;
00565   return(LocaleCompare(*p,*q));
00566 }
00567 
00568 #if defined(__cplusplus) || defined(c_plusplus)
00569 }
00570 #endif
00571 
00572 MagickExport char **GetDelegateList(const char *pattern,
00573   size_t *number_delegates,ExceptionInfo *exception)
00574 {
00575   char
00576     **delegates;
00577 
00578   register const DelegateInfo
00579     *p;
00580 
00581   register ssize_t
00582     i;
00583 
00584   /*
00585     Allocate delegate list.
00586   */
00587   assert(pattern != (char *) NULL);
00588   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00589   assert(number_delegates != (size_t *) NULL);
00590   *number_delegates=0;
00591   p=GetDelegateInfo("*","*",exception);
00592   if (p == (const DelegateInfo *) NULL)
00593     return((char **) NULL);
00594   delegates=(char **) AcquireQuantumMemory((size_t)
00595     GetNumberOfElementsInLinkedList(delegate_list)+1UL,sizeof(*delegates));
00596   if (delegates == (char **) NULL)
00597     return((char **) NULL);
00598   LockSemaphoreInfo(delegate_semaphore);
00599   ResetLinkedListIterator(delegate_list);
00600   p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00601   for (i=0; p != (const DelegateInfo *) NULL; )
00602   {
00603     if ((p->stealth == MagickFalse) &&
00604         (GlobExpression(p->decode,pattern,MagickFalse) != MagickFalse))
00605       delegates[i++]=ConstantString(p->decode);
00606     if ((p->stealth == MagickFalse) &&
00607         (GlobExpression(p->encode,pattern,MagickFalse) != MagickFalse))
00608       delegates[i++]=ConstantString(p->encode);
00609     p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
00610   }
00611   UnlockSemaphoreInfo(delegate_semaphore);
00612   qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateCompare);
00613   delegates[i]=(char *) NULL;
00614   *number_delegates=(size_t) i;
00615   return(delegates);
00616 }
00617 
00618 /*
00619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00620 %                                                                             %
00621 %                                                                             %
00622 %                                                                             %
00623 %   G e t D e l e g a t e M o d e                                             %
00624 %                                                                             %
00625 %                                                                             %
00626 %                                                                             %
00627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00628 %
00629 %  GetDelegateMode() returns the mode of the delegate.
00630 %
00631 %  The format of the GetDelegateMode method is:
00632 %
00633 %      ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
00634 %
00635 %  A description of each parameter follows:
00636 %
00637 %    o delegate_info:  The delegate info.
00638 %
00639 */
00640 MagickExport ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
00641 {
00642   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00643   assert(delegate_info != (DelegateInfo *) NULL);
00644   assert(delegate_info->signature == MagickSignature);
00645   return(delegate_info->mode);
00646 }
00647 
00648 /*
00649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00650 %                                                                             %
00651 %                                                                             %
00652 %                                                                             %
00653 +   G e t D e l e g a t e T h r e a d S u p p o r t                           %
00654 %                                                                             %
00655 %                                                                             %
00656 %                                                                             %
00657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00658 %
00659 %  GetDelegateThreadSupport() returns MagickTrue if the delegate supports
00660 %  threads.
00661 %
00662 %  The format of the GetDelegateThreadSupport method is:
00663 %
00664 %      MagickBooleanType GetDelegateThreadSupport(
00665 %        const DelegateInfo *delegate_info)
00666 %
00667 %  A description of each parameter follows:
00668 %
00669 %    o delegate_info:  The delegate info.
00670 %
00671 */
00672 MagickExport MagickBooleanType GetDelegateThreadSupport(
00673   const DelegateInfo *delegate_info)
00674 {
00675   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00676   assert(delegate_info != (DelegateInfo *) NULL);
00677   assert(delegate_info->signature == MagickSignature);
00678   return(delegate_info->thread_support);
00679 }
00680 
00681 /*
00682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00683 %                                                                             %
00684 %                                                                             %
00685 %                                                                             %
00686 +   I n i t i a l i z e D e l e g a t e L i s t                               %
00687 %                                                                             %
00688 %                                                                             %
00689 %                                                                             %
00690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00691 %
00692 %  InitializeDelegateList() initializes the delegate list.
00693 %
00694 %  The format of the InitializeDelegateList method is:
00695 %
00696 %      MagickBooleanType InitializeDelegateList(ExceptionInfo *exception)
00697 %
00698 %  A description of each parameter follows.
00699 %
00700 %    o exception: return any errors or warnings in this structure.
00701 %
00702 */
00703 static MagickBooleanType InitializeDelegateList(ExceptionInfo *exception)
00704 {
00705   if ((delegate_list == (LinkedListInfo *) NULL) &&
00706       (instantiate_delegate == MagickFalse))
00707     {
00708       if (delegate_semaphore == (SemaphoreInfo *) NULL)
00709         AcquireSemaphoreInfo(&delegate_semaphore);
00710       LockSemaphoreInfo(delegate_semaphore);
00711       if ((delegate_list == (LinkedListInfo *) NULL) &&
00712           (instantiate_delegate == MagickFalse))
00713         {
00714           (void) LoadDelegateLists(DelegateFilename,exception);
00715           instantiate_delegate=MagickTrue;
00716         }
00717       UnlockSemaphoreInfo(delegate_semaphore);
00718     }
00719   return(delegate_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
00720 }
00721 
00722 /*
00723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00724 %                                                                             %
00725 %                                                                             %
00726 %                                                                             %
00727 %   I n v o k e D e l e g a t e                                               %
00728 %                                                                             %
00729 %                                                                             %
00730 %                                                                             %
00731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00732 %
00733 %  InvokeDelegate replaces any embedded formatting characters with the
00734 %  appropriate image attribute and executes the resulting command.  MagickFalse
00735 %  is returned if the commands execute with success otherwise MagickTrue.
00736 %
00737 %  The format of the InvokeDelegate method is:
00738 %
00739 %      MagickBooleanType InvokeDelegate(ImageInfo *image_info,Image *image,
00740 %        const char *decode,const char *encode,ExceptionInfo *exception)
00741 %
00742 %  A description of each parameter follows:
00743 %
00744 %    o image_info: the imageInfo.
00745 %
00746 %    o image: the image.
00747 %
00748 %    o exception: return any errors or warnings in this structure.
00749 %
00750 */
00751 
00752 static inline size_t MagickMin(const size_t x,const size_t y)
00753 {
00754   if (x < y)
00755     return(x);
00756   return(y);
00757 }
00758 
00759 static MagickBooleanType CopyDelegateFile(const char *source,
00760   const char *destination)
00761 {
00762   int
00763     destination_file,
00764     source_file;
00765 
00766   MagickBooleanType
00767     status;
00768 
00769   register size_t
00770     i;
00771 
00772   size_t
00773     length,
00774     quantum;
00775 
00776   ssize_t
00777     count;
00778 
00779   struct stat
00780     attributes;
00781 
00782   unsigned char
00783     *buffer;
00784 
00785   /*
00786     Return if destination file already exists.
00787   */
00788   assert(source != (const char *) NULL);
00789   assert(destination != (char *) NULL);
00790   status=GetPathAttributes(destination,&attributes);
00791   if (status != MagickFalse)
00792     return(MagickTrue);
00793   /*
00794     Copy source file to destination.
00795   */
00796   destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE);
00797   if (destination_file == -1)
00798     return(MagickFalse);
00799   source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
00800   if (source_file == -1)
00801     {
00802       (void) close(destination_file);
00803       return(MagickFalse);
00804     }
00805   quantum=(size_t) MagickMaxBufferExtent;
00806   if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
00807     quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
00808   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
00809   if (buffer == (unsigned char *) NULL)
00810     {
00811       (void) close(source_file);
00812       (void) close(destination_file);
00813       return(MagickFalse);
00814     }
00815   length=0;
00816   for (i=0; ; i+=count)
00817   {
00818     count=(ssize_t) read(source_file,buffer,quantum);
00819     if (count <= 0)
00820       break;
00821     length=(size_t) count;
00822     count=(ssize_t) write(destination_file,buffer,length);
00823     if ((size_t) count != length)
00824       break;
00825   }
00826   (void) close(destination_file);
00827   (void) close(source_file);
00828   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00829   return(i != 0 ? MagickTrue : MagickFalse);
00830 }
00831 
00832 MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info,
00833   Image *image,const char *decode,const char *encode,ExceptionInfo *exception)
00834 {
00835   char
00836     *command,
00837     **commands,
00838     input_filename[MaxTextExtent],
00839     output_filename[MaxTextExtent];
00840 
00841   const DelegateInfo
00842     *delegate_info;
00843 
00844   MagickBooleanType
00845     status,
00846     temporary;
00847 
00848   register ssize_t
00849     i;
00850 
00851   PolicyRights
00852     rights;
00853 
00854   /*
00855     Get delegate.
00856   */
00857   assert(image_info != (ImageInfo *) NULL);
00858   assert(image_info->signature == MagickSignature);
00859   assert(image != (Image *) NULL);
00860   assert(image->signature == MagickSignature);
00861   if (image->debug != MagickFalse)
00862     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00863   rights=ExecutePolicyRights;
00864   if (IsRightsAuthorized(DelegatePolicyDomain,rights,decode) == MagickFalse)
00865     {
00866       errno=EPERM;
00867       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
00868         "NotAuthorized","`%s'",decode);
00869       return(MagickFalse);
00870     }
00871   if (IsRightsAuthorized(DelegatePolicyDomain,rights,encode) == MagickFalse)
00872     {
00873       errno=EPERM;
00874       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
00875         "NotAuthorized","`%s'",encode);
00876       return(MagickFalse);
00877     }
00878   temporary=(*image->filename == '\0') ? MagickTrue : MagickFalse;
00879   if (temporary != MagickFalse)
00880     if (AcquireUniqueFilename(image->filename) == MagickFalse)
00881       {
00882         ThrowFileException(exception,FileOpenError,
00883           "UnableToCreateTemporaryFile",image->filename);
00884         return(MagickFalse);
00885       }
00886   delegate_info=GetDelegateInfo(decode,encode,exception);
00887   if (delegate_info == (DelegateInfo *) NULL)
00888     {
00889       if (temporary != MagickFalse)
00890         (void) RelinquishUniqueFileResource(image->filename);
00891       (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
00892         "NoTagFound","`%s'",decode ? decode : encode);
00893       return(MagickFalse);
00894     }
00895   if (*image_info->filename == '\0')
00896     {
00897       if (AcquireUniqueFilename(image_info->filename) == MagickFalse)
00898         {
00899           if (temporary != MagickFalse)
00900             (void) RelinquishUniqueFileResource(image->filename);
00901           ThrowFileException(exception,FileOpenError,
00902             "UnableToCreateTemporaryFile",image_info->filename);
00903           return(MagickFalse);
00904         }
00905       image_info->temporary=MagickTrue;
00906     }
00907   if ((delegate_info->mode != 0) && (((decode != (const char *) NULL) &&
00908         (delegate_info->encode != (char *) NULL)) ||
00909        ((encode != (const char *) NULL) &&
00910         (delegate_info->decode != (char *) NULL))))
00911     {
00912       char
00913         *magick;
00914 
00915       ImageInfo
00916         *clone_info;
00917 
00918       register Image
00919         *p;
00920 
00921       /*
00922         Delegate requires a particular image format.
00923       */
00924       if (AcquireUniqueFilename(image_info->unique) == MagickFalse)
00925         {
00926           ThrowFileException(exception,FileOpenError,
00927             "UnableToCreateTemporaryFile",image_info->unique);
00928           return(MagickFalse);
00929         }
00930       if (AcquireUniqueFilename(image_info->zero) == MagickFalse)
00931         {
00932           (void) RelinquishUniqueFileResource(image_info->zero);
00933           ThrowFileException(exception,FileOpenError,
00934             "UnableToCreateTemporaryFile",image_info->zero);
00935           return(MagickFalse);
00936         }
00937       magick=InterpretImageProperties(image_info,image,decode != (char *) NULL ?
00938         delegate_info->encode : delegate_info->decode,exception);
00939       if (magick == (char *) NULL)
00940         {
00941           (void) RelinquishUniqueFileResource(image_info->unique);
00942           (void) RelinquishUniqueFileResource(image_info->zero);
00943           if (temporary != MagickFalse)
00944             (void) RelinquishUniqueFileResource(image->filename);
00945           (void) ThrowMagickException(exception,GetMagickModule(),
00946             DelegateError,"DelegateFailed","`%s'",decode ? decode : encode);
00947           return(MagickFalse);
00948         }
00949       LocaleUpper(magick);
00950       clone_info=CloneImageInfo(image_info);
00951       (void) CopyMagickString((char *) clone_info->magick,magick,
00952         MaxTextExtent);
00953       if (LocaleCompare(magick,"NULL") != 0)
00954         (void) CopyMagickString(image->magick,magick,MaxTextExtent);
00955       magick=DestroyString(magick);
00956       (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:",
00957         delegate_info->decode);
00958       (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(image),
00959         exception);
00960       (void) CopyMagickString(clone_info->filename,image_info->filename,
00961         MaxTextExtent);
00962       (void) CopyMagickString(image_info->filename,image->filename,
00963         MaxTextExtent);
00964       for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
00965       {
00966         (void) FormatLocaleString(p->filename,MaxTextExtent,"%s:%s",
00967           delegate_info->decode,clone_info->filename);
00968         status=WriteImage(clone_info,p,exception);
00969         if (status == MagickFalse)
00970           {
00971             (void) RelinquishUniqueFileResource(image_info->unique);
00972             (void) RelinquishUniqueFileResource(image_info->zero);
00973             if (temporary != MagickFalse)
00974               (void) RelinquishUniqueFileResource(image->filename);
00975             clone_info=DestroyImageInfo(clone_info);
00976             (void) ThrowMagickException(exception,GetMagickModule(),
00977               DelegateError,"DelegateFailed","`%s'",decode ? decode : encode);
00978             return(MagickFalse);
00979           }
00980         if (clone_info->adjoin != MagickFalse)
00981           break;
00982       }
00983       (void) RelinquishUniqueFileResource(image_info->unique);
00984       (void) RelinquishUniqueFileResource(image_info->zero);
00985       clone_info=DestroyImageInfo(clone_info);
00986     }
00987   /*
00988     Invoke delegate.
00989   */
00990   commands=StringToList(delegate_info->commands);
00991   if (commands == (char **) NULL)
00992     {
00993       if (temporary != MagickFalse)
00994         (void) RelinquishUniqueFileResource(image->filename);
00995       (void) ThrowMagickException(exception,GetMagickModule(),
00996         ResourceLimitError,"MemoryAllocationFailed","`%s'",
00997         decode ? decode : encode);
00998       return(MagickFalse);
00999     }
01000   command=(char *) NULL;
01001   status=MagickFalse;
01002   (void) CopyMagickString(output_filename,image_info->filename,MaxTextExtent);
01003   (void) CopyMagickString(input_filename,image->filename,MaxTextExtent);
01004   for (i=0; commands[i] != (char *) NULL; i++)
01005   {
01006     status=AcquireUniqueSymbolicLink(output_filename,image_info->filename);
01007     if (AcquireUniqueFilename(image_info->unique) == MagickFalse)
01008       {
01009         ThrowFileException(exception,FileOpenError,
01010           "UnableToCreateTemporaryFile",image_info->unique);
01011         break;
01012       }
01013     if (AcquireUniqueFilename(image_info->zero) == MagickFalse)
01014       {
01015         (void) RelinquishUniqueFileResource(image_info->unique);
01016         ThrowFileException(exception,FileOpenError,
01017           "UnableToCreateTemporaryFile",image_info->zero);
01018         break;
01019       }
01020     if (LocaleCompare(decode,"SCAN") != 0)
01021       {
01022         status=AcquireUniqueSymbolicLink(input_filename,image->filename);
01023         if (status == MagickFalse)
01024           {
01025             ThrowFileException(exception,FileOpenError,
01026               "UnableToCreateTemporaryFile",input_filename);
01027             break;
01028           }
01029       }
01030     status=MagickFalse;
01031     command=InterpretImageProperties(image_info,image,commands[i],exception);
01032     if (command != (char *) NULL)
01033       {
01034         /*
01035           Execute delegate.
01036         */
01037         status=SystemCommand(delegate_info->spawn,image_info->verbose,command,
01038           exception) != 0 ? MagickTrue : MagickFalse;
01039         if (delegate_info->spawn != MagickFalse)
01040           (void) sleep(2);
01041         command=DestroyString(command);
01042       }
01043     if (LocaleCompare(decode,"SCAN") != 0)
01044       {
01045         if (CopyDelegateFile(image->filename,input_filename) == MagickFalse)
01046           (void) RelinquishUniqueFileResource(input_filename);
01047       }
01048     if (CopyDelegateFile(image_info->filename,output_filename) == MagickFalse)
01049       (void) RelinquishUniqueFileResource(output_filename);
01050     if (image_info->temporary != MagickFalse)
01051       (void) RelinquishUniqueFileResource(image_info->filename);
01052     (void) RelinquishUniqueFileResource(image_info->unique);
01053     (void) RelinquishUniqueFileResource(image_info->zero);
01054     (void) RelinquishUniqueFileResource(image_info->filename);
01055     (void) RelinquishUniqueFileResource(image->filename);
01056     if (status != MagickFalse)
01057       {
01058         (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
01059           "DelegateFailed","`%s'",commands[i]);
01060         break;
01061       }
01062     commands[i]=DestroyString(commands[i]);
01063   }
01064   (void) CopyMagickString(image_info->filename,output_filename,MaxTextExtent);
01065   (void) CopyMagickString(image->filename,input_filename,MaxTextExtent);
01066   /*
01067     Relinquish resources.
01068   */
01069   for ( ; commands[i] != (char *) NULL; i++)
01070     commands[i]=DestroyString(commands[i]);
01071   commands=(char **) RelinquishMagickMemory(commands);
01072   if (temporary != MagickFalse)
01073     (void) RelinquishUniqueFileResource(image->filename);
01074   return(status == MagickFalse ? MagickTrue : MagickFalse);
01075 }
01076 
01077 /*
01078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01079 %                                                                             %
01080 %                                                                             %
01081 %                                                                             %
01082 %  L i s t D e l e g a t e I n f o                                            %
01083 %                                                                             %
01084 %                                                                             %
01085 %                                                                             %
01086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01087 %
01088 %  ListDelegateInfo() lists the image formats to a file.
01089 %
01090 %  The format of the ListDelegateInfo method is:
01091 %
01092 %      MagickBooleanType ListDelegateInfo(FILE *file,ExceptionInfo *exception)
01093 %
01094 %  A description of each parameter follows.
01095 %
01096 %    o file:  An pointer to a FILE.
01097 %
01098 %    o exception: return any errors or warnings in this structure.
01099 %
01100 */
01101 MagickExport MagickBooleanType ListDelegateInfo(FILE *file,
01102   ExceptionInfo *exception)
01103 {
01104   const DelegateInfo
01105     **delegate_info;
01106 
01107   char
01108     **commands,
01109     delegate[MaxTextExtent];
01110 
01111   const char
01112     *path;
01113 
01114   register ssize_t
01115     i;
01116 
01117   size_t
01118     number_delegates;
01119 
01120   ssize_t
01121     j;
01122 
01123   if (file == (const FILE *) NULL)
01124     file=stdout;
01125   delegate_info=GetDelegateInfoList("*",&number_delegates,exception);
01126   if (delegate_info == (const DelegateInfo **) NULL)
01127     return(MagickFalse);
01128   path=(const char *) NULL;
01129   for (i=0; i < (ssize_t) number_delegates; i++)
01130   {
01131     if (delegate_info[i]->stealth != MagickFalse)
01132       continue;
01133     if ((path == (const char *) NULL) ||
01134         (LocaleCompare(path,delegate_info[i]->path) != 0))
01135       {
01136         if (delegate_info[i]->path != (char *) NULL)
01137           (void) FormatLocaleFile(file,"\nPath: %s\n\n",delegate_info[i]->path);
01138         (void) FormatLocaleFile(file,"Delegate                Command\n");
01139         (void) FormatLocaleFile(file,
01140           "-------------------------------------------------"
01141           "------------------------------\n");
01142       }
01143     path=delegate_info[i]->path;
01144     *delegate='\0';
01145     if (delegate_info[i]->encode != (char *) NULL)
01146       (void) CopyMagickString(delegate,delegate_info[i]->encode,MaxTextExtent);
01147     (void) ConcatenateMagickString(delegate,"        ",MaxTextExtent);
01148     delegate[8]='\0';
01149     commands=StringToList(delegate_info[i]->commands);
01150     if (commands == (char **) NULL)
01151       continue;
01152     (void) FormatLocaleFile(file,"%11s%c=%c%s  ",delegate_info[i]->decode ?
01153       delegate_info[i]->decode : "",delegate_info[i]->mode <= 0 ? '<' : ' ',
01154       delegate_info[i]->mode >= 0 ? '>' : ' ',delegate);
01155     StripString(commands[0]);
01156     (void) FormatLocaleFile(file,"\"%s\"\n",commands[0]);
01157     for (j=1; commands[j] != (char *) NULL; j++)
01158     {
01159       StripString(commands[j]);
01160       (void) FormatLocaleFile(file,"                     \"%s\"\n",commands[j]);
01161     }
01162     for (j=0; commands[j] != (char *) NULL; j++)
01163       commands[j]=DestroyString(commands[j]);
01164     commands=(char **) RelinquishMagickMemory(commands);
01165   }
01166   (void) fflush(file);
01167   delegate_info=(const DelegateInfo **)
01168     RelinquishMagickMemory((void *) delegate_info);
01169   return(MagickTrue);
01170 }
01171 
01172 /*
01173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01174 %                                                                             %
01175 %                                                                             %
01176 %                                                                             %
01177 +   L o a d D e l e g a t e L i s t                                           %
01178 %                                                                             %
01179 %                                                                             %
01180 %                                                                             %
01181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01182 %
01183 %  LoadDelegateList() loads the delegate configuration file which provides a
01184 %  mapping between delegate attributes and a delegate name.
01185 %
01186 %  The format of the LoadDelegateList method is:
01187 %
01188 %      MagickBooleanType LoadDelegateList(const char *xml,const char *filename,
01189 %        const size_t depth,ExceptionInfo *exception)
01190 %
01191 %  A description of each parameter follows:
01192 %
01193 %    o xml:  The delegate list in XML format.
01194 %
01195 %    o filename:  The delegate list filename.
01196 %
01197 %    o depth: depth of <include /> statements.
01198 %
01199 %    o exception: return any errors or warnings in this structure.
01200 %
01201 */
01202 static MagickBooleanType LoadDelegateList(const char *xml,const char *filename,
01203   const size_t depth,ExceptionInfo *exception)
01204 {
01205   char
01206     keyword[MaxTextExtent],
01207     *token;
01208 
01209   const char
01210     *q;
01211 
01212   DelegateInfo
01213     *delegate_info;
01214 
01215   MagickBooleanType
01216     status;
01217 
01218   /*
01219     Load the delegate map file.
01220   */
01221   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
01222     "Loading delegate configuration file \"%s\" ...",filename);
01223   if (xml == (const char *) NULL)
01224     return(MagickFalse);
01225   if (delegate_list == (LinkedListInfo *) NULL)
01226     {
01227       delegate_list=NewLinkedList(0);
01228       if (delegate_list == (LinkedListInfo *) NULL)
01229         {
01230           ThrowFileException(exception,ResourceLimitError,
01231             "MemoryAllocationFailed",filename);
01232           return(MagickFalse);
01233         }
01234     }
01235   status=MagickTrue;
01236   delegate_info=(DelegateInfo *) NULL;
01237   token=AcquireString(xml);
01238   for (q=(const char *) xml; *q != '\0'; )
01239   {
01240     /*
01241       Interpret XML.
01242     */
01243     GetMagickToken(q,&q,token);
01244     if (*token == '\0')
01245       break;
01246     (void) CopyMagickString(keyword,token,MaxTextExtent);
01247     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
01248       {
01249         /*
01250           Doctype element.
01251         */
01252         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
01253           GetMagickToken(q,&q,token);
01254         continue;
01255       }
01256     if (LocaleNCompare(keyword,"<!--",4) == 0)
01257       {
01258         /*
01259           Comment element.
01260         */
01261         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
01262           GetMagickToken(q,&q,token);
01263         continue;
01264       }
01265     if (LocaleCompare(keyword,"<include") == 0)
01266       {
01267         /*
01268           Include element.
01269         */
01270         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
01271         {
01272           (void) CopyMagickString(keyword,token,MaxTextExtent);
01273           GetMagickToken(q,&q,token);
01274           if (*token != '=')
01275             continue;
01276           GetMagickToken(q,&q,token);
01277           if (LocaleCompare(keyword,"file") == 0)
01278             {
01279               if (depth > 200)
01280                 (void) ThrowMagickException(exception,GetMagickModule(),
01281                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
01282               else
01283                 {
01284                   char
01285                     path[MaxTextExtent],
01286                     *xml;
01287 
01288                   GetPathComponent(filename,HeadPath,path);
01289                   if (*path != '\0')
01290                     (void) ConcatenateMagickString(path,DirectorySeparator,
01291                       MaxTextExtent);
01292                   if (*token == *DirectorySeparator)
01293                     (void) CopyMagickString(path,token,MaxTextExtent);
01294                   else
01295                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
01296                   xml=FileToString(path,~0,exception);
01297                   if (xml != (char *) NULL)
01298                     {
01299                       status=LoadDelegateList(xml,path,depth+1,exception);
01300                       xml=(char *) RelinquishMagickMemory(xml);
01301                     }
01302                 }
01303             }
01304         }
01305         continue;
01306       }
01307     if (LocaleCompare(keyword,"<delegate") == 0)
01308       {
01309         /*
01310           Delegate element.
01311         */
01312         delegate_info=(DelegateInfo *) AcquireMagickMemory(
01313           sizeof(*delegate_info));
01314         if (delegate_info == (DelegateInfo *) NULL)
01315           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01316         (void) ResetMagickMemory(delegate_info,0,sizeof(*delegate_info));
01317         delegate_info->path=ConstantString(filename);
01318         delegate_info->signature=MagickSignature;
01319         continue;
01320       }
01321     if (delegate_info == (DelegateInfo *) NULL)
01322       continue;
01323     if (LocaleCompare(keyword,"/>") == 0)
01324       {
01325         status=AppendValueToLinkedList(delegate_list,delegate_info);
01326         if (status == MagickFalse)
01327           (void) ThrowMagickException(exception,GetMagickModule(),
01328             ResourceLimitError,"MemoryAllocationFailed","`%s'",
01329             delegate_info->commands);
01330         delegate_info=(DelegateInfo *) NULL;
01331       }
01332     GetMagickToken(q,(const char **) NULL,token);
01333     if (*token != '=')
01334       continue;
01335     GetMagickToken(q,&q,token);
01336     GetMagickToken(q,&q,token);
01337     switch (*keyword)
01338     {
01339       case 'C':
01340       case 'c':
01341       {
01342         if (LocaleCompare((char *) keyword,"command") == 0)
01343           {
01344             char
01345               *commands;
01346 
01347             commands=AcquireString(token);
01348 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
01349             if (strchr(commands,'@') != (char *) NULL)
01350               {
01351                 char
01352                   path[MaxTextExtent];
01353 
01354                 NTGhostscriptEXE(path,MaxTextExtent);
01355                 (void) SubstituteString((char **) &commands,"@PSDelegate@",
01356                   path);
01357                 (void) SubstituteString((char **) &commands,"\\","/");
01358               }
01359 #endif
01360             (void) SubstituteString((char **) &commands,"&amp;","&");
01361             (void) SubstituteString((char **) &commands,"&quot;","\"");
01362             (void) SubstituteString((char **) &commands,"&gt;",">");
01363             (void) SubstituteString((char **) &commands,"&lt;","<");
01364             delegate_info->commands=commands;
01365             break;
01366           }
01367         break;
01368       }
01369       case 'D':
01370       case 'd':
01371       {
01372         if (LocaleCompare((char *) keyword,"decode") == 0)
01373           {
01374             delegate_info->decode=ConstantString(token);
01375             delegate_info->mode=1;
01376             break;
01377           }
01378         break;
01379       }
01380       case 'E':
01381       case 'e':
01382       {
01383         if (LocaleCompare((char *) keyword,"encode") == 0)
01384           {
01385             delegate_info->encode=ConstantString(token);
01386             delegate_info->mode=(-1);
01387             break;
01388           }
01389         break;
01390       }
01391       case 'M':
01392       case 'm':
01393       {
01394         if (LocaleCompare((char *) keyword,"mode") == 0)
01395           {
01396             delegate_info->mode=1;
01397             if (LocaleCompare(token,"bi") == 0)
01398               delegate_info->mode=0;
01399             else
01400               if (LocaleCompare(token,"encode") == 0)
01401                 delegate_info->mode=(-1);
01402             break;
01403           }
01404         break;
01405       }
01406       case 'S':
01407       case 's':
01408       {
01409         if (LocaleCompare((char *) keyword,"spawn") == 0)
01410           {
01411             delegate_info->spawn=IsMagickTrue(token);
01412             break;
01413           }
01414         if (LocaleCompare((char *) keyword,"stealth") == 0)
01415           {
01416             delegate_info->stealth=IsMagickTrue(token);
01417             break;
01418           }
01419         break;
01420       }
01421       case 'T':
01422       case 't':
01423       {
01424         if (LocaleCompare((char *) keyword,"thread-support") == 0)
01425           {
01426             delegate_info->thread_support=IsMagickTrue(token);
01427             break;
01428           }
01429         break;
01430       }
01431       default:
01432         break;
01433     }
01434   }
01435   token=(char *) RelinquishMagickMemory(token);
01436   return(status);
01437 }
01438 
01439 /*
01440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01441 %                                                                             %
01442 %                                                                             %
01443 %                                                                             %
01444 %  L o a d D e l e g a t e L i s t s                                          %
01445 %                                                                             %
01446 %                                                                             %
01447 %                                                                             %
01448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01449 %
01450 %  LoadDelegateList() loads one or more delegate configuration file which
01451 %  provides a mapping between delegate attributes and a delegate name.
01452 %
01453 %  The format of the LoadDelegateLists method is:
01454 %
01455 %      MagickBooleanType LoadDelegateLists(const char *filename,
01456 %        ExceptionInfo *exception)
01457 %
01458 %  A description of each parameter follows:
01459 %
01460 %    o filename: the font file name.
01461 %
01462 %    o exception: return any errors or warnings in this structure.
01463 %
01464 */
01465 static MagickBooleanType LoadDelegateLists(const char *filename,
01466   ExceptionInfo *exception)
01467 {
01468 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
01469   return(LoadDelegateList(DelegateMap,"built-in",0,exception));
01470 #else
01471   const StringInfo
01472     *option;
01473 
01474   LinkedListInfo
01475     *options;
01476 
01477   MagickStatusType
01478     status;
01479 
01480   status=MagickFalse;
01481   options=GetConfigureOptions(filename,exception);
01482   option=(const StringInfo *) GetNextValueInLinkedList(options);
01483   while (option != (const StringInfo *) NULL)
01484   {
01485     status|=LoadDelegateList((const char *) GetStringInfoDatum(option),
01486       GetStringInfoPath(option),0,exception);
01487     option=(const StringInfo *) GetNextValueInLinkedList(options);
01488   }
01489   options=DestroyConfigureOptions(options);
01490   if ((delegate_list == (LinkedListInfo *) NULL) ||
01491       (IsLinkedListEmpty(delegate_list) != MagickFalse))
01492     status|=LoadDelegateList(DelegateMap,"built-in",0,exception);
01493   return(status != 0 ? MagickTrue : MagickFalse);
01494 #endif
01495 }