1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  *   https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  *   Redistribution and use in source and binary forms, with or
10  *   without modification, are permitted provided that the following
11  *   conditions are met:
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above
15  *     copyright notice, this list of conditions and the following
16  *     disclaimer in the documentation and/or other materials provided
17  *     with the distribution.
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *   POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef DART_COMMON_URI_HPP_
34 #define DART_COMMON_URI_HPP_
35 
36 #include <string>
37 
38 namespace dart {
39 namespace common {
40 
41 class UriComponent final
42 {
43 public:
44   using value_type = std::string;
45   using reference_type = value_type&;
46   using reference_const_type = const value_type&;
47   using pointer_type = value_type*;
48   using pointer_const_type = const value_type*;
49 
50   UriComponent();
51   UriComponent(reference_const_type _value);
52 
53   operator bool() const;
54 
55   bool operator!() const;
56 
57   UriComponent& operator=(reference_const_type _value);
58 
59   reference_type operator*();
60   reference_const_type operator*() const;
61 
62   pointer_type operator->();
63   pointer_const_type operator->() const;
64 
65   void assign(reference_const_type _value);
66   void reset();
67 
68   reference_type get();
69   reference_const_type get() const;
70 
71   reference_type get_value_or(reference_type _default);
72   reference_const_type get_value_or(reference_const_type _default) const;
73 
74 private:
75   bool mExists;
76   std::string mValue;
77 };
78 
79 /// The Uri struct provides URI parsing and merging functionality based on RFC
80 /// 3986.
81 ///
82 /// We have Uri as a struct rather than class to expose member variables. Many
83 /// ResourceRetreiver classes rewrite URIs to other types of URIs (e.g, resolve
84 /// 'package://' URIs to 'file://' URIs), which is easier to implement if you
85 /// have direct access to the URI components.
86 struct Uri final
87 {
88   /// Scheme, e.g. 'http', 'file', 'package'
89   UriComponent mScheme;
90 
91   /// Authority, e.g. 'google.com', 'en.wikipedia.org'
92   UriComponent mAuthority;
93 
94   /// Path, e.g. '/index.html', '/foo/bar.txt'
95   UriComponent mPath;
96 
97   /// Query string, i.e. the part of the URI after the ?
98   UriComponent mQuery;
99 
100   /// Fragment, e.g. the part of the URI after the #
101   UriComponent mFragment;
102 
103   /// Constructor
104   Uri() = default;
105 
106   /// Constructor that takes a URI or local path. Internally, this is equivalent
107   /// to calling fromStringOrPath(_input) after default constructor.
108   ///
109   /// We don't declare this constructor as explicit in order to allow implicit
110   /// conversion from string so that you can pass in string parameter to a
111   /// function that takes Uri.
112   Uri(const std::string& _input);
113 
114   /// Constructor that takes a URI or local path as const char*. The behavior is
115   /// identical to Uri(const std::string&).
116   Uri(const char* _input);
117 
118   /// Clear the URI by reset()ing all components.
119   void clear();
120 
121   /// Parse a URI from a string; return success. All the components will be
122   /// cleared on failure.
123   bool fromString(const std::string& _input);
124 
125   /// Parse a local path (i.e. URI with no schema) from a string; return
126   /// success. Note that the input path should be absolute path. All the
127   /// components will be cleared on failure.
128   bool fromPath(const std::string& _path);
129 
130   /// Parse a URI or local path (i.e. URI with no schema) from a string; return
131   /// success. We assume that any string without a scheme is a path. All the
132   /// components will be cleared on failure.
133   bool fromStringOrPath(const std::string& _input);
134 
135   /// Resolve a relative path reference; return success. All the components will
136   /// be cleared on failure.
137   bool fromRelativeUri(
138       const std::string& _base,
139       const std::string& _relative,
140       bool _strict = false);
141 
142   /// Resolve a relative path reference; return success. All the components will
143   /// be cleared on failure.
144   bool fromRelativeUri(
145       const char* _base, const char* _relative, bool _strict = false);
146 
147   /// Resolve a relative path reference; return success. All the components will
148   /// be cleared on failure.
149   bool fromRelativeUri(
150       const Uri& _base, const std::string& _relative, bool _strict = false);
151 
152   /// Resolve a relative path reference; return success. All the components will
153   /// be cleared on failure.
154   bool fromRelativeUri(
155       const Uri& _base, const char* _relative, bool _strict = false);
156 
157   /// Resolve a relative path reference; return success. All the components will
158   /// be cleared on failure.
159   bool fromRelativeUri(
160       const Uri& _base, const Uri& _relative, bool _strict = false);
161 
162   /// Combine the parts of the URI into a string.
163   std::string toString() const;
164 
165   /// Create URI from a string; return an empty URI on failure.
166   static Uri createFromString(const std::string& _input);
167 
168   /// Create file URI from a string; return an empty URI on failure.
169   static Uri createFromPath(const std::string& _path);
170 
171   /// Create general URI or file URI from a string; return an empty URI on
172   /// failure.
173   static Uri createFromStringOrPath(const std::string& _input);
174 
175   /// Create URI resolving a relative path reference; return an empty URI on
176   /// failure.
177   static Uri createFromRelativeUri(
178       const std::string& _base,
179       const std::string& _relative,
180       bool _strict = false);
181 
182   /// Create URI resolving a relative path reference; return an empty URI on
183   /// failure.
184   static Uri createFromRelativeUri(
185       const Uri& _base, const std::string& _relative, bool _strict = false);
186 
187   /// Create URI resolving a relative path reference; return an empty URI on
188   /// failure.
189   static Uri createFromRelativeUri(
190       const Uri& _base, const Uri& _relative, bool _strict = false);
191 
192   /// Parse a URI from a string; return an empty string on failure.
193   static std::string getUri(const std::string& _input);
194 
195   /// Resolve a relative path reference; return an empty string on failure.
196   static std::string getRelativeUri(
197       const std::string& _base,
198       const std::string& _relative,
199       bool _strict = false);
200 
201   /// Resolve a relative path reference; return an empty string on failure.
202   static std::string getRelativeUri(
203       const Uri& _base, const std::string& _relative, bool _strict = false);
204 
205   /// Resolve a relative path reference; return an empty string on failure.
206   static std::string getRelativeUri(
207       const Uri& _base, const Uri& _relative, bool _strict = false);
208 
209   /// Get the path component of the URI as a string.
210   std::string getPath() const;
211 
212   /// Get the path in the local filesystem as a string. You should use this
213   /// function rather than getPath() if you are trying to access a local file.
214   /// Note that this function is identical to getPath() for Unix systems, but
215   /// differ by the leading '/' on Windows.
216   std::string getFilesystemPath() const;
217 
218 private:
219   /// Implement section 5.2.3 of RFC 3986.
220   static std::string mergePaths(const Uri& _base, const Uri& _relative);
221 
222   /// Implement section 5.2.4 of RFC 3986.
223   static std::string removeDotSegments(const std::string& _path);
224 };
225 
226 } // namespace common
227 } // namespace dart
228 
229 #endif // ifndef DART_COMMON_URI_HPP_
230