Coverage Report

Created: 2026-03-31 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/ora.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                              OOO   RRRR    AAA                              %
7
%                             O   O  R   R  A   A                             %
8
%                             O   O  RRRR   AAAAA                             %
9
%                             O   O  R  R   A   A                             %
10
%                              OOO   R   R  A   A                             %
11
%                                                                             %
12
%                                                                             %
13
%                       Read OpenRaster (.ora) files                          %
14
%                                                                             %
15
%                             OpenRaster spec:                                %
16
%         https://www.freedesktop.org/wiki/Specifications/OpenRaster/         %
17
%                                                                             %
18
%                                Implementer                                  %
19
%                           Christopher Chianelli                             %
20
%                                August 2020                                  %
21
%                                                                             %
22
%                                                                             %
23
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
24
%  dedicated to making software imaging solutions freely available.           %
25
%                                                                             %
26
%  You may not use this file except in compliance with the License.  You may  %
27
%  obtain a copy of the License at                                            %
28
%                                                                             %
29
%    https://imagemagick.org/license/                                         %
30
%                                                                             %
31
%  Unless required by applicable law or agreed to in writing, software        %
32
%  distributed under the License is distributed on an "AS IS" BASIS,          %
33
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
34
%  See the License for the specific language governing permissions and        %
35
%  limitations under the License.                                             %
36
%                                                                             %
37
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
%
39
%
40
*/
41

42
/*
43
  Include declarations.
44
*/
45
#include "MagickCore/studio.h"
46
#include "MagickCore/blob.h"
47
#include "MagickCore/blob-private.h"
48
#include "MagickCore/constitute.h"
49
#include "MagickCore/exception.h"
50
#include "MagickCore/exception-private.h"
51
#include "MagickCore/image.h"
52
#include "MagickCore/image-private.h"
53
#include "MagickCore/list.h"
54
#include "MagickCore/magick.h"
55
#include "MagickCore/memory_.h"
56
#include "MagickCore/module.h"
57
#include "MagickCore/nt-base-private.h"
58
#include "MagickCore/quantum-private.h"
59
#include "MagickCore/static.h"
60
#include "MagickCore/resource_.h"
61
#include "MagickCore/string_.h"
62
#include "MagickCore/utility.h"
63
64
#if defined(MAGICKCORE_ZIP_DELEGATE)
65
#include <zip.h>
66
#endif
67

68
/*
69
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70
%                                                                             %
71
%                                                                             %
72
%                                                                             %
73
%   R e a d O R A I m a g e                                                   %
74
%                                                                             %
75
%                                                                             %
76
%                                                                             %
77
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78
%
79
%  ReadORAImage reads an ORA file in the most basic way possible: by
80
%  reading it as a ZIP File and extracting the mergedimage.png file from it,
81
%  which is then passed to ReadPNGImage.
82
%
83
%  https://www.freedesktop.org/wiki/Specifications/OpenRaster/Draft/FileLayout/
84
%
85
%  The format of the ReadORAImage method is:
86
%
87
%      Image *ReadORAImage(const ImageInfo *image_info,ExceptionInfo *exception)
88
%
89
%  A description of each parameter follows:
90
%
91
%    o image_info: the image info.
92
%
93
%    o exception: return any errors or warnings in this structure.
94
%
95
*/
96
97
#if defined(__cplusplus) || defined(c_plusplus)
98
extern "C" {
99
#endif
100
101
#if defined(__cplusplus) || defined(c_plusplus)
102
}
103
#endif
104
105
#if defined(MAGICKCORE_PNG_DELEGATE) && defined(MAGICKCORE_ZIP_DELEGATE)
106
static Image *ReadORAImage(const ImageInfo *image_info,
107
  ExceptionInfo *exception)
108
{
109
  char
110
    image_data_buffer[8192];
111
112
  const char
113
    *MERGED_IMAGE_PATH = "mergedimage.png";
114
115
  FILE
116
    *file;
117
118
  Image
119
    *image_metadata,
120
    *out_image;
121
122
  ImageInfo
123
    *read_info;
124
125
  int
126
    unique_file,
127
    zip_error;
128
129
  MagickBooleanType
130
    status;
131
132
  struct stat
133
    stat_info;
134
135
  zip_t
136
    *zip_archive;
137
138
  zip_file_t
139
    *merged_image_file;
140
141
  zip_int64_t
142
    read_bytes;
143
144
  zip_uint64_t
145
    offset;
146
147
  image_metadata=AcquireImage(image_info,exception);
148
  read_info=CloneImageInfo(image_info);
149
  SetImageInfoBlob(read_info,(void *) NULL,0);
150
  (void) stat(image_info->filename,&stat_info);
151
  zip_archive=zip_open(image_info->filename,ZIP_RDONLY,&zip_error);
152
  if (zip_archive == NULL)
153
    {
154
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
155
        image_info->filename);
156
      read_info=DestroyImageInfo(read_info);
157
      image_metadata=DestroyImage(image_metadata);
158
      return((Image *) NULL);
159
    }
160
  merged_image_file=zip_fopen(zip_archive,MERGED_IMAGE_PATH,ZIP_FL_UNCHANGED);
161
  if (merged_image_file == NULL)
162
    {
163
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
164
        image_info->filename);
165
      read_info=DestroyImageInfo(read_info);
166
      image_metadata=DestroyImage(image_metadata);
167
      zip_discard(zip_archive);
168
      return((Image *) NULL);
169
    }
170
  /* Get a temporary file to write the mergedimage.png of the ZIP to */
171
  (void) CopyMagickString(read_info->magick,"PNG",MagickPathExtent);
172
  unique_file=AcquireUniqueFileResource(read_info->unique);
173
  (void) CopyMagickString(read_info->filename,read_info->unique,
174
    MagickPathExtent);
175
  file=(FILE *) NULL;
176
  if (unique_file != -1)
177
    file=fdopen(unique_file,"wb");
178
  if ((unique_file == -1) || (file == (FILE *) NULL))
179
    {
180
      ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
181
        read_info->filename);
182
      if (unique_file != -1)
183
        (void) RelinquishUniqueFileResource(read_info->filename);
184
      read_info=DestroyImageInfo(read_info);
185
      image_metadata=DestroyImage(image_metadata);
186
      zip_fclose(merged_image_file);
187
      zip_discard(zip_archive);
188
      return((Image *) NULL);
189
    }
190
  /* Write the uncompressed mergedimage.png to the temporary file */
191
  status=MagickTrue;
192
  offset=0;
193
  while (status != MagickFalse)
194
  {
195
    read_bytes=zip_fread(merged_image_file,image_data_buffer+offset,
196
      sizeof(image_data_buffer)-offset);
197
    if (read_bytes == -1)
198
      status=MagickFalse;
199
    else if (read_bytes == 0)
200
      {
201
        /* Write up to offset of image_data_buffer to temp file */
202
        if (!fwrite(image_data_buffer,1,(size_t) offset,file))
203
          status=MagickFalse;
204
        break;
205
      }
206
    else if (read_bytes == (ssize_t) (sizeof(image_data_buffer)-offset))
207
      {
208
        /* Write the entirely of image_data_buffer to temp file */
209
        if (!fwrite(image_data_buffer,1,sizeof(image_data_buffer),file))
210
          status=MagickFalse;
211
        else
212
          offset=0;
213
      }
214
    else
215
      offset+=(zip_uint64_t) read_bytes;
216
  }
217
  (void) fclose(file);
218
  (void) zip_fclose(merged_image_file);
219
  (void) zip_discard(zip_archive);
220
  if (status == MagickFalse)
221
    {
222
      ThrowFileException(exception,CoderError,"UnableToReadImageData",
223
          read_info->filename);
224
      (void) RelinquishUniqueFileResource(read_info->filename);
225
      read_info=DestroyImageInfo(read_info);
226
      image_metadata=DestroyImage(image_metadata);
227
      return((Image *) NULL);
228
    }
229
  /* Delegate to ReadImage to read mergedimage.png */
230
  out_image=ReadImage(read_info,exception);
231
  (void) RelinquishUniqueFileResource(read_info->filename);
232
  read_info=DestroyImageInfo(read_info);
233
  /* Update fields of image from fields of png_image */
234
  if (out_image != NULL)
235
    {
236
      (void) CopyMagickString(out_image->filename,image_metadata->filename,
237
        MagickPathExtent);
238
      (void) CopyMagickString(out_image->magick_filename,
239
        image_metadata->magick_filename,MagickPathExtent);
240
      out_image->timestamp=time(&stat_info.st_mtime);
241
      (void) CopyMagickString(out_image->magick,image_metadata->magick,
242
        MagickPathExtent);
243
      out_image->extent=(MagickSizeType) stat_info.st_size;
244
    }
245
  image_metadata=DestroyImage(image_metadata);
246
  return(out_image);
247
}
248
#endif /* MAGICKCORE_ZIP_DELEGATE && MAGICKCORE_PNG_DELEGATE */
249

250
/*
251
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
%                                                                             %
253
%                                                                             %
254
%                                                                             %
255
%   R e g i s t e r O R A I m a g e                                           %
256
%                                                                             %
257
%                                                                             %
258
%                                                                             %
259
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260
%
261
%  RegisterORAImage() adds attributes for the ORA image format to
262
%  the list of supported formats.  The attributes include the image format
263
%  tag, a method to read and/or write the format, whether the format
264
%  supports the saving of more than one frame to the same file or blob,
265
%  whether the format supports native in-memory I/O, and a brief
266
%  description of the format.
267
%
268
%  The format of the RegisterORAImage method is:
269
%
270
%      size_t RegisterORAImage(void)
271
%
272
*/
273
ModuleExport size_t RegisterORAImage(void)
274
8
{
275
8
  MagickInfo
276
8
    *entry;
277
278
8
  entry=AcquireMagickInfo("ORA","ORA","OpenRaster format");
279
280
#if defined(MAGICKCORE_ZIP_DELEGATE) && defined(MAGICKCORE_PNG_DELEGATE)
281
  entry->decoder=(DecodeImageHandler *) ReadORAImage;
282
#endif
283
8
  entry->flags^=CoderBlobSupportFlag;
284
8
  entry->flags|=CoderDecoderSeekableStreamFlag;
285
8
  entry->format_type=ExplicitFormatType;
286
8
  (void) RegisterMagickInfo(entry);
287
8
  return(MagickImageCoderSignature);
288
8
}
289

290
/*
291
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292
%                                                                             %
293
%                                                                             %
294
%                                                                             %
295
%   U n r e g i s t e r O R A I m a g e                                       %
296
%                                                                             %
297
%                                                                             %
298
%                                                                             %
299
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300
%
301
%  UnregisterORAImage() removes format registrations made by the
302
%  ORA module from the list of supported formats.
303
%
304
%  The format of the UnregisterORAImage method is:
305
%
306
%      UnregisterORAImage(void)
307
%
308
*/
309
ModuleExport void UnregisterORAImage(void)
310
0
{
311
0
  (void) UnregisterMagickInfo("ORA");
312
0
}