uri.h 5.98 KB
Newer Older
Max Gaukler's avatar
Max Gaukler committed
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
MenTaLguY's avatar
MenTaLguY committed
3
4
5
6
7
8
 * Authors:
 *   MenTaLguY <mental@rydia.net>
 *   Jon A. Cruz <jon@joncruz.org>
 *
 * Copyright (C) 2003 MenTaLguY
 *
Max Gaukler's avatar
Max Gaukler committed
9
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
MenTaLguY's avatar
MenTaLguY committed
10
11
12
13
14
15
 */

#ifndef INKSCAPE_URI_H
#define INKSCAPE_URI_H

#include <libxml/uri.h>
16
#include <memory>
17
#include <string>
MenTaLguY's avatar
MenTaLguY committed
18
19
20

namespace Inkscape {

21
22
/**
 * Represents an URI as per RFC 2396.
Thomas Holder's avatar
Thomas Holder committed
23
24
25
26
27
28
29
30
31
32
33
 *
 * Typical use-cases of this class:
 * - converting between relative and absolute URIs
 * - converting URIs to/from filenames (alternative: Glib functions, but those only handle absolute paths)
 * - generic handling of data/file/http URIs (e.g. URI::getContents and URI::getMimeType)
 *
 * Wraps libxml2's URI functions. Direct usage of libxml2's C-API is discouraged if favor of
 * Inkscape::URI. (At the time of writing this, no de-factor standard C++ URI library exists, so
 * wrapping libxml2 seems like a good solution)
 *
 * Implementation detail: Immutable type, copies share a ref-counted data pointer.
34
 */
MenTaLguY's avatar
MenTaLguY committed
35
36
class URI {
public:
37

38
39
40
    /* Blank constructor */
    URI();

41
42
43
44
    /**
     * Constructor from a C-style ASCII string.
     *
     * @param preformed Properly quoted C-style string to be represented.
Thomas Holder's avatar
Thomas Holder committed
45
46
47
     * @param baseuri If @a preformed is a relative URI, use @a baseuri to make it absolute
     *
     * @throw MalformedURIException
48
     */
Thomas Holder's avatar
Thomas Holder committed
49
50
    explicit URI(char const *preformed, char const *baseuri = nullptr);
    explicit URI(char const *preformed, URI const &baseuri);
51
52
53
54
55
56

    /**
     * Determines if the URI represented is an 'opaque' URI.
     *
     * @return \c true if the URI is opaque, \c false if hierarchial.
     */
57
    bool isOpaque() const;
58
59
60
61

    /**
     * Determines if the URI represented is 'relative' as per RFC 2396.
     *
Unknown's avatar
Unknown committed
62
     * Relative URI references are distinguished by not beginning with a
63
64
65
66
     * scheme name.
     *
     * @return \c true if the URI is relative, \c false if it is absolute.
     */
67
    bool isRelative() const;
68
69
70
71

    /**
     * Determines if the relative URI represented is a 'net-path' as per RFC 2396.
     *
Thomas Holder's avatar
Thomas Holder committed
72
     * A net-path is one that starts with "//".
73
74
75
     *
     * @return \c true if the URI is relative and a net-path, \c false otherwise.
     */
76
    bool isNetPath() const;
77
78
79
80
81
82
83
84

    /**
     * Determines if the relative URI represented is a 'relative-path' as per RFC 2396.
     *
     * A relative-path is one that starts with no slashes.
     *
     * @return \c true if the URI is relative and a relative-path, \c false otherwise.
     */
85
    bool isRelativePath() const;
86
87
88
89

    /**
     * Determines if the relative URI represented is a 'absolute-path' as per RFC 2396.
     *
Thomas Holder's avatar
Thomas Holder committed
90
     * An absolute-path is one that starts with a single "/".
91
92
93
     *
     * @return \c true if the URI is relative and an absolute-path, \c false otherwise.
     */
94
    bool isAbsolutePath() const;
95

96
97
98
    /**
     * Return the scheme, e.g.\ "http", or \c NULL if this is not an absolute URI.
     */
99
    const char *getScheme() const;
100

101
102
103
104
105
106
107
    /**
     * Return the path.
     *
     * Example: "http://host/foo/bar?query#frag" -> "/foo/bar"
     *
     * For an opaque URI, this is identical to getOpaque()
     */
108
    const char *getPath() const;
109

110
111
112
    /**
     * Return the query, which is the part between "?" and the optional fragment hash ("#")
     */
113
    const char *getQuery() const;
114

115
116
117
    /**
     * Return the fragment, which is everything after "#"
     */
118
    const char *getFragment() const;
119

120
121
122
123
    /**
     * For an opaque URI, return everything between the scheme colon (":") and the optional
     * fragment hash ("#"). For non-opaque URIs, return NULL.
     */
124
    const char *getOpaque() const;
MenTaLguY's avatar
MenTaLguY committed
125

126
127
128
    /**
     * Construct a "file" URI from an absolute filename.
     */
129
    static URI from_native_filename(char const *path);
130

Thomas Holder's avatar
Thomas Holder committed
131
132
133
134
135
136
137
138
139
140
    /**
     * URI of a local directory. The URI path will end with a slash.
     */
    static URI from_dirname(char const *path);

    /**
     * Convenience function for the common use case given a xlink:href attribute and a local
     * directory as the document base. Returns an empty URI on failure.
     */
    static URI from_href_and_basedir(char const *href, char const *basedir);
MenTaLguY's avatar
MenTaLguY committed
141

Thomas Holder's avatar
Thomas Holder committed
142
143
144
    /**
     * Convert this URI to a native filename.
     *
145
146
     * Discards the fragment identifier.
     *
Thomas Holder's avatar
Thomas Holder committed
147
148
149
     * @throw Glib::ConvertError If this is not a "file" URI
     */
    std::string toNativeFilename() const;
150

151
    /**
Thomas Holder's avatar
Thomas Holder committed
152
153
154
155
156
157
158
159
160
161
162
163
164
     * Return the string representation of this URI
     *
     * @param baseuri Return a relative path if this URI shares protocol and host with @a baseuri
     */
    std::string str(char const *baseuri = nullptr) const;

    /**
     * Get the MIME type (e.g.\ "image/png")
     */
    std::string getMimeType() const;

    /**
     * Return the contents of the file
Thomas Holder's avatar
Thomas Holder committed
165
166
     *
     * @throw Glib::Error If the URL can't be read
Thomas Holder's avatar
Thomas Holder committed
167
168
169
170
171
172
173
174
175
176
     */
    std::string getContents() const;

    /**
     * Return a CSS formatted url value
     *
     * @param baseuri Return a relative path if this URI shares protocol and host with @a baseuri
     */
    std::string cssStr(char const *baseuri = nullptr) const {
        return "url(" + str(baseuri) + ")";
177
178
    }

Thomas Holder's avatar
Thomas Holder committed
179
180
181
182
183
    /**
     * True if the scheme equals the given string (not case sensitive)
     */
    bool hasScheme(const char *scheme) const;

MenTaLguY's avatar
MenTaLguY committed
184
private:
185
186
187
188
189
    std::shared_ptr<xmlURI> m_shared;

    void init(xmlURI *ptr) { m_shared.reset(ptr, xmlFreeURI); }

    xmlURI *_xmlURIPtr() const { return m_shared.get(); }
MenTaLguY's avatar
MenTaLguY committed
190
191
};

192
193
194
195
196
197
198
199
200
201
202
/**
 * Unescape the UTF-8 parts of the given URI.
 *
 * Does not decode non-UTF-8 escape sequences (e.g. reserved ASCII characters).
 * Does not do any IDN (internationalized domain name) decoding.
 *
 * @param uri URI or part of a URI
 * @return IRI equivalent of \c uri
 */
std::string uri_to_iri(const char *uri);

MenTaLguY's avatar
MenTaLguY committed
203
204
205
206
207
208
209
210
211
212
213
214
215
}  /* namespace Inkscape */

#endif

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
216
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :