Coverage Report

Created: 2023-06-07 06:20

/src/mupdf/source/xps/xps-resource.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2021 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
#include "xps-imp.h"
25
26
#include <string.h>
27
28
static fz_xml *
29
xps_lookup_resource(fz_context *ctx, xps_document *doc, xps_resource *dict, char *name, char **urip)
30
0
{
31
0
  xps_resource *head, *node;
32
0
  for (head = dict; head; head = head->parent)
33
0
  {
34
0
    for (node = head; node; node = node->next)
35
0
    {
36
0
      if (!strcmp(node->name, name))
37
0
      {
38
0
        if (urip && head->base_uri)
39
0
          *urip = head->base_uri;
40
0
        return node->data;
41
0
      }
42
0
    }
43
0
  }
44
0
  return NULL;
45
0
}
46
47
static fz_xml *
48
xps_parse_resource_reference(fz_context *ctx, xps_document *doc, xps_resource *dict, char *att, char **urip)
49
0
{
50
0
  char name[1024];
51
0
  char *s;
52
53
0
  if (strstr(att, "{StaticResource ") != att)
54
0
    return NULL;
55
56
0
  fz_strlcpy(name, att + 16, sizeof name);
57
0
  s = strrchr(name, '}');
58
0
  if (s)
59
0
    *s = 0;
60
61
0
  return xps_lookup_resource(ctx, doc, dict, name, urip);
62
0
}
63
64
void
65
xps_resolve_resource_reference(fz_context *ctx, xps_document *doc, xps_resource *dict,
66
    char **attp, fz_xml **tagp, char **urip)
67
0
{
68
0
  if (*attp)
69
0
  {
70
0
    fz_xml *rsrc = xps_parse_resource_reference(ctx, doc, dict, *attp, urip);
71
0
    if (rsrc)
72
0
    {
73
0
      *attp = NULL;
74
0
      *tagp = rsrc;
75
0
    }
76
0
  }
77
0
}
78
79
static xps_resource *
80
xps_parse_remote_resource_dictionary(fz_context *ctx, xps_document *doc, char *base_uri, char *source_att)
81
0
{
82
0
  char part_name[1024];
83
0
  char part_uri[1024];
84
0
  xps_part *part;
85
0
  xps_resource *dict = NULL;
86
0
  fz_xml_doc *xml = NULL;
87
0
  char *s;
88
89
0
  fz_var(xml);
90
91
  /* External resource dictionaries MUST NOT reference other resource dictionaries */
92
0
  xps_resolve_url(ctx, doc, part_name, base_uri, source_att, sizeof part_name);
93
94
0
  part = xps_read_part(ctx, doc, part_name);
95
0
  fz_try(ctx)
96
0
  {
97
0
    xml = fz_parse_xml(ctx, part->data, 0);
98
0
    if (!fz_xml_is_tag(fz_xml_root(xml), "ResourceDictionary"))
99
0
      fz_throw(ctx, FZ_ERROR_GENERIC, "expected ResourceDictionary element");
100
101
0
    fz_strlcpy(part_uri, part_name, sizeof part_uri);
102
0
    s = strrchr(part_uri, '/');
103
0
    if (s)
104
0
      s[1] = 0;
105
106
0
    dict = xps_parse_resource_dictionary(ctx, doc, part_uri, fz_xml_root(xml));
107
0
    if (dict)
108
0
    {
109
0
      dict->base_xml = xml; /* pass on ownership */
110
0
      xml = NULL;
111
0
    }
112
0
  }
113
0
  fz_always(ctx)
114
0
  {
115
0
    xps_drop_part(ctx, doc, part);
116
0
    fz_drop_xml(ctx, xml);
117
0
  }
118
0
  fz_catch(ctx)
119
0
  {
120
0
    fz_rethrow(ctx);
121
0
  }
122
123
0
  return dict;
124
0
}
125
126
xps_resource *
127
xps_parse_resource_dictionary(fz_context *ctx, xps_document *doc, char *base_uri, fz_xml *root)
128
0
{
129
0
  xps_resource *head;
130
0
  xps_resource *entry;
131
0
  fz_xml *node;
132
0
  char *source;
133
0
  char *key;
134
135
0
  source = fz_xml_att(root, "Source");
136
0
  if (source)
137
0
    return xps_parse_remote_resource_dictionary(ctx, doc, base_uri, source);
138
139
0
  head = NULL;
140
141
0
  for (node = fz_xml_down(root); node; node = fz_xml_next(node))
142
0
  {
143
0
    key = fz_xml_att(node, "x:Key");
144
0
    if (key)
145
0
    {
146
0
      entry = fz_malloc_struct(ctx, xps_resource);
147
0
      entry->name = key;
148
0
      entry->base_uri = NULL;
149
0
      entry->base_xml = NULL;
150
0
      entry->data = node;
151
0
      entry->next = head;
152
0
      entry->parent = NULL;
153
0
      head = entry;
154
0
    }
155
0
  }
156
157
0
  if (head)
158
0
  {
159
0
    fz_try(ctx)
160
0
      head->base_uri = fz_strdup(ctx, base_uri);
161
0
    fz_catch(ctx)
162
0
    {
163
0
      fz_free(ctx, entry);
164
0
      fz_rethrow(ctx);
165
0
    }
166
0
  }
167
168
0
  return head;
169
0
}
170
171
void
172
xps_drop_resource_dictionary(fz_context *ctx, xps_document *doc, xps_resource *dict)
173
0
{
174
0
  xps_resource *next;
175
0
  while (dict)
176
0
  {
177
0
    next = dict->next;
178
0
    fz_drop_xml(ctx, dict->base_xml);
179
0
    fz_free(ctx, dict->base_uri);
180
0
    fz_free(ctx, dict);
181
0
    dict = next;
182
0
  }
183
0
}