xref: /aosp_15_r20/external/sandboxed-api/contrib/uriparser/utils/utils_uriparser.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "contrib/uriparser/utils/utils_uriparser.h"
16 
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
19 #include <sys/socket.h>
20 
21 #include <fstream>
22 #include <iostream>
23 #include <string>
24 
25 #include "absl/cleanup/cleanup.h"
26 
~UriParser()27 UriParser::~UriParser() {
28   if (GetStatus().ok()) {
29     api_.uriFreeUriMembersA(uri_.PtrBefore()).IgnoreError();
30   }
31 }
32 
GetStatus()33 absl::Status UriParser::GetStatus() { return status_; }
34 
ParseUri()35 absl::Status UriParser::ParseUri() {
36   SAPI_RETURN_IF_ERROR(sandbox_->Allocate(&uri_, true));
37 
38   sapi::v::Struct<UriParserStateA> state;
39   state.mutable_data()->uri = reinterpret_cast<UriUriA*>(uri_.GetRemote());
40   SAPI_ASSIGN_OR_RETURN(
41       int ret, api_.uriParseUriA(state.PtrBefore(), c_uri_.PtrBefore()));
42   if (ret != 0) {
43     return absl::UnavailableError("Unable to parse uri");
44   }
45 
46   SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&uri_));
47 
48   return absl::OkStatus();
49 }
50 
FetchUriText(UriTextRangeA * ptr)51 absl::StatusOr<std::string> UriParser::FetchUriText(UriTextRangeA* ptr) {
52   if (ptr == nullptr) {
53     return "";
54   }
55   if (ptr->first == nullptr) {
56     return "";
57   }
58 
59   size_t size = ptr->afterLast - ptr->first;
60 
61   // Sometimes uriparser dosen't allocate new memory
62   // and sometimes it does.
63   SAPI_ASSIGN_OR_RETURN(
64       std::string uri,
65       sandbox_->GetCString(sapi::v::RemotePtr(const_cast<char*>(ptr->first))));
66 
67   return uri.substr(0, size);
68 }
69 
GetScheme()70 absl::StatusOr<std::string> UriParser::GetScheme() {
71   return FetchUriText(&uri_.mutable_data()->scheme);
72 }
73 
GetUserInfo()74 absl::StatusOr<std::string> UriParser::GetUserInfo() {
75   return FetchUriText(&uri_.mutable_data()->userInfo);
76 }
77 
GetHostText()78 absl::StatusOr<std::string> UriParser::GetHostText() {
79   return FetchUriText(&uri_.mutable_data()->hostText);
80 }
81 
GetHostIP()82 absl::StatusOr<std::string> UriParser::GetHostIP() {
83   char ipstr[INET6_ADDRSTRLEN] = "";
84 
85   UriHostDataA* data = &uri_.mutable_data()->hostData;
86 
87   if (uri_.mutable_data()->hostData.ip4) {
88     sapi::v::Struct<UriIp4> ip4;
89     ip4.SetRemote(uri_.mutable_data()->hostData.ip4);
90     SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&ip4));
91     inet_ntop(AF_INET, ip4.mutable_data()->data, ipstr, sizeof(ipstr));
92   } else if (uri_.mutable_data()->hostData.ip6) {
93     sapi::v::Struct<UriIp6> ip6;
94     ip6.SetRemote(uri_.mutable_data()->hostData.ip6);
95     SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&ip6));
96     inet_ntop(AF_INET6, ip6.mutable_data()->data, ipstr, sizeof(ipstr));
97   }
98 
99   return std::string(ipstr);
100 }
101 
GetPortText()102 absl::StatusOr<std::string> UriParser::GetPortText() {
103   return FetchUriText(&uri_.mutable_data()->portText);
104 }
105 
GetQuery()106 absl::StatusOr<std::string> UriParser::GetQuery() {
107   return FetchUriText(&uri_.mutable_data()->query);
108 }
109 
GetFragment()110 absl::StatusOr<std::string> UriParser::GetFragment() {
111   return FetchUriText(&uri_.mutable_data()->fragment);
112 }
113 
GetPath()114 absl::StatusOr<std::vector<std::string>> UriParser::GetPath() {
115   std::vector<std::string> ret;
116 
117   UriPathSegmentA* pathHead = uri_.mutable_data()->pathHead;
118   if (pathHead == nullptr) {
119     return ret;
120   }
121 
122   sapi::v::Struct<UriPathSegmentA> path_segment;
123   path_segment.SetRemote(pathHead);
124 
125   while (path_segment.GetRemote() != nullptr) {
126     SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&path_segment));
127 
128     SAPI_ASSIGN_OR_RETURN(std::string seg,
129                           FetchUriText(&path_segment.mutable_data()->text));
130     if (!seg.empty()) {
131       ret.push_back(seg);
132     }
133 
134     path_segment.SetRemote(path_segment.mutable_data()->next);
135   }
136 
137   return ret;
138 }
139 
NormalizeSyntax()140 absl::Status UriParser::NormalizeSyntax() {
141   SAPI_ASSIGN_OR_RETURN(int dirty_parts,
142                         api_.uriNormalizeSyntaxMaskRequiredA(uri_.PtrNone()));
143 
144   return NormalizeSyntax(dirty_parts);
145 }
146 
NormalizeSyntax(int norm_mask)147 absl::Status UriParser::NormalizeSyntax(int norm_mask) {
148   SAPI_ASSIGN_OR_RETURN(int ret,
149                         api_.uriNormalizeSyntaxExA(uri_.PtrAfter(), norm_mask));
150 
151   if (ret != 0) {
152     return absl::UnavailableError("Unable to normalize");
153   }
154 
155   return absl::OkStatus();
156 }
157 
GetUri()158 absl::StatusOr<std::string> UriParser::GetUri() { return GetUri(&uri_); }
159 
GetUri(sapi::v::Struct<UriUriA> * uri)160 absl::StatusOr<std::string> UriParser::GetUri(sapi::v::Struct<UriUriA>* uri) {
161   sapi::v::Int size;
162   int ret;
163 
164   SAPI_ASSIGN_OR_RETURN(
165       ret, api_.uriToStringCharsRequiredA(uri->PtrNone(), size.PtrAfter()));
166   if (ret != 0) {
167     return absl::UnavailableError("Unable to get size");
168   }
169 
170   sapi::v::Array<char> buf(size.GetValue() + 1);
171   sapi::v::NullPtr null_ptr;
172 
173   SAPI_ASSIGN_OR_RETURN(ret, api_.uriToStringA(buf.PtrAfter(), uri->PtrNone(),
174                                                buf.GetSize(), &null_ptr));
175   if (ret != 0) {
176     return absl::UnavailableError("Unable to Recomposing URI");
177   }
178 
179   return std::string(buf.GetData());
180 }
181 
GetUriEscaped(bool space_to_plus,bool normalize_breaks)182 absl::StatusOr<std::string> UriParser::GetUriEscaped(bool space_to_plus,
183                                                      bool normalize_breaks) {
184   SAPI_ASSIGN_OR_RETURN(std::string uri, GetUri());
185 
186   // Be sure to allocate *6 times* the space of the input buffer for
187   // *6 times* for _normalizeBreaks == URI_TRUE_
188   int space = uri.length() * 6 + 1;
189 
190   sapi::v::Array<char> bufout(space);
191   sapi::v::ConstCStr bufin(uri.c_str());
192 
193   SAPI_RETURN_IF_ERROR(api_.uriEscapeA(bufin.PtrBefore(), bufout.PtrAfter(),
194                                        space_to_plus, normalize_breaks));
195 
196   return std::string(bufout.GetData());
197 }
198 
GetUriWithBase(const std::string & base)199 absl::StatusOr<std::string> UriParser::GetUriWithBase(const std::string& base) {
200   UriParser base_uri(sandbox_, base);
201 
202   sapi::v::Struct<UriUriA> newuri;
203   SAPI_ASSIGN_OR_RETURN(int ret,
204                         api_.uriAddBaseUriA(newuri.PtrAfter(), uri_.PtrNone(),
205                                             base_uri.uri_.PtrBefore()));
206   if (ret != 0) {
207     return absl::UnavailableError("Unable to add base");
208   }
209   absl::Cleanup newuri_cleanup = [this, &newuri] {
210     api_.uriFreeUriMembersA(newuri.PtrNone()).IgnoreError();
211   };
212 
213   return GetUri(&newuri);
214 }
215 
GetUriWithoutBase(const std::string & base,bool domain_root_mode)216 absl::StatusOr<std::string> UriParser::GetUriWithoutBase(
217     const std::string& base, bool domain_root_mode) {
218   UriParser base_uri(sandbox_, base);
219 
220   sapi::v::Struct<UriUriA> newuri;
221   SAPI_ASSIGN_OR_RETURN(
222       int ret,
223       api_.uriRemoveBaseUriA(newuri.PtrAfter(), uri_.PtrNone(),
224                              base_uri.uri_.PtrBefore(), domain_root_mode));
225   if (ret != 0) {
226     return absl::UnavailableError("Unable to remove base");
227   }
228   absl::Cleanup newuri_cleanup = [this, &newuri] {
229     api_.uriFreeUriMembersA(newuri.PtrNone()).IgnoreError();
230   };
231 
232   return GetUri(&newuri);
233 }
234 
235 absl::StatusOr<absl::btree_map<std::string, std::string>>
GetQueryElements()236 UriParser::GetQueryElements() {
237   absl::btree_map<std::string, std::string> outquery;
238 
239   if (uri_.mutable_data()->query.first == nullptr) {
240     return outquery;
241   }
242 
243   sapi::v::Array<void*> query_ptr(1);
244   sapi::v::Int query_count;
245   sapi::v::RemotePtr first(const_cast<char*>(uri_.mutable_data()->query.first));
246   sapi::v::RemotePtr afterLast(
247       const_cast<char*>(uri_.mutable_data()->query.afterLast));
248 
249   SAPI_ASSIGN_OR_RETURN(
250       int ret,
251       api_.uriDissectQueryMallocA(query_ptr.PtrAfter(), query_count.PtrAfter(),
252                                   &first, &afterLast));
253   if (ret != 0) {
254     return absl::UnavailableError("Unable to get query list");
255   }
256   absl::Cleanup query_list_cleanup = [this, &query_ptr] {
257     sapi::v::RemotePtr rptr(query_ptr[0]);
258     api_.uriFreeQueryListA(&rptr).IgnoreError();
259   };
260 
261   sapi::v::Struct<UriQueryListA> obj;
262   obj.SetRemote(query_ptr[0]);
263 
264   for (int i = 0; i < query_count.GetValue(); ++i) {
265     SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&obj));
266     obj.SetRemote(nullptr);
267 
268     void* key_p = const_cast<char*>(obj.mutable_data()->key);
269     void* value_p = const_cast<char*>(obj.mutable_data()->value);
270 
271     SAPI_ASSIGN_OR_RETURN(std::string key_s,
272                           sandbox_->GetCString(sapi::v::RemotePtr(key_p)));
273     std::string value_s;
274     if (value_p != nullptr) {
275       SAPI_ASSIGN_OR_RETURN(value_s,
276                             sandbox_->GetCString(sapi::v::RemotePtr(value_p)));
277     } else {
278       value_s = "";
279     }
280     outquery[key_s] = value_s;
281     obj.SetRemote(obj.mutable_data()->next);
282   }
283   obj.SetRemote(nullptr);
284 
285   return outquery;
286 }
287