• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2021 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 %    https://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 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/constitute.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/image.h"
50 #include "MagickCore/image-private.h"
51 #include "MagickCore/list.h"
52 #include "MagickCore/magick.h"
53 #include "MagickCore/memory_.h"
54 #include "MagickCore/module.h"
55 #include "MagickCore/quantum-private.h"
56 #include "MagickCore/static.h"
57 #include "MagickCore/resource_.h"
58 #include "MagickCore/string_.h"
59 #include "MagickCore/utility.h"
60 #if defined(MAGICKCORE_XML_DELEGATE)
61 #  if defined(MAGICKCORE_WINDOWS_SUPPORT)
62 #    if !defined(__MINGW32__)
63 #      include <win32config.h>
64 #    endif
65 #  endif
66 #  include <libxml/parser.h>
67 #  include <libxml/xmlmemory.h>
68 #  include <libxml/nanoftp.h>
69 #  include <libxml/nanohttp.h>
70 #endif
71 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
72     !defined(__MINGW32__)
73 #  include <urlmon.h>
74 #  pragma comment(lib, "urlmon.lib")
75 #endif
76 
77 /*
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 %                                                                             %
80 %                                                                             %
81 %                                                                             %
82 %   R e a d U R L I m a g e                                                   %
83 %                                                                             %
84 %                                                                             %
85 %                                                                             %
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %
88 %  ReadURLImage retrieves an image via URL, decodes the image, and returns
89 %  it.  It allocates the memory necessary for the new Image structure and
90 %  returns a pointer to the new image.
91 %
92 %  The format of the ReadURLImage method is:
93 %
94 %      Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
95 %
96 %  A description of each parameter follows:
97 %
98 %    o image_info: the image info.
99 %
100 %    o exception: return any errors or warnings in this structure.
101 %
102 */
103 
104 #if defined(__cplusplus) || defined(c_plusplus)
105 extern "C" {
106 #endif
107 
108 #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
GetFTPData(void * userdata,const char * data,int size)109 static void GetFTPData(void *userdata,const char *data,int size)
110 {
111   FILE
112     *file;
113 
114   size_t
115     length;
116 
117   file=(FILE *) userdata;
118   if (file == (FILE *) NULL)
119     return;
120   if (size <= 0)
121     return;
122   length=fwrite(data,size,1,file);
123   (void) length;
124 }
125 #endif
126 
127 #if defined(__cplusplus) || defined(c_plusplus)
128 }
129 #endif
130 
ReadURLImage(const ImageInfo * image_info,ExceptionInfo * exception)131 static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
132 {
133   char
134     filename[MagickPathExtent];
135 
136   FILE
137     *file;
138 
139   Image
140     *image,
141     *images,
142     *next;
143 
144   ImageInfo
145     *read_info;
146 
147   int
148     unique_file;
149 
150   images=(Image *) NULL;
151   image=AcquireImage(image_info,exception);
152   read_info=CloneImageInfo(image_info);
153   SetImageInfoBlob(read_info,(void *) NULL,0);
154 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
155   if (LocaleCompare(read_info->magick,"https") == 0)
156     {
157       MagickBooleanType
158         status;
159 
160       /*
161         Leverage delegate to read HTTPS link.
162       */
163       status=InvokeDelegate(read_info,image,"https:decode",(char *) NULL,
164         exception);
165       if (status != MagickFalse)
166         {
167           (void) FormatLocaleString(read_info->filename,MagickPathExtent,
168             "%s.dat",read_info->unique);
169           *read_info->magick='\0';
170           images=ReadImage(read_info,exception);
171           (void) RelinquishUniqueFileResource(read_info->filename);
172           if (images != (Image *) NULL)
173             for (next=images; next != (Image *) NULL; next=next->next)
174               (void) CopyMagickString(next->filename,image->filename,
175                 MagickPathExtent);
176         }
177       read_info=DestroyImageInfo(read_info);
178       image=DestroyImage(image);
179       return(images);
180     }
181 #endif
182   if (LocaleCompare(read_info->magick,"file") == 0)
183     {
184       (void) CopyMagickString(read_info->filename,image_info->filename+2,
185         MagickPathExtent);
186       *read_info->magick='\0';
187       images=ReadImage(read_info,exception);
188       read_info=DestroyImageInfo(read_info);
189       image=DestroyImage(image);
190       return(GetFirstImageInList(images));
191     }
192   file=(FILE *) NULL;
193   unique_file=AcquireUniqueFileResource(read_info->filename);
194   if (unique_file != -1)
195     file=fdopen(unique_file,"wb");
196   if ((unique_file == -1) || (file == (FILE *) NULL))
197     {
198       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
199         read_info->filename);
200       read_info=DestroyImageInfo(read_info);
201       image=DestroyImage(image);
202       return((Image *) NULL);
203     }
204   (void) CopyMagickString(filename,image_info->magick,MagickPathExtent);
205   (void) ConcatenateMagickString(filename,":",MagickPathExtent);
206   LocaleLower(filename);
207   (void) ConcatenateMagickString(filename,image_info->filename,
208     MagickPathExtent);
209 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__)
210   (void) fclose(file);
211   if (URLDownloadToFile(NULL,filename,read_info->filename,0,NULL) != S_OK)
212     {
213       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
214         filename);
215       (void) RelinquishUniqueFileResource(read_info->filename);
216       read_info=DestroyImageInfo(read_info);
217       image=DestroyImage(image);
218       return((Image *) NULL);
219     }
220 #else
221 #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
222   if (LocaleCompare(read_info->magick,"ftp") == 0)
223     {
224       void
225         *context;
226 
227       xmlNanoFTPInit();
228       context=xmlNanoFTPNewCtxt(filename);
229       if (context != (void *) NULL)
230         {
231           if (xmlNanoFTPConnect(context) >= 0)
232             (void) xmlNanoFTPGet(context,GetFTPData,(void *) file,
233               (char *) NULL);
234           (void) xmlNanoFTPClose(context);
235         }
236     }
237 #endif
238 #if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)
239   if (LocaleCompare(read_info->magick,"http") == 0)
240     {
241       char
242         buffer[8192],
243         *type;
244 
245       int
246         bytes;
247 
248       void
249         *context;
250 
251       type=(char *) NULL;
252       context=xmlNanoHTTPMethod(filename,(const char *) NULL,
253         (const char *) NULL,&type,(const char *) NULL,0);
254       if (context != (void *) NULL)
255         {
256           ssize_t
257             count;
258 
259           while ((bytes=xmlNanoHTTPRead(context,buffer,sizeof(buffer))) > 0)
260             count=(ssize_t) fwrite(buffer,bytes,1,file);
261           (void) count;
262           xmlNanoHTTPClose(context);
263           xmlFree(type);
264           xmlNanoHTTPCleanup();
265         }
266     }
267 #endif
268   (void) fclose(file);
269 #endif
270   *read_info->magick='\0';
271   images=ReadImage(read_info,exception);
272   (void) RelinquishUniqueFileResource(read_info->filename);
273   if (images != (Image *) NULL)
274     for (next=images; next != (Image *) NULL; next=next->next)
275       (void) CopyMagickString(next->filename,image->filename,MagickPathExtent);
276   read_info=DestroyImageInfo(read_info);
277   image=DestroyImage(image);
278   if (images != (Image *) NULL)
279     GetPathComponent(image_info->filename,TailPath,images->filename);
280   else
281     {
282       (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
283         "NoDataReturned","`%s'",filename);
284       return((Image *) NULL);
285     }
286   return(GetFirstImageInList(images));
287 }
288 
289 /*
290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 %                                                                             %
292 %                                                                             %
293 %                                                                             %
294 %   R e g i s t e r U R L I m a g e                                           %
295 %                                                                             %
296 %                                                                             %
297 %                                                                             %
298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299 %
300 %  RegisterURLImage() adds attributes for the URL image format to
301 %  the list of supported formats.  The attributes include the image format
302 %  tag, a method to read and/or write the format, whether the format
303 %  supports the saving of more than one frame to the same file or blob,
304 %  whether the format supports native in-memory I/O, and a brief
305 %  description of the format.
306 %
307 %  The format of the RegisterURLImage method is:
308 %
309 %      size_t RegisterURLImage(void)
310 %
311 */
RegisterURLImage(void)312 ModuleExport size_t RegisterURLImage(void)
313 {
314   MagickInfo
315     *entry;
316 
317   entry=AcquireMagickInfo("URL","HTTP","Uniform Resource Locator (http://)");
318 #if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
319     !defined(__MINGW32__)) || \
320     (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED))
321   entry->decoder=(DecodeImageHandler *) ReadURLImage;
322 #endif
323   entry->format_type=ImplicitFormatType;
324   (void) RegisterMagickInfo(entry);
325   entry=AcquireMagickInfo("URL","HTTPS","Uniform Resource Locator (https://)");
326   entry->decoder=(DecodeImageHandler *) ReadURLImage;
327   entry->format_type=ImplicitFormatType;
328   (void) RegisterMagickInfo(entry);
329   entry=AcquireMagickInfo("URL","FTP","Uniform Resource Locator (ftp://)");
330 #if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
331     !defined(__MINGW32__)) || \
332     (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED))
333   entry->decoder=(DecodeImageHandler *) ReadURLImage;
334 #endif
335   entry->format_type=ImplicitFormatType;
336   (void) RegisterMagickInfo(entry);
337   entry=AcquireMagickInfo("URL","FILE","Uniform Resource Locator (file://)");
338   entry->decoder=(DecodeImageHandler *) ReadURLImage;
339   entry->format_type=ImplicitFormatType;
340   (void) RegisterMagickInfo(entry);
341   return(MagickImageCoderSignature);
342 }
343 
344 /*
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 %                                                                             %
347 %                                                                             %
348 %                                                                             %
349 %   U n r e g i s t e r U R L I m a g e                                       %
350 %                                                                             %
351 %                                                                             %
352 %                                                                             %
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 %
355 %  UnregisterURLImage() removes format registrations made by the
356 %  URL module from the list of supported formats.
357 %
358 %  The format of the UnregisterURLImage method is:
359 %
360 %      UnregisterURLImage(void)
361 %
362 */
UnregisterURLImage(void)363 ModuleExport void UnregisterURLImage(void)
364 {
365   (void) UnregisterMagickInfo("HTTP");
366   (void) UnregisterMagickInfo("FTP");
367   (void) UnregisterMagickInfo("FILE");
368 }
369