blob: 19dbd73bdceeb5fbda4889cbe4036eb72139dc64 [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% %
cristy45ef08f2012-12-07 13:13:34 +000021% Copyright 1999-2013 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
73
74/*
75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76% %
77% %
78% %
79% R e a d U R L I m a g e %
80% %
81% %
82% %
83%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84%
85% ReadURLImage retrieves an image via URL, decodes the image, and returns
86% it. It allocates the memory necessary for the new Image structure and
87% returns a pointer to the new image.
88%
89% The format of the ReadURLImage method is:
90%
91% Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
92%
93% A description of each parameter follows:
94%
95% o image_info: the image info.
96%
97% o exception: return any errors or warnings in this structure.
98%
99*/
100
101#if defined(__cplusplus) || defined(c_plusplus)
102extern "C" {
103#endif
104
105#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
106static void GetFTPData(void *userdata,const char *data,int size)
107{
108 FILE
109 *file;
110
111 size_t
112 length;
113
114 file=(FILE *) userdata;
115 if (file == (FILE *) NULL)
116 return;
117 if (size <= 0)
118 return;
119 length=fwrite(data,size,1,file);
cristyda16f162011-02-19 23:52:17 +0000120 (void) length;
cristy3ed852e2009-09-05 21:47:34 +0000121}
122#endif
123
124#if defined(__cplusplus) || defined(c_plusplus)
125}
126#endif
127
128static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
129{
130#define MaxBufferExtent 8192
131
132 char
133 filename[MaxTextExtent];
134
135 FILE
136 *file;
137
138 Image
139 *image;
140
141 ImageInfo
142 *read_info;
143
144 int
145 unique_file;
146
147 image=(Image *) NULL;
148 read_info=CloneImageInfo(image_info);
149 SetImageInfoBlob(read_info,(void *) NULL,0);
150 file=(FILE *) NULL;
151 unique_file=AcquireUniqueFileResource(read_info->filename);
152 if (unique_file != -1)
153 file=fdopen(unique_file,"wb");
154 if ((unique_file == -1) || (file == (FILE *) NULL))
155 {
156 read_info=DestroyImageInfo(read_info);
157 (void) CopyMagickString(image->filename,read_info->filename,
158 MaxTextExtent);
159 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
160 image->filename);
161 image=DestroyImageList(image);
162 return((Image *) NULL);
163 }
164 (void) CopyMagickString(filename,image_info->magick,MaxTextExtent);
165 (void) ConcatenateMagickString(filename,":",MaxTextExtent);
166 LocaleLower(filename);
167 (void) ConcatenateMagickString(filename,image_info->filename,MaxTextExtent);
168 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,
173 MaxTextExtent);
174 }
175#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
176 if (LocaleCompare(read_info->magick,"ftp") == 0)
177 {
178 void
179 *context;
180
181 xmlNanoFTPInit();
182 context=xmlNanoFTPNewCtxt(filename);
183 if (context != (void *) NULL)
184 {
185 if (xmlNanoFTPConnect(context) >= 0)
186 (void) xmlNanoFTPGet(context,GetFTPData,(void *) file,
187 (char *) NULL);
188 (void) xmlNanoFTPClose(context);
189 }
190 }
191#endif
192#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)
193 if (LocaleCompare(read_info->magick,"http") == 0)
194 {
195 char
196 buffer[MaxBufferExtent],
197 *type;
198
199 int
200 bytes;
201
202 void
203 *context;
204
205 type=(char *) NULL;
206 context=xmlNanoHTTPMethod(filename,(const char *) NULL,
207 (const char *) NULL,&type,(const char *) NULL,0);
208 if (context != (void *) NULL)
209 {
210 ssize_t
211 count;
212
213 while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0)
214 count=(ssize_t) fwrite(buffer,bytes,1,file);
cristyda16f162011-02-19 23:52:17 +0000215 (void) count;
cristy3ed852e2009-09-05 21:47:34 +0000216 xmlNanoHTTPClose(context);
217 xmlFree(type);
218 xmlNanoHTTPCleanup();
219 }
220 }
221#endif
222 (void) fclose(file);
cristy6ec529f2012-08-28 11:21:44 +0000223 {
224 ExceptionInfo
225 *sans;
226
227 ImageInfo
228 *clone_info;
229
230 /*
231 Guess image format from URL.
232 */
233 clone_info=CloneImageInfo(image_info);
234 sans=AcquireExceptionInfo();
235 (void) SetImageInfo(clone_info,0,sans);
236 (void) CopyMagickString(read_info->magick,clone_info->magick,MaxTextExtent);
237 clone_info=DestroyImageInfo(clone_info);
238 sans=DestroyExceptionInfo(sans);
239 }
cristy3ed852e2009-09-05 21:47:34 +0000240 image=ReadImage(read_info,exception);
241 if (unique_file != -1)
242 (void) RelinquishUniqueFileResource(read_info->filename);
243 read_info=DestroyImageInfo(read_info);
cristya134d332010-12-12 20:33:53 +0000244 if (image != (Image *) NULL)
245 GetPathComponent(image_info->filename,TailPath,image->filename);
246 else
cristy7ff4c442012-04-03 18:02:50 +0000247 {
248 (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
249 "NoDataReturned","`%s'",filename);
250 return((Image *) NULL);
251 }
cristy3ed852e2009-09-05 21:47:34 +0000252 return(GetFirstImageInList(image));
253}
254
255/*
256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257% %
258% %
259% %
260% R e g i s t e r U R L I m a g e %
261% %
262% %
263% %
264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265%
266% RegisterURLImage() adds attributes for the URL image format to
267% the list of supported formats. The attributes include the image format
268% tag, a method to read and/or write the format, whether the format
269% supports the saving of more than one frame to the same file or blob,
270% whether the format supports native in-memory I/O, and a brief
271% description of the format.
272%
273% The format of the RegisterURLImage method is:
274%
cristybb503372010-05-27 20:51:26 +0000275% size_t RegisterURLImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000276%
277*/
cristybb503372010-05-27 20:51:26 +0000278ModuleExport size_t RegisterURLImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000279{
280 MagickInfo
281 *entry;
282
283 entry=SetMagickInfo("HTTP");
284#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)
285 entry->decoder=(DecodeImageHandler *) ReadURLImage;
286#endif
287 entry->description=ConstantString("Uniform Resource Locator (http://)");
288 entry->module=ConstantString("URL");
289 entry->stealth=MagickTrue;
290 (void) RegisterMagickInfo(entry);
291 entry=SetMagickInfo("FTP");
292#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)
293 entry->decoder=(DecodeImageHandler *) ReadURLImage;
294#endif
295 entry->description=ConstantString("Uniform Resource Locator (ftp://)");
296 entry->module=ConstantString("URL");
297 entry->stealth=MagickTrue;
298 (void) RegisterMagickInfo(entry);
299 entry=SetMagickInfo("FILE");
300 entry->decoder=(DecodeImageHandler *) ReadURLImage;
301 entry->description=ConstantString("Uniform Resource Locator (file://)");
302 entry->module=ConstantString("URL");
303 entry->stealth=MagickTrue;
304 (void) RegisterMagickInfo(entry);
305 return(MagickImageCoderSignature);
306}
307
308/*
309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310% %
311% %
312% %
313% U n r e g i s t e r U R L I m a g e %
314% %
315% %
316% %
317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318%
319% UnregisterURLImage() removes format registrations made by the
320% URL module from the list of supported formats.
321%
322% The format of the UnregisterURLImage method is:
323%
324% UnregisterURLImage(void)
325%
326*/
327ModuleExport void UnregisterURLImage(void)
328{
329 (void) UnregisterMagickInfo("HTTP");
330 (void) UnregisterMagickInfo("FTP");
331 (void) UnregisterMagickInfo("FILE");
332}