blob: 6276ee999dd9e634c028f79597484c8cf75bdee3 [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 %
16% John Cristy %
17% Bill Radcliffe %
18% March 2000 %
19% %
20% %
cristyfe676ee2013-11-18 13:03:38 +000021% Copyright 1999-2014 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)
cristy07a3cca2012-12-10 13:09:10 +000062# if defined(__MINGW32__) || defined(__MINGW64__)
cristy3ed852e2009-09-05 21:47:34 +000063# define _MSC_VER
64# else
65# include <win32config.h>
66# endif
67# endif
68# include <libxml/parser.h>
69# include <libxml/xmlmemory.h>
70# include <libxml/nanoftp.h>
71# include <libxml/nanohttp.h>
72#endif
cristyb0af14f2013-09-26 12:22:34 +000073#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
74 !(defined(__MINGW32__) || defined(__MINGW64__))
75# include <urlmon.h>
dirk853b77b2013-09-21 19:04:42 +000076#endif
77
cristy3ed852e2009-09-05 21:47:34 +000078/*
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80% %
81% %
82% %
83% R e a d U R L I m a g e %
84% %
85% %
86% %
87%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88%
89% ReadURLImage retrieves an image via URL, decodes the image, and returns
90% it. It allocates the memory necessary for the new Image structure and
91% returns a pointer to the new image.
92%
93% The format of the ReadURLImage method is:
94%
95% Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
96%
97% A description of each parameter follows:
98%
99% o image_info: the image info.
100%
101% o exception: return any errors or warnings in this structure.
102%
103*/
104
105#if defined(__cplusplus) || defined(c_plusplus)
106extern "C" {
107#endif
108
109#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
110static void GetFTPData(void *userdata,const char *data,int size)
111{
112 FILE
113 *file;
114
115 size_t
116 length;
117
118 file=(FILE *) userdata;
119 if (file == (FILE *) NULL)
120 return;
121 if (size <= 0)
122 return;
123 length=fwrite(data,size,1,file);
cristyda16f162011-02-19 23:52:17 +0000124 (void) length;
cristy3ed852e2009-09-05 21:47:34 +0000125}
126#endif
127
128#if defined(__cplusplus) || defined(c_plusplus)
129}
130#endif
131
132static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
133{
134#define MaxBufferExtent 8192
135
136 char
137 filename[MaxTextExtent];
138
139 FILE
140 *file;
141
142 Image
143 *image;
144
145 ImageInfo
146 *read_info;
147
148 int
149 unique_file;
150
151 image=(Image *) NULL;
152 read_info=CloneImageInfo(image_info);
153 SetImageInfoBlob(read_info,(void *) NULL,0);
154 file=(FILE *) NULL;
155 unique_file=AcquireUniqueFileResource(read_info->filename);
156 if (unique_file != -1)
157 file=fdopen(unique_file,"wb");
158 if ((unique_file == -1) || (file == (FILE *) NULL))
159 {
cristy3ed852e2009-09-05 21:47:34 +0000160 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
cristy12e65472013-04-05 11:49:29 +0000161 read_info->filename);
162 read_info=DestroyImageInfo(read_info);
cristy3ed852e2009-09-05 21:47:34 +0000163 return((Image *) NULL);
164 }
165 (void) CopyMagickString(filename,image_info->magick,MaxTextExtent);
166 (void) ConcatenateMagickString(filename,":",MaxTextExtent);
167 LocaleLower(filename);
168 (void) ConcatenateMagickString(filename,image_info->filename,MaxTextExtent);
169 if (LocaleCompare(read_info->magick,"file") == 0)
170 {
171 (void) RelinquishUniqueFileResource(read_info->filename);
172 unique_file=(-1);
173 (void) CopyMagickString(read_info->filename,image_info->filename+2,
174 MaxTextExtent);
175 }
cristyb0af14f2013-09-26 12:22:34 +0000176#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
177 !(defined(__MINGW32__) || defined(__MINGW64__))
178 (void) fclose(file);
dirk93b02b72013-11-16 16:03:36 +0000179 if (URLDownloadToFile(NULL,filename,read_info->filename,0,NULL) != S_OK)
cristyb0af14f2013-09-26 12:22:34 +0000180 {
181 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
182 filename);
183 (void) RelinquishUniqueFileResource(read_info->filename);
184 read_info=DestroyImageInfo(read_info);
185 return((Image *) NULL);
186 }
dirk853b77b2013-09-21 19:04:42 +0000187#else
cristy3ed852e2009-09-05 21:47:34 +0000188#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
189 if (LocaleCompare(read_info->magick,"ftp") == 0)
190 {
191 void
192 *context;
193
194 xmlNanoFTPInit();
195 context=xmlNanoFTPNewCtxt(filename);
196 if (context != (void *) NULL)
197 {
198 if (xmlNanoFTPConnect(context) >= 0)
199 (void) xmlNanoFTPGet(context,GetFTPData,(void *) file,
200 (char *) NULL);
201 (void) xmlNanoFTPClose(context);
202 }
203 }
204#endif
205#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)
206 if (LocaleCompare(read_info->magick,"http") == 0)
207 {
208 char
209 buffer[MaxBufferExtent],
210 *type;
211
212 int
213 bytes;
214
215 void
216 *context;
217
218 type=(char *) NULL;
219 context=xmlNanoHTTPMethod(filename,(const char *) NULL,
220 (const char *) NULL,&type,(const char *) NULL,0);
221 if (context != (void *) NULL)
222 {
223 ssize_t
224 count;
225
226 while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0)
227 count=(ssize_t) fwrite(buffer,bytes,1,file);
cristyda16f162011-02-19 23:52:17 +0000228 (void) count;
cristy3ed852e2009-09-05 21:47:34 +0000229 xmlNanoHTTPClose(context);
230 xmlFree(type);
231 xmlNanoHTTPCleanup();
232 }
233 }
234#endif
235 (void) fclose(file);
dirk853b77b2013-09-21 19:04:42 +0000236#endif
cristy6ec529f2012-08-28 11:21:44 +0000237 {
238 ExceptionInfo
239 *sans;
240
241 ImageInfo
242 *clone_info;
243
244 /*
245 Guess image format from URL.
246 */
247 clone_info=CloneImageInfo(image_info);
248 sans=AcquireExceptionInfo();
249 (void) SetImageInfo(clone_info,0,sans);
250 (void) CopyMagickString(read_info->magick,clone_info->magick,MaxTextExtent);
251 clone_info=DestroyImageInfo(clone_info);
252 sans=DestroyExceptionInfo(sans);
253 }
cristy3ed852e2009-09-05 21:47:34 +0000254 image=ReadImage(read_info,exception);
255 if (unique_file != -1)
256 (void) RelinquishUniqueFileResource(read_info->filename);
257 read_info=DestroyImageInfo(read_info);
cristya134d332010-12-12 20:33:53 +0000258 if (image != (Image *) NULL)
259 GetPathComponent(image_info->filename,TailPath,image->filename);
260 else
cristy7ff4c442012-04-03 18:02:50 +0000261 {
262 (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
263 "NoDataReturned","`%s'",filename);
264 return((Image *) NULL);
265 }
cristy3ed852e2009-09-05 21:47:34 +0000266 return(GetFirstImageInList(image));
267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
274% R e g i s t e r U R L I m a g e %
275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
280% RegisterURLImage() adds attributes for the URL image format to
281% the list of supported formats. The attributes include the image format
282% tag, a method to read and/or write the format, whether the format
283% supports the saving of more than one frame to the same file or blob,
284% whether the format supports native in-memory I/O, and a brief
285% description of the format.
286%
287% The format of the RegisterURLImage method is:
288%
cristybb503372010-05-27 20:51:26 +0000289% size_t RegisterURLImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000290%
291*/
cristybb503372010-05-27 20:51:26 +0000292ModuleExport size_t RegisterURLImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000293{
294 MagickInfo
295 *entry;
296
297 entry=SetMagickInfo("HTTP");
cristyb0af14f2013-09-26 12:22:34 +0000298#if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
299 !(defined(__MINGW32__) || defined(__MINGW64__))) || \
dirk853b77b2013-09-21 19:04:42 +0000300 (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED))
cristy3ed852e2009-09-05 21:47:34 +0000301 entry->decoder=(DecodeImageHandler *) ReadURLImage;
302#endif
303 entry->description=ConstantString("Uniform Resource Locator (http://)");
304 entry->module=ConstantString("URL");
305 entry->stealth=MagickTrue;
306 (void) RegisterMagickInfo(entry);
cristyb0af14f2013-09-26 12:22:34 +0000307 entry=SetMagickInfo("HTTPS");
308#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \
309 !(defined(__MINGW32__) || defined(__MINGW64__))
310 entry->decoder=(DecodeImageHandler *) ReadURLImage;
311#endif
312 entry->description=ConstantString("Uniform Resource Locator (https://)");
313 entry->module=ConstantString("URL");
314 entry->stealth=MagickTrue;
dirk853b77b2013-09-21 19:04:42 +0000315 (void) RegisterMagickInfo(entry);
cristy3ed852e2009-09-05 21:47:34 +0000316 entry=SetMagickInfo("FTP");
cristyb0af14f2013-09-26 12:22:34 +0000317#if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \
318 !(defined(__MINGW32__) || defined(__MINGW64__))) || \
dirk853b77b2013-09-21 19:04:42 +0000319 (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED))
cristy3ed852e2009-09-05 21:47:34 +0000320 entry->decoder=(DecodeImageHandler *) ReadURLImage;
321#endif
322 entry->description=ConstantString("Uniform Resource Locator (ftp://)");
323 entry->module=ConstantString("URL");
324 entry->stealth=MagickTrue;
325 (void) RegisterMagickInfo(entry);
326 entry=SetMagickInfo("FILE");
327 entry->decoder=(DecodeImageHandler *) ReadURLImage;
328 entry->description=ConstantString("Uniform Resource Locator (file://)");
329 entry->module=ConstantString("URL");
330 entry->stealth=MagickTrue;
331 (void) RegisterMagickInfo(entry);
332 return(MagickImageCoderSignature);
333}
334
335/*
336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337% %
338% %
339% %
340% U n r e g i s t e r U R L I m a g e %
341% %
342% %
343% %
344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345%
346% UnregisterURLImage() removes format registrations made by the
347% URL module from the list of supported formats.
348%
349% The format of the UnregisterURLImage method is:
350%
351% UnregisterURLImage(void)
352%
353*/
354ModuleExport void UnregisterURLImage(void)
355{
356 (void) UnregisterMagickInfo("HTTP");
357 (void) UnregisterMagickInfo("FTP");
358 (void) UnregisterMagickInfo("FILE");
359}