Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                            U   U  RRRR   L                                  %
      7 %                            U   U  R   R  L                                  %
      8 %                            U   U  RRRR   L                                  %
      9 %                            U   U  R R    L                                  %
     10 %                             UUU   R  R   LLLLL                              %
     11 %                                                                             %
     12 %                                                                             %
     13 %                        Retrieve An Image Via URL.                           %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                              Bill Radcliffe                                 %
     18 %                                March 2000                                   %
     19 %                                                                             %
     20 %                                                                             %
     21 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     22 %  dedicated to making software imaging solutions freely available.           %
     23 %                                                                             %
     24 %  You may not use this file except in compliance with the License.  You may  %
     25 %  obtain a copy of the License at                                            %
     26 %                                                                             %
     27 %    http://www.imagemagick.org/script/license.php                            %
     28 %                                                                             %
     29 %  Unless required by applicable law or agreed to in writing, software        %
     30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     32 %  See the License for the specific language governing permissions and        %
     33 %  limitations under the License.                                             %
     34 %                                                                             %
     35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     36 %
     37 %
     38 */
     39 
     40 /*
     42   Include declarations.
     43 */
     44 #include "MagickCore/studio.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/blob-private.h"
     47 #include "MagickCore/constitute.h"
     48 #include "MagickCore/exception.h"
     49 #include "MagickCore/exception-private.h"
     50 #include "MagickCore/image.h"
     51 #include "MagickCore/image-private.h"
     52 #include "MagickCore/list.h"
     53 #include "MagickCore/magick.h"
     54 #include "MagickCore/memory_.h"
     55 #include "MagickCore/module.h"
     56 #include "MagickCore/quantum-private.h"
     57 #include "MagickCore/static.h"
     58 #include "MagickCore/resource_.h"
     59 #include "MagickCore/string_.h"
     60 #include "MagickCore/utility.h"
     61 #if defined(MAGICKCORE_XML_DELEGATE)
     62 #  if defined(MAGICKCORE_WINDOWS_SUPPORT)
     63 #    if !defined(__MINGW32__) && !defined(__MINGW64__)
     64 #      include <win32config.h>
     65 #    endif
     66 #  endif
     67 #  include <libxml/parser.h>
     68 #  include <libxml/xmlmemory.h>
     69 #  include <libxml/nanoftp.h>
     70 #  include <libxml/nanohttp.h>
     71 #endif
     72 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
     73     !(defined(__MINGW32__) || defined(__MINGW64__))
     74 #  include <urlmon.h>
     75 #  pragma comment(lib, "urlmon.lib")
     76 #endif
     77 
     78 /*
     80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     81 %                                                                             %
     82 %                                                                             %
     83 %                                                                             %
     84 %   R e a d U R L I m a g e                                                   %
     85 %                                                                             %
     86 %                                                                             %
     87 %                                                                             %
     88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     89 %
     90 %  ReadURLImage retrieves an image via URL, decodes the image, and returns
     91 %  it.  It allocates the memory necessary for the new Image structure and
     92 %  returns a pointer to the new image.
     93 %
     94 %  The format of the ReadURLImage method is:
     95 %
     96 %      Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
     97 %
     98 %  A description of each parameter follows:
     99 %
    100 %    o image_info: the image info.
    101 %
    102 %    o exception: return any errors or warnings in this structure.
    103 %
    104 */
    105 
    106 #if defined(__cplusplus) || defined(c_plusplus)
    107 extern "C" {
    108 #endif
    109 
    110 #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
    111 static void GetFTPData(void *userdata,const char *data,int size)
    112 {
    113   FILE
    114     *file;
    115 
    116   size_t
    117     length;
    118 
    119   file=(FILE *) userdata;
    120   if (file == (FILE *) NULL)
    121     return;
    122   if (size <= 0)
    123     return;
    124   length=fwrite(data,size,1,file);
    125   (void) length;
    126 }
    127 #endif
    128 
    129 #if defined(__cplusplus) || defined(c_plusplus)
    130 }
    131 #endif
    132 
    133 static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
    134 {
    135 #define MaxBufferExtent  8192
    136 
    137   char
    138     filename[MagickPathExtent];
    139 
    140   FILE
    141     *file;
    142 
    143   Image
    144     *image;
    145 
    146   ImageInfo
    147     *read_info;
    148 
    149   int
    150     unique_file;
    151 
    152   read_info=CloneImageInfo(image_info);
    153   SetImageInfoBlob(read_info,(void *) NULL,0);
    154   if (LocaleCompare(read_info->magick,"file") == 0)
    155     {
    156       (void) CopyMagickString(read_info->filename,image_info->filename+2,
    157         MagickPathExtent);
    158       *read_info->magick='\0';
    159       image=ReadImage(read_info,exception);
    160       read_info=DestroyImageInfo(read_info);
    161       return(GetFirstImageInList(image));
    162     }
    163   file=(FILE *) NULL;
    164   unique_file=AcquireUniqueFileResource(read_info->filename);
    165   if (unique_file != -1)
    166     file=fdopen(unique_file,"wb");
    167   if ((unique_file == -1) || (file == (FILE *) NULL))
    168     {
    169       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
    170         read_info->filename);
    171       read_info=DestroyImageInfo(read_info);
    172       return((Image *) NULL);
    173     }
    174   (void) CopyMagickString(filename,image_info->magick,MagickPathExtent);
    175   (void) ConcatenateMagickString(filename,":",MagickPathExtent);
    176   LocaleLower(filename);
    177   (void) ConcatenateMagickString(filename,image_info->filename,
    178     MagickPathExtent);
    179 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
    180     !(defined(__MINGW32__) || defined(__MINGW64__))
    181   (void) fclose(file);
    182   if (URLDownloadToFile(NULL,filename,read_info->filename,0,NULL) != S_OK)
    183     {
    184       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
    185         filename);
    186       (void) RelinquishUniqueFileResource(read_info->filename);
    187       read_info=DestroyImageInfo(read_info);
    188       return((Image *) NULL);
    189     }
    190 #else
    191 #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
    192   if (LocaleCompare(read_info->magick,"ftp") == 0)
    193     {
    194       void
    195         *context;
    196 
    197       xmlNanoFTPInit();
    198       context=xmlNanoFTPNewCtxt(filename);
    199       if (context != (void *) NULL)
    200         {
    201           if (xmlNanoFTPConnect(context) >= 0)
    202             (void) xmlNanoFTPGet(context,GetFTPData,(void *) file,
    203               (char *) NULL);
    204           (void) xmlNanoFTPClose(context);
    205         }
    206     }
    207 #endif
    208 #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)
    209   if (LocaleCompare(read_info->magick,"http") == 0)
    210     {
    211       char
    212         buffer[MaxBufferExtent],
    213         *type;
    214 
    215       int
    216         bytes;
    217 
    218       void
    219         *context;
    220 
    221       type=(char *) NULL;
    222       context=xmlNanoHTTPMethod(filename,(const char *) NULL,
    223         (const char *) NULL,&type,(const char *) NULL,0);
    224       if (context != (void *) NULL)
    225         {
    226           ssize_t
    227             count;
    228 
    229           while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0)
    230             count=(ssize_t) fwrite(buffer,bytes,1,file);
    231           (void) count;
    232           xmlNanoHTTPClose(context);
    233           xmlFree(type);
    234           xmlNanoHTTPCleanup();
    235         }
    236     }
    237 #endif
    238   (void) fclose(file);
    239 #endif
    240   *read_info->magick='\0';
    241   image=ReadImage(read_info,exception);
    242   (void) RelinquishUniqueFileResource(read_info->filename);
    243   read_info=DestroyImageInfo(read_info);
    244   if (image != (Image *) NULL)
    245     GetPathComponent(image_info->filename,TailPath,image->filename);
    246   else
    247     {
    248       (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
    249         "NoDataReturned","`%s'",filename);
    250       return((Image *) NULL);
    251     }
    252   return(GetFirstImageInList(image));
    253 }
    254 
    255 /*
    257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    258 %                                                                             %
    259 %                                                                             %
    260 %                                                                             %
    261 %   R e g i s t e r U R L I m a g e                                           %
    262 %                                                                             %
    263 %                                                                             %
    264 %                                                                             %
    265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    266 %
    267 %  RegisterURLImage() adds attributes for the URL image format to
    268 %  the list of supported formats.  The attributes include the image format
    269 %  tag, a method to read and/or write the format, whether the format
    270 %  supports the saving of more than one frame to the same file or blob,
    271 %  whether the format supports native in-memory I/O, and a brief
    272 %  description of the format.
    273 %
    274 %  The format of the RegisterURLImage method is:
    275 %
    276 %      size_t RegisterURLImage(void)
    277 %
    278 */
    279 ModuleExport size_t RegisterURLImage(void)
    280 {
    281   MagickInfo
    282     *entry;
    283 
    284   entry=AcquireMagickInfo("URL","HTTP","Uniform Resource Locator (http://)");
    285 #if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
    286     !(defined(__MINGW32__) || defined(__MINGW64__))) || \
    287     (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED))
    288   entry->decoder=(DecodeImageHandler *) ReadURLImage;
    289 #endif
    290   entry->format_type=ImplicitFormatType;
    291   (void) RegisterMagickInfo(entry);
    292   entry=AcquireMagickInfo("URL","HTTPS","Uniform Resource Locator (https://)");
    293 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
    294     !(defined(__MINGW32__) || defined(__MINGW64__))
    295   entry->decoder=(DecodeImageHandler *) ReadURLImage;
    296 #endif
    297   entry->format_type=ImplicitFormatType;
    298   (void) RegisterMagickInfo(entry);
    299   entry=AcquireMagickInfo("URL","FTP","Uniform Resource Locator (ftp://)");
    300 #if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
    301     !(defined(__MINGW32__) || defined(__MINGW64__))) || \
    302     (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED))
    303   entry->decoder=(DecodeImageHandler *) ReadURLImage;
    304 #endif
    305   entry->format_type=ImplicitFormatType;
    306   (void) RegisterMagickInfo(entry);
    307   entry=AcquireMagickInfo("URL","FILE","Uniform Resource Locator (file://)");
    308   entry->decoder=(DecodeImageHandler *) ReadURLImage;
    309   entry->format_type=ImplicitFormatType;
    310   (void) RegisterMagickInfo(entry);
    311   return(MagickImageCoderSignature);
    312 }
    313 
    314 /*
    316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    317 %                                                                             %
    318 %                                                                             %
    319 %                                                                             %
    320 %   U n r e g i s t e r U R L I m a g e                                       %
    321 %                                                                             %
    322 %                                                                             %
    323 %                                                                             %
    324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    325 %
    326 %  UnregisterURLImage() removes format registrations made by the
    327 %  URL module from the list of supported formats.
    328 %
    329 %  The format of the UnregisterURLImage method is:
    330 %
    331 %      UnregisterURLImage(void)
    332 %
    333 */
    334 ModuleExport void UnregisterURLImage(void)
    335 {
    336   (void) UnregisterMagickInfo("HTTP");
    337   (void) UnregisterMagickInfo("FTP");
    338   (void) UnregisterMagickInfo("FILE");
    339 }
    340