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/* 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__) && !defined(__MINGW64__) 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__) || defined(__MINGW64__)) 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) 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); 123 (void) length; 124} 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 136 filename[MagickPathExtent]; 137 138 FILE 139 *file; 140 141 Image 142 *image; 143 144 ImageInfo 145 *read_info; 146 147 int 148 unique_file; 149 150 read_info=CloneImageInfo(image_info); 151 SetImageInfoBlob(read_info,(void *) NULL,0); 152 if (LocaleCompare(read_info->magick,"file") == 0) 153 { 154 (void) CopyMagickString(read_info->filename,image_info->filename+2, 155 MagickPathExtent); 156 *read_info->magick='\0'; 157 image=ReadImage(read_info,exception); 158 read_info=DestroyImageInfo(read_info); 159 return(GetFirstImageInList(image)); 160 } 161 file=(FILE *) NULL; 162 unique_file=AcquireUniqueFileResource(read_info->filename); 163 if (unique_file != -1) 164 file=fdopen(unique_file,"wb"); 165 if ((unique_file == -1) || (file == (FILE *) NULL)) 166 { 167 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", 168 read_info->filename); 169 read_info=DestroyImageInfo(read_info); 170 return((Image *) NULL); 171 } 172 (void) CopyMagickString(filename,image_info->magick,MagickPathExtent); 173 (void) ConcatenateMagickString(filename,":",MagickPathExtent); 174 LocaleLower(filename); 175 (void) ConcatenateMagickString(filename,image_info->filename, 176 MagickPathExtent); 177#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \ 178 !(defined(__MINGW32__) || defined(__MINGW64__)) 179 (void) fclose(file); 180 if (URLDownloadToFile(NULL,filename,read_info->filename,0,NULL) != S_OK) 181 { 182 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 183 filename); 184 (void) RelinquishUniqueFileResource(read_info->filename); 185 read_info=DestroyImageInfo(read_info); 186 return((Image *) NULL); 187 } 188#else 189#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED) 190 if (LocaleCompare(read_info->magick,"ftp") == 0) 191 { 192 void 193 *context; 194 195 xmlNanoFTPInit(); 196 context=xmlNanoFTPNewCtxt(filename); 197 if (context != (void *) NULL) 198 { 199 if (xmlNanoFTPConnect(context) >= 0) 200 (void) xmlNanoFTPGet(context,GetFTPData,(void *) file, 201 (char *) NULL); 202 (void) xmlNanoFTPClose(context); 203 } 204 } 205#endif 206#if defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED) 207 if (LocaleCompare(read_info->magick,"http") == 0) 208 { 209 char 210 buffer[MaxBufferExtent], 211 *type; 212 213 int 214 bytes; 215 216 void 217 *context; 218 219 type=(char *) NULL; 220 context=xmlNanoHTTPMethod(filename,(const char *) NULL, 221 (const char *) NULL,&type,(const char *) NULL,0); 222 if (context != (void *) NULL) 223 { 224 ssize_t 225 count; 226 227 while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0) 228 count=(ssize_t) fwrite(buffer,bytes,1,file); 229 (void) count; 230 xmlNanoHTTPClose(context); 231 xmlFree(type); 232 xmlNanoHTTPCleanup(); 233 } 234 } 235#endif 236 (void) fclose(file); 237#endif 238 *read_info->magick='\0'; 239 image=ReadImage(read_info,exception); 240 (void) RelinquishUniqueFileResource(read_info->filename); 241 read_info=DestroyImageInfo(read_info); 242 if (image != (Image *) NULL) 243 GetPathComponent(image_info->filename,TailPath,image->filename); 244 else 245 { 246 (void) ThrowMagickException(exception,GetMagickModule(),CoderError, 247 "NoDataReturned","`%s'",filename); 248 return((Image *) NULL); 249 } 250 return(GetFirstImageInList(image)); 251} 252 253/* 254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 255% % 256% % 257% % 258% R e g i s t e r U R L I m a g e % 259% % 260% % 261% % 262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 263% 264% RegisterURLImage() adds attributes for the URL image format to 265% the list of supported formats. The attributes include the image format 266% tag, a method to read and/or write the format, whether the format 267% supports the saving of more than one frame to the same file or blob, 268% whether the format supports native in-memory I/O, and a brief 269% description of the format. 270% 271% The format of the RegisterURLImage method is: 272% 273% size_t RegisterURLImage(void) 274% 275*/ 276ModuleExport size_t RegisterURLImage(void) 277{ 278 MagickInfo 279 *entry; 280 281 entry=AcquireMagickInfo("URL","HTTP","Uniform Resource Locator (http://)"); 282#if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \ 283 !(defined(__MINGW32__) || defined(__MINGW64__))) || \ 284 (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_HTTP_ENABLED)) 285 entry->decoder=(DecodeImageHandler *) ReadURLImage; 286#endif 287 entry->format_type=ImplicitFormatType; 288 (void) RegisterMagickInfo(entry); 289 entry=AcquireMagickInfo("URL","HTTPS","Uniform Resource Locator (https://)"); 290#if defined(MAGICKCORE_WINDOWS_SUPPORT) && \ 291 !(defined(__MINGW32__) || defined(__MINGW64__)) 292 entry->decoder=(DecodeImageHandler *) ReadURLImage; 293#endif 294 entry->format_type=ImplicitFormatType; 295 (void) RegisterMagickInfo(entry); 296 entry=AcquireMagickInfo("URL","FTP","Uniform Resource Locator (ftp://)"); 297#if (defined(MAGICKCORE_WINDOWS_SUPPORT) && \ 298 !(defined(__MINGW32__) || defined(__MINGW64__))) || \ 299 (defined(MAGICKCORE_XML_DELEGATE) && defined(LIBXML_FTP_ENABLED)) 300 entry->decoder=(DecodeImageHandler *) ReadURLImage; 301#endif 302 entry->format_type=ImplicitFormatType; 303 (void) RegisterMagickInfo(entry); 304 entry=AcquireMagickInfo("URL","FILE","Uniform Resource Locator (file://)"); 305 entry->decoder=(DecodeImageHandler *) ReadURLImage; 306 entry->format_type=ImplicitFormatType; 307 (void) RegisterMagickInfo(entry); 308 return(MagickImageCoderSignature); 309} 310 311/* 312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 313% % 314% % 315% % 316% U n r e g i s t e r U R L I m a g e % 317% % 318% % 319% % 320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 321% 322% UnregisterURLImage() removes format registrations made by the 323% URL module from the list of supported formats. 324% 325% The format of the UnregisterURLImage method is: 326% 327% UnregisterURLImage(void) 328% 329*/ 330ModuleExport void UnregisterURLImage(void) 331{ 332 (void) UnregisterMagickInfo("HTTP"); 333 (void) UnregisterMagickInfo("FTP"); 334 (void) UnregisterMagickInfo("FILE"); 335} 336