Coverage Report

Created: 2025-07-23 08:18

/src/graphicsmagick/coders/url.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
% Copyright (C) 2003-2022 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
%
5
% This program is covered by multiple licenses, which are described in
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8
%
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10
%                                                                             %
11
%                                                                             %
12
%                                                                             %
13
%                            U   U  RRRR   L                                  %
14
%                            U   U  R   R  L                                  %
15
%                            U   U  RRRR   L                                  %
16
%                            U   U  R R    L                                  %
17
%                             UUU   R  R   LLLLL                              %
18
%                                                                             %
19
%                                                                             %
20
%                       Retrieve An Image Via a URL.                          %
21
%                                                                             %
22
%                                                                             %
23
%                              Software Design                                %
24
%                                John Cristy                                  %
25
%                              Bill Radcliffe                                 %
26
%                                March 2000                                   %
27
%                                                                             %
28
%                                                                             %
29
%                                                                             %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%
32
%
33
*/
34

35
/*
36
  Include declarations.
37
*/
38
#include "magick/studio.h"
39
#if defined(HasXML)
40
#include "magick/blob.h"
41
#include "magick/confirm_access.h"
42
#include "magick/constitute.h"
43
#include "magick/magick.h"
44
#include "magick/tempfile.h"
45
#include "magick/utility.h"
46
#if defined(MSWINDOWS)
47
#  if defined(__MINGW32__)
48
#    if !defined(_MSC_VER)
49
#      define _MSC_VER 1200
50
#    endif
51
#  else
52
#    include <win32config.h>
53
#  endif
54
#endif
55
#include <libxml/xmlversion.h>
56
#include <libxml/parser.h>
57
#include <libxml/xmlmemory.h>
58
#if defined(LIBXML_FTP_ENABLED)
59
#  if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT
60
#    include <libxml/nanoftp.h>
61
#  endif /* defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT */
62
#endif /* if defined(LIBXML_FTP_ENABLED) */
63
#if defined(LIBXML_HTTP_ENABLED)
64
#  if defined(HAVE_XMLNANOHTTPOPEN) && HAVE_XMLNANOHTTPOPEN
65
#    include <libxml/nanohttp.h>
66
#  endif /* defined(HAVE_XMLNANOHTTPOPEN) && HAVE_XMLNANOHTTPOPEN */
67
#endif /* if defined(LIBXML_HTTP_ENABLED) */
68

69
/*
70
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71
%                                                                             %
72
%                                                                             %
73
%                                                                             %
74
%   R e a d U R L I m a g e                                                   %
75
%                                                                             %
76
%                                                                             %
77
%                                                                             %
78
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79
%
80
%  Method ReadURLImage retrieves an image via a URL, decodes the image, and
81
%   returns it.  It allocates the memory necessary for the new Image structure
82
%  and returns a pointer to the new image.
83
%
84
%  The format of the ReadURLImage method is:
85
%
86
%      Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
87
%
88
%  A description of each parameter follows:
89
%
90
%    o image:  Method ReadURLImage returns a pointer to the image after
91
%      reading. A null image is returned if there is a memory shortage or if
92
%      the image cannot be read.
93
%
94
%    o image_info: Specifies a pointer to a ImageInfo structure.
95
%
96
%    o exception: return any errors or warnings in this structure.
97
%
98
%
99
*/
100
101
#if defined(__cplusplus) || defined(c_plusplus)
102
extern "C" {
103
#endif
104
105
#if defined(LIBXML_FTP_ENABLED)
106
#if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT
107
static void GetFTPData(void *userdata,const char *data,int length)
108
{
109
  FILE
110
    *file;
111
112
  file=(FILE *) userdata;
113
  if (file == (FILE *) NULL)
114
    return;
115
  if (length <= 0)
116
    return;
117
  (void) fwrite(data,length,1,file);
118
}
119
#endif /* if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT */
120
#endif /* if defined(LIBXML_FTP_ENABLED) */
121
122
#if defined(__cplusplus) || defined(c_plusplus)
123
}
124
#endif
125
126
static Image *ReadURLImage(const ImageInfo *image_info,ExceptionInfo *exception)
127
22
{
128
22
#define MaxBufferExtent  8192
129
130
22
  char
131
22
    filename[MaxTextExtent];
132
133
22
  FILE
134
22
    *file;
135
136
22
  Image
137
22
    *image;
138
139
22
  ImageInfo
140
22
    *clone_info;
141
142
22
  ConfirmAccessMode
143
22
    access_mode=UndefinedConfirmAccessMode;
144
145
22
  image=(Image *) NULL;
146
147
22
  if (LocaleCompare(image_info->magick,"ftp") == 0)
148
0
    access_mode=URLGetFTPConfirmAccessMode;
149
22
  else if (LocaleCompare(image_info->magick,"http") == 0)
150
0
    access_mode=URLGetHTTPConfirmAccessMode;
151
22
  else if (LocaleCompare(image_info->magick,"file") == 0)
152
22
    access_mode=URLGetFileConfirmAccessMode;
153
154
155
  /* Attempt to re-compose original URL */
156
22
  (void) strlcpy(filename,image_info->magick,MaxTextExtent);
157
22
  LocaleLower(filename);
158
22
  (void) strlcat(filename,":",MaxTextExtent);
159
22
  (void) strlcat(filename,image_info->filename,MaxTextExtent);
160
161
22
  if (MagickConfirmAccess(access_mode,filename,exception)
162
22
      == MagickFail)
163
0
    return image;
164
165
22
  clone_info=CloneImageInfo(image_info);
166
22
  if (LocaleCompare(clone_info->magick,"file") == 0)
167
22
    {
168
      /* Skip over "//" at start of parsed filename */
169
22
      (void) strlcpy(clone_info->filename,image_info->filename+2,
170
22
                     sizeof(clone_info->filename));
171
22
      clone_info->magick[0]='\'';
172
22
      image=ReadImage(clone_info,exception);
173
22
    }
174
0
  else
175
0
    {
176
0
      clone_info->blob=(void *) NULL;
177
0
      clone_info->length=0;
178
0
      file=AcquireTemporaryFileStream(clone_info->filename,BinaryFileIOMode);
179
0
      if (file == (FILE *) NULL)
180
0
        {
181
0
          (void) strlcpy(filename,clone_info->filename,sizeof(filename));
182
0
          DestroyImageInfo(clone_info);
183
0
          ThrowReaderTemporaryFileException(filename);
184
0
        }
185
0
      if (LocaleCompare(clone_info->magick,"http") == 0)
186
0
        {
187
#if defined(LIBXML_HTTP_ENABLED)
188
#if defined(HAVE_XMLNANOHTTPOPEN) && HAVE_XMLNANOHTTPOPEN
189
          char
190
            buffer[MaxBufferExtent];
191
192
          void
193
            *context;
194
195
          char
196
            *type;
197
198
          int
199
            bytes;
200
201
          type=(char *) NULL;
202
          context=xmlNanoHTTPOpen(filename,&type);
203
          if (context != (void *) NULL)
204
            {
205
              while ((bytes=xmlNanoHTTPRead(context,buffer,MaxBufferExtent)) > 0)
206
                (void) fwrite(buffer,bytes,1,file);
207
              xmlNanoHTTPClose(context);
208
              xmlFree(type);
209
              xmlNanoHTTPCleanup();
210
            }
211
#endif /* if defined(HAVE_XMLNANOHTTPOPEN) && HAVE_XMLNANOHTTPOPEN */
212
#endif /* if defined(LIBXML_FTP_ENABLED) */
213
0
        }
214
0
      else if (LocaleCompare(clone_info->magick,"ftp") == 0)
215
0
        {
216
#if defined(LIBXML_FTP_ENABLED)
217
#if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT
218
          void
219
            *context;
220
221
          xmlNanoFTPInit();
222
          context=xmlNanoFTPNewCtxt(filename);
223
          if (context != (void *) NULL)
224
            {
225
              if (xmlNanoFTPConnect(context) >= 0)
226
                (void) xmlNanoFTPGet(context,GetFTPData,(void *) file,
227
                                     (char *) NULL);
228
              (void) xmlNanoFTPClose(context);
229
            }
230
#endif /* if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT */
231
#endif /* if defined(LIBXML_FTP_ENABLED) */
232
0
        }
233
0
      (void) fclose(file);
234
0
      if (!IsAccessibleAndNotEmpty(clone_info->filename))
235
0
        {
236
0
          (void) LiberateTemporaryFile(clone_info->filename);
237
0
          ThrowException(exception,CoderError,NoDataReturned,filename);
238
0
        }
239
0
      else
240
0
        {
241
0
          *clone_info->magick='\0';
242
0
          image=ReadImage(clone_info,exception);
243
0
        }
244
0
      (void) LiberateTemporaryFile(clone_info->filename);
245
0
    }
246
22
  DestroyImageInfo(clone_info);
247
22
  return(image);
248
22
}
249
#endif /* defined(HasXML) */
250

251
/*
252
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253
%                                                                             %
254
%                                                                             %
255
%                                                                             %
256
%   R e g i s t e r U R L I m a g e                                           %
257
%                                                                             %
258
%                                                                             %
259
%                                                                             %
260
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
%
262
%  Method RegisterURLImage adds attributes for the URL image format to
263
%  the list of supported formats.  The attributes include the image format
264
%  tag, a method to read and/or write the format, whether the format
265
%  supports the saving of more than one frame to the same file or blob,
266
%  whether the format supports native in-memory I/O, and a brief
267
%  description of the format.
268
%
269
%  The format of the RegisterURLImage method is:
270
%
271
%      RegisterURLImage(void)
272
%
273
*/
274
ModuleExport void RegisterURLImage(void)
275
1
{
276
1
#if defined(HasXML)
277
1
  MagickInfo
278
1
    *entry;
279
280
  /* HTTP URLs are not encouraged on the Internet */
281
#if defined(LIBXML_HTTP_ENABLED)
282
#if defined(HAVE_XMLNANOHTTPOPEN) && HAVE_XMLNANOHTTPOPEN
283
  entry=SetMagickInfo("HTTP");
284
  entry->decoder=(DecoderHandler) ReadURLImage;
285
  entry->description="Uniform Resource Locator (http://)";
286
  entry->module="URL";
287
  entry->extension_treatment=IgnoreExtensionTreatment;
288
  entry->coder_class=UnstableCoderClass;
289
  (void) RegisterMagickInfo(entry);
290
#endif /* if defined(HAVE_XMLNANOHTTPOPEN) && HAVE_XMLNANOHTTPOPEN */
291
#endif /* if defined(LIBXML_HTTP_ENABLED) */
292
293
  /* FTP URLs have been deprecated for quite some time already */
294
#if defined(LIBXML_FTP_ENABLED)
295
#if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT
296
  entry=SetMagickInfo("FTP");
297
  entry->decoder=(DecoderHandler) ReadURLImage;
298
  entry->description="Uniform Resource Locator (ftp://)";
299
  entry->module="URL";
300
  entry->extension_treatment=IgnoreExtensionTreatment;
301
  entry->coder_class=UnstableCoderClass;
302
  (void) RegisterMagickInfo(entry);
303
#endif /* if defined(HAVE_XMLNANOFTPNEWCTXT) && HAVE_XMLNANOFTPNEWCTXT */
304
#endif /* if defined(LIBXML_FTP_ENABLED) */
305
306
1
  entry=SetMagickInfo("FILE");
307
1
  entry->decoder=(DecoderHandler) ReadURLImage;
308
1
  entry->description="Uniform Resource Locator (file://)";
309
1
  entry->extension_treatment=IgnoreExtensionTreatment;
310
1
  entry->module="URL";
311
1
  entry->coder_class=StableCoderClass;
312
1
  (void) RegisterMagickInfo(entry);
313
1
#endif /* defined(HasXML) */
314
1
}
315

316
/*
317
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318
%                                                                             %
319
%                                                                             %
320
%                                                                             %
321
%   U n r e g i s t e r U R L I m a g e                                       %
322
%                                                                             %
323
%                                                                             %
324
%                                                                             %
325
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326
%
327
%  Method UnregisterURLImage removes format registrations made by the
328
%  URL module from the list of supported formats.
329
%
330
%  The format of the UnregisterURLImage method is:
331
%
332
%      UnregisterURLImage(void)
333
%
334
*/
335
ModuleExport void UnregisterURLImage(void)
336
0
{
337
0
#if defined(HasXML)
338
0
  (void) UnregisterMagickInfo("HTTP");
339
0
  (void) UnregisterMagickInfo("FTP");
340
0
  (void) UnregisterMagickInfo("FILE");
341
0
#endif /* defined(HasXML) */
342
0
}