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

Generated on 21 Nov 2009 for MagickCore by  doxygen 1.6.1