summaryrefslogtreecommitdiffstats
path: root/src/object/uri.h
blob: 381adec58cf3171d6f6aef9f71fe8d0ea91f3226 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Authors:
 *   MenTaLguY <mental@rydia.net>
 *   Jon A. Cruz <jon@joncruz.org>
 *
 * Copyright (C) 2003 MenTaLguY
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef INKSCAPE_URI_H
#define INKSCAPE_URI_H

#include <libxml/uri.h>
#include <memory>
#include <string>

namespace Inkscape {

/**
 * Represents an URI as per RFC 2396.
 *
 * 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.
 */
class URI {
public:

    /* Blank constructor */
    URI();

    /**
     * Constructor from a C-style ASCII string.
     *
     * @param preformed Properly quoted C-style string to be represented.
     * @param baseuri If @a preformed is a relative URI, use @a baseuri to make it absolute
     *
     * @throw MalformedURIException
     */
    explicit URI(char const *preformed, char const *baseuri = nullptr);
    explicit URI(char const *preformed, URI const &baseuri);

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

    /**
     * Determines if the URI represented is 'relative' as per RFC 2396.
     *
     * Relative URI references are distinguished by not beginning with a
     * scheme name.
     *
     * @return \c true if the URI is relative, \c false if it is absolute.
     */
    bool isRelative() const;

    /**
     * Determines if the relative URI represented is a 'net-path' as per RFC 2396.
     *
     * A net-path is one that starts with "//".
     *
     * @return \c true if the URI is relative and a net-path, \c false otherwise.
     */
    bool isNetPath() const;

    /**
     * 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.
     */
    bool isRelativePath() const;

    /**
     * Determines if the relative URI represented is a 'absolute-path' as per RFC 2396.
     *
     * An absolute-path is one that starts with a single "/".
     *
     * @return \c true if the URI is relative and an absolute-path, \c false otherwise.
     */
    bool isAbsolutePath() const;

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

    /**
     * Return the path.
     *
     * Example: "http://host/foo/bar?query#frag" -> "/foo/bar"
     *
     * For an opaque URI, this is identical to getOpaque()
     */
    const char *getPath() const;

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

    /**
     * Return the fragment, which is everything after "#"
     */
    const char *getFragment() const;

    /**
     * For an opaque URI, return everything between the scheme colon (":") and the optional
     * fragment hash ("#"). For non-opaque URIs, return NULL.
     */
    const char *getOpaque() const;

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

    /**
     * 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);

    /**
     * Convert this URI to a native filename.
     *
     * Discards the fragment identifier.
     *
     * @throw Glib::ConvertError If this is not a "file" URI
     */
    std::string toNativeFilename() const;

    /**
     * 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
     *
     * @throw Glib::Error If the URL can't be read
     */
    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) + ")";
    }

    /**
     * True if the scheme equals the given string (not case sensitive)
     */
    bool hasScheme(const char *scheme) const;

private:
    std::shared_ptr<xmlURI> m_shared;

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

    xmlURI *_xmlURIPtr() const { return m_shared.get(); }
};

/**
 * 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);

}  /* 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:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :