blob: 5449b4229859a340f5fb7230e7d5f28dd5744e1d [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% Bill Radcliffe %
18% March 2000 %
19% %
20% %
cristyb56bb242014-11-25 17:12:48 +000021% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000022% 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/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#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"
cristy3ed852e2009-09-05 21:47:34 +000060#if defined(MAGICKCORE_XML_DELEGATE)
cristy0157aea2010-04-24 21:12:18 +000061# if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy14e6cc72014-10-05 19:31:31 +000062# if !defined(__MINGW32__) && !defined(__MINGW64__)
cristy3ed852e2009-09-05 21:47:34 +000063# 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
cristyb0af14f2013-09-26 12:22:34 +000071#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
72 !(defined(__MINGW32__) || defined(__MINGW64__))
73# include <urlmon.h>
dirk5cb71bb2015-01-03 17:38:05 +000074# pragma comment(lib, "urlmon.lib")
dirk853b77b2013-09-21 19:04:42 +000075#endif
76
cristy3ed852e2009-09-05 21:47:34 +000077/*
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)
105extern "C" {
106#endif
107
108#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
109static 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);
cristyda16f162011-02-19 23:52:17 +0000123 (void) length;
cristy3ed852e2009-09-05 21:47:34 +0000124}
125#endif
126
127#if defined(__cplusplus) || defined(c_plusplus)
128}
129#endif
130
131static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
132{
133#define MaxBufferExtent 8192
134
135 char
cristy151b66d2015-04-15 10:50:31 +0000136 filename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000137
138 FILE
139 *file;
140
141 Image
142 *image;
143
144 ImageInfo
145 *read_info;
146
147 int
148 unique_file;
149
150 image=(Image *) NULL;
151 read_info=CloneImageInfo(image_info);
152 SetImageInfoBlob(read_info,(void *) NULL,0);
153 file=(FILE *) NULL;
154 unique_file=AcquireUniqueFileResource(read_info->filename);
155 if (unique_file != -1)
156 file=fdopen(unique_file,"wb");
157 if ((unique_file == -1) || (file == (FILE *) NULL))
158 {
cristy3ed852e2009-09-05 21:47:34 +0000159 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
cristy12e65472013-04-05 11:49:29 +0000160 read_info->filename);
161 read_info=DestroyImageInfo(read_info);
cristy3ed852e2009-09-05 21:47:34 +0000162 return((Image *) NULL);
163 }
cristy151b66d2015-04-15 10:50:31 +0000164 (void) CopyMagickString(filename,image_info->magick,MagickPathExtent);
165 (void) ConcatenateMagickString(filename,":",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000166 LocaleLower(filename);
cristy151b66d2015-04-15 10:50:31 +0000167 (void) ConcatenateMagickString(filename,image_info->filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000168 if (LocaleCompare(read_info->magick,"file") == 0)
169 {
170 (void) RelinquishUniqueFileResource(read_info->filename);
171 unique_file=(-1);
172 (void) CopyMagickString(read_info->filename,image_info->filename+2,
cristy151b66d2015-04-15 10:50:31 +0000173 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000174 }
cristyb0af14f2013-09-26 12:22:34 +0000175#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
176 !(defined(__MINGW32__) || defined(__MINGW64__))
177 (void) fclose(file);
dirk93b02b72013-11-16 16:03:36 +0000178 if (URLDownloadToFile(NULL,filename,read_info->filename,0,NULL) != S_OK)
cristyb0af14f2013-09-26 12:22:34 +0000179 {
180 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
181 filename);
182 (void) RelinquishUniqueFileResource(read_info->filename);
183 read_info=DestroyImageInfo(read_info);
184 return((Image *) NULL);
185 }
dirk853b77b2013-09-21 19:04:42 +0000186#else
cristy3ed852e2009-09-05 21:47:34 +0000187#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
188 if (LocaleCompare(read_info->magick,"ftp") == 0)
189 {
190 void
191 *context;
192
193 xmlNanoFTPInit();
194 context=xmlNanoFTPNewCtxt(filename);
195 if (context != (void *) NULL)
196 {
197 if (xmlNanoFTPConnect(context) >= 0)
198 (void) xmlNanoFTPGet(context,GetFTPData,(void *) file,
199 (char *) NULL);
200 (void) xmlNanoFTPClose(context);
201 }
202 }
203#endif
204#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)
205 if (LocaleCompare(read_info->magick,"http") == 0)
206 {
207 char
208 buffer[MaxBufferExtent],
209 *type;
210
211 int
212 bytes;
213
214 void
215 *context;
216
217 type=(char *) NULL;
218 context=xmlNanoHTTPMethod(filename,(const char *) NULL,
219 (const char *) NULL,&type,(const char *) NULL,0);
220 if (context != (void *) NULL)
221 {
222 ssize_t
223 count;
224
225 while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0)
226 count=(ssize_t) fwrite(buffer,bytes,1,file);
cristyda16f162011-02-19 23:52:17 +0000227 (void) count;
cristy3ed852e2009-09-05 21:47:34 +0000228 xmlNanoHTTPClose(context);
229 xmlFree(type);
230 xmlNanoHTTPCleanup();
231 }
232 }
233#endif
234 (void) fclose(file);
dirk853b77b2013-09-21 19:04:42 +0000235#endif
cristy6ec529f2012-08-28 11:21:44 +0000236 {
237 ExceptionInfo
238 *sans;
239
240 ImageInfo
241 *clone_info;
242
243 /*
244 Guess image format from URL.
245 */
246 clone_info=CloneImageInfo(image_info);
247 sans=AcquireExceptionInfo();
248 (void) SetImageInfo(clone_info,0,sans);
cristy151b66d2015-04-15 10:50:31 +0000249 (void) CopyMagickString(read_info->magick,clone_info->magick,MagickPathExtent);
cristy6ec529f2012-08-28 11:21:44 +0000250 clone_info=DestroyImageInfo(clone_info);
251 sans=DestroyExceptionInfo(sans);
252 }
cristy3ed852e2009-09-05 21:47:34 +0000253 image=ReadImage(read_info,exception);
254 if (unique_file != -1)
255 (void) RelinquishUniqueFileResource(read_info->filename);
256 read_info=DestroyImageInfo(read_info);
cristya134d332010-12-12 20:33:53 +0000257 if (image != (Image *) NULL)
258 GetPathComponent(image_info->filename,TailPath,image->filename);
259 else
cristy7ff4c442012-04-03 18:02:50 +0000260 {
261 (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
262 "NoDataReturned","`%s'",filename);
263 return((Image *) NULL);
264 }
cristy3ed852e2009-09-05 21:47:34 +0000265 return(GetFirstImageInList(image));
266}
267
268/*
269%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
270% %
271% %
272% %
273% R e g i s t e r U R L I m a g e %
274% %
275% %
276% %
277%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278%
279% RegisterURLImage() adds attributes for the URL image format to
280% the list of supported formats. The attributes include the image format
281% tag, a method to read and/or write the format, whether the format
282% supports the saving of more than one frame to the same file or blob,
283% whether the format supports native in-memory I/O, and a brief
284% description of the format.
285%
286% The format of the RegisterURLImage method is:
287%
cristybb503372010-05-27 20:51:26 +0000288% size_t RegisterURLImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000289%
290*/
cristybb503372010-05-27 20:51:26 +0000291ModuleExport size_t RegisterURLImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000292{
293 MagickInfo
294 *entry;
295
dirk06b627a2015-04-06 18:59:17 +0000296 entry=AcquireMagickInfo("URL","HTTP","Uniform Resource Locator (http://)");
cristyb0af14f2013-09-26 12:22:34 +0000297#if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
298 !(defined(__MINGW32__) || defined(__MINGW64__))) || \
dirk853b77b2013-09-21 19:04:42 +0000299 (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED))
cristy3ed852e2009-09-05 21:47:34 +0000300 entry->decoder=(DecodeImageHandler *) ReadURLImage;
301#endif
dirk08e9a112015-02-22 01:51:41 +0000302 entry->flags|=CoderStealthFlag;
cristy3ed852e2009-09-05 21:47:34 +0000303 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000304 entry=AcquireMagickInfo("URL","HTTPS","Uniform Resource Locator (https://)");
cristyb0af14f2013-09-26 12:22:34 +0000305#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
306 !(defined(__MINGW32__) || defined(__MINGW64__))
307 entry->decoder=(DecodeImageHandler *) ReadURLImage;
308#endif
dirk08e9a112015-02-22 01:51:41 +0000309 entry->flags|=CoderStealthFlag;
dirk853b77b2013-09-21 19:04:42 +0000310 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000311 entry=AcquireMagickInfo("URL","FTP","Uniform Resource Locator (ftp://)");
cristyb0af14f2013-09-26 12:22:34 +0000312#if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
313 !(defined(__MINGW32__) || defined(__MINGW64__))) || \
dirk853b77b2013-09-21 19:04:42 +0000314 (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED))
cristy3ed852e2009-09-05 21:47:34 +0000315 entry->decoder=(DecodeImageHandler *) ReadURLImage;
316#endif
dirk08e9a112015-02-22 01:51:41 +0000317 entry->flags|=CoderStealthFlag;
cristy3ed852e2009-09-05 21:47:34 +0000318 (void) RegisterMagickInfo(entry);
dirk06b627a2015-04-06 18:59:17 +0000319 entry=AcquireMagickInfo("URL","FILE","Uniform Resource Locator (file://)");
cristy3ed852e2009-09-05 21:47:34 +0000320 entry->decoder=(DecodeImageHandler *) ReadURLImage;
dirk08e9a112015-02-22 01:51:41 +0000321 entry->flags|=CoderStealthFlag;
cristy3ed852e2009-09-05 21:47:34 +0000322 (void) RegisterMagickInfo(entry);
323 return(MagickImageCoderSignature);
324}
325
326/*
327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328% %
329% %
330% %
331% U n r e g i s t e r U R L I m a g e %
332% %
333% %
334% %
335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336%
337% UnregisterURLImage() removes format registrations made by the
338% URL module from the list of supported formats.
339%
340% The format of the UnregisterURLImage method is:
341%
342% UnregisterURLImage(void)
343%
344*/
345ModuleExport void UnregisterURLImage(void)
346{
347 (void) UnregisterMagickInfo("HTTP");
348 (void) UnregisterMagickInfo("FTP");
349 (void) UnregisterMagickInfo("FILE");
350}