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