Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
uri.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
/*
7 * Authors: see git history
8 *
9 * Copyright (C) 2006-2024 Authors
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13#include <cstring>
14#include <glib.h>
15#include <optional>
16
17#include "uri.h"
18
19std::string extract_uri(char const *s, char const **endptr)
20{
21 std::string result;
22
23 if (!s)
24 return result;
25
26 gchar const *sb = s;
27 if ( strlen(sb) < 4 || strncmp(sb, "url", 3) != 0 ) {
28 return result;
29 }
30
31 sb += 3;
32
33 if ( endptr ) {
34 *endptr = nullptr;
35 }
36
37 // This first whitespace technically is not allowed.
38 // Just left in for now for legacy behavior.
39 while ( ( *sb == ' ' ) ||
40 ( *sb == '\t' ) )
41 {
42 sb++;
43 }
44
45 if ( *sb == '(' ) {
46 sb++;
47 while ( ( *sb == ' ' ) ||
48 ( *sb == '\t' ) )
49 {
50 sb++;
51 }
52
53 gchar delim = ')';
54 if ( (*sb == '\'' || *sb == '"') ) {
55 delim = *sb;
56 sb++;
57 }
58
59 if (!*sb) {
60 return result;
61 }
62
63 gchar const* se = sb;
64 while ( *se && (*se != delim) ) {
65 se++;
66 }
67
68 // we found the delimiter
69 if ( *se ) {
70 if ( delim == ')' ) {
71 if ( endptr ) {
72 *endptr = se + 1;
73 }
74
75 // back up for any trailing whitespace
76 while (se > sb && g_ascii_isspace(se[-1]))
77 {
78 se--;
79 }
80
81 result = std::string(sb, se);
82 } else {
83 gchar const* tail = se + 1;
84 while ( ( *tail == ' ' ) ||
85 ( *tail == '\t' ) )
86 {
87 tail++;
88 }
89 if ( *tail == ')' ) {
90 if ( endptr ) {
91 *endptr = tail + 1;
92 }
93 result = std::string(sb, se);
94 }
95 }
96 }
97 }
98
99 return result;
100}
101
102std::optional<std::string> try_extract_uri(const char* url) {
103 auto link = extract_uri(url);
104 return link.empty() ? std::nullopt : std::make_optional(link);
105}
106
107std::optional<std::string> try_extract_uri_id(const char *url) {
108 if (auto ret = try_extract_uri(url)) {
109 if (!ret->empty() && (*ret)[0] == '#') {
110 ret->erase(0, 1);
111 return ret;
112 }
113 }
114 return std::nullopt;
115}
116
117std::tuple<char const *, Base64Data> extract_uri_data(char const *uri_data)
118{
119 bool data_is_base64 = false;
120 bool data_is_image = false;
121 bool data_is_svg = false;
122 bool data_has_mime = false;
123
124 gchar const *data = uri_data;
125
126 if ((*data) && strncmp(data, "data:", 5) == 0) {
127 data += 5;
128 }
129
130 while (*data) {
131 if (strncmp(data, "base64", 6) == 0) {
132 /* base64-encoding */
133 data_is_base64 = true;
134 // Illustrator produces embedded images without MIME type, so we assume it's image if no mime found
135 data_is_image = !data_has_mime;
136 data += 6;
137 }
138 else if (strncmp(data, "image/png", 9) == 0
139 || strncmp(data, "image/jpg", 9) == 0
140 || strncmp(data, "image/jp2", 9) == 0
141 || strncmp(data, "image/bmp", 9) == 0) {
142 /* PNGi, JPEG, JPEG200, BMP image */
143 data_is_image = true;
144 data += 9;
145 }
146 else if (strncmp(data, "image/jpeg", 10) == 0
147 || strncmp(data, "image/tiff", 10) == 0) {
148 /* JPEG, TIFF image */
149 data_is_image = true;
150 data += 10;
151 }
152 else if (strncmp(data, "image/svg+xml", 13) == 0) {
153 /* SVG image */
154 data_is_svg = true;
155 data_is_image = true;
156 data += 13;
157 }
158 else { /* unrecognized option; skip it */
159 while (*data) {
160 if (((*data) == ';') || ((*data) == ',')) {
161 break;
162 }
163 if ((*data) == '/') {
164 data_has_mime = true;
165 }
166 data++;
167 }
168 }
169 if ((*data) == ';') {
170 data++;
171 continue;
172 }
173 if ((*data) == ',') {
174 data++;
175 break;
176 }
177 }
178 if (data_is_base64 && data_is_image) {
179 return {data, data_is_svg ? Base64Data::SVG : Base64Data::RASTER};
180 }
181 // No other data format yet
182 return std::tuple{data, Base64Data::NONE};
183}
184
185
186/*
187 Local Variables:
188 mode:c++
189 c-file-style:"stroustrup"
190 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
191 indent-tabs-mode:nil
192 fill-column:99
193 End:
194*/
195// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Css & result
static const Point data[]
std::tuple< char const *, Base64Data > extract_uri_data(char const *uri_data)
Attempt to extract the data in a data uri, but does not decode the base64.
Definition uri.cpp:117
std::string extract_uri(char const *s, char const **endptr)
Parse functional URI notation, as per 4.3.4 of CSS 2.1.
Definition uri.cpp:19
std::optional< std::string > try_extract_uri_id(const char *url)
Try extracting the object id from "url(#obj_id)" string using extract_uri.
Definition uri.cpp:107
std::optional< std::string > try_extract_uri(const char *url)
Try extracting URI from "url(xyz)" string using extract_uri.
Definition uri.cpp:102