1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "proxy_util.h"
18 
19 namespace {
GetXmlRpcArrayFromVector(const VectorType & vector_in,XmlRpc::XmlRpcValue * xml_rpc_value_out)20 template<typename VectorType> void GetXmlRpcArrayFromVector(
21     const VectorType& vector_in,
22     XmlRpc::XmlRpcValue* xml_rpc_value_out) {
23   if (vector_in.empty()) {
24     xml_rpc_value_out->setToNil();
25     return;
26   }
27   int i = 0;
28   for (const auto& value : vector_in) {
29     (*xml_rpc_value_out)[++i] = value;
30   }
31 }
32 
GetXmlRpcStructFromStringMap(const std::map<std::string,std::string> & string_map_in,XmlRpc::XmlRpcValue * xml_rpc_value_out)33 void GetXmlRpcStructFromStringMap(
34     const std::map<std::string, std::string>& string_map_in,
35     XmlRpc::XmlRpcValue* xml_rpc_value_out) {
36   if (string_map_in.empty()) {
37     xml_rpc_value_out->setToNil();
38     return;
39   }
40   for (const auto& value : string_map_in) {
41     (*xml_rpc_value_out)[value.first] = value.second;
42   }
43 }
44 
GetXmlRpcStructFromBrilloVariantDictionary(const brillo::VariantDictionary & var_dict_in,XmlRpc::XmlRpcValue * xml_rpc_value_out)45 void GetXmlRpcStructFromBrilloVariantDictionary(
46     const brillo::VariantDictionary& var_dict_in,
47     XmlRpc::XmlRpcValue* xml_rpc_value_out) {
48   if (var_dict_in.empty()) {
49     xml_rpc_value_out->setToNil();
50     return;
51   }
52   for (const auto& value : var_dict_in) {
53     XmlRpc::XmlRpcValue tmp_value;
54     GetXmlRpcValueFromBrilloAnyValue(value.second, &tmp_value);
55     (*xml_rpc_value_out)[value.first] = tmp_value;
56   }
57 }
58 
GetVectorFromXmlRpcArray(XmlRpc::XmlRpcValue * xml_rpc_value_in,std::vector<ElementType> * vector_out)59 template<typename ElementType> void GetVectorFromXmlRpcArray(
60     XmlRpc::XmlRpcValue* xml_rpc_value_in,
61     std::vector<ElementType>* vector_out) {
62   int array_size = xml_rpc_value_in->size();
63   for (int i = 0; i < array_size; ++i) {
64     vector_out->push_back(static_cast<ElementType>((*xml_rpc_value_in)[i]));
65   }
66 }
67 
GetBrilloAnyVectorFromXmlRpcArray(XmlRpc::XmlRpcValue * xml_rpc_value_in,brillo::Any * any_value_out)68 void GetBrilloAnyVectorFromXmlRpcArray(
69     XmlRpc::XmlRpcValue* xml_rpc_value_in,
70     brillo::Any* any_value_out) {
71   int array_size = xml_rpc_value_in->size();
72   if (!array_size) {
73     any_value_out->Clear();
74     return;
75   }
76   XmlRpc::XmlRpcValue::Type elem_type = (*xml_rpc_value_in)[0].getType();
77   for (int i = 0; i < array_size; ++i) {
78     CHECK((*xml_rpc_value_in)[i].getType() == elem_type);
79   }
80   switch (elem_type) {
81     case XmlRpc::XmlRpcValue::TypeBoolean: {
82         std::vector<bool> bool_vec;
83         GetVectorFromXmlRpcArray(xml_rpc_value_in, &bool_vec);
84         *any_value_out = bool_vec;
85         return;
86     }
87     case XmlRpc::XmlRpcValue::TypeInt: {
88         std::vector<int> int_vec;
89         GetVectorFromXmlRpcArray(xml_rpc_value_in, &int_vec);
90         *any_value_out = int_vec;
91         return;
92     }
93     case XmlRpc::XmlRpcValue::TypeDouble: {
94         std::vector<double> double_vec;
95         GetVectorFromXmlRpcArray(xml_rpc_value_in, &double_vec);
96         *any_value_out = double_vec;
97         return;
98     }
99     case XmlRpc::XmlRpcValue::TypeString: {
100       std::vector<std::string> string_vec;
101       GetVectorFromXmlRpcArray(xml_rpc_value_in, &string_vec);
102       *any_value_out = string_vec;
103       return;
104     }
105     default:
106       LOG(FATAL) << __func__ << ". Unhandled type: "
107                  << (*xml_rpc_value_in)[0].getType();
108   }
109 }
110 
111 template<typename ValueType> XmlRpc::XmlRpcValue::Type GetXmlRpcType();
GetXmlRpcType()112 template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<bool>() {
113   return XmlRpc::XmlRpcValue::TypeBoolean;
114 }
GetXmlRpcType()115 template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<int>() {
116   return XmlRpc::XmlRpcValue::TypeInt;
117 }
GetXmlRpcType()118 template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<double>() {
119   return XmlRpc::XmlRpcValue::TypeDouble;
120 }
GetXmlRpcType()121 template<> XmlRpc::XmlRpcValue::Type GetXmlRpcType<std::string>() {
122   return XmlRpc::XmlRpcValue::TypeString;
123 }
124 
IsMemberValuePresent(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name)125 template<typename ValueType> bool IsMemberValuePresent(
126     XmlRpc::XmlRpcValue* xml_rpc_value_in,
127     const std::string& member_name) {
128   if (xml_rpc_value_in->hasMember(member_name) &&
129       ((*xml_rpc_value_in)[member_name].getType() ==
130        GetXmlRpcType<ValueType>())) {
131     return true;
132   }
133   return false;
134 }
135 
GetValueFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,ValueType default_value,ValueType * value_out)136 template<typename ValueType> bool GetValueFromXmlRpcValueStructMember(
137     XmlRpc::XmlRpcValue* xml_rpc_value_in,
138     const std::string& member_name,
139     ValueType default_value,
140     ValueType* value_out) {
141   if (!IsMemberValuePresent<ValueType>(xml_rpc_value_in, member_name)) {
142     *value_out = default_value;
143     return false;
144   }
145   *value_out = ValueType((*xml_rpc_value_in)[member_name]);
146   return true;
147 }
148 
IsMemberVectorPresent(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name)149 template<typename ElementType> bool IsMemberVectorPresent(
150     XmlRpc::XmlRpcValue* xml_rpc_value_in,
151     const std::string& member_name) {
152   if (xml_rpc_value_in->hasMember(member_name) &&
153       ((*xml_rpc_value_in)[member_name].getType() ==
154        XmlRpc::XmlRpcValue::TypeArray) &&
155       ((*xml_rpc_value_in)[member_name][0].getType() ==
156        GetXmlRpcType<ElementType>())) {
157     return true;
158   }
159   return false;
160 }
161 
GetVectorFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,std::vector<ElementType> default_value,std::vector<ElementType> * value_out)162 template<typename ElementType> bool GetVectorFromXmlRpcValueStructMember(
163     XmlRpc::XmlRpcValue* xml_rpc_value_in,
164     const std::string& member_name,
165     std::vector<ElementType> default_value,
166     std::vector<ElementType>* value_out) {
167   if (!IsMemberVectorPresent<ElementType>(xml_rpc_value_in, member_name)) {
168     *value_out = default_value;
169     return false;
170   }
171   XmlRpc::XmlRpcValue& xml_rpc_member_array = (*xml_rpc_value_in)[member_name];
172   int array_size = xml_rpc_member_array.size();
173   for (int array_pos = 0; array_pos < array_size; ++array_pos) {
174     value_out->push_back(ElementType(xml_rpc_member_array[array_pos]));
175   }
176   return true;
177 }
178 } // namespace
179 
GetXmlRpcValueFromBrilloAnyValue(const brillo::Any & any_value_in,XmlRpc::XmlRpcValue * xml_rpc_value_out)180 void GetXmlRpcValueFromBrilloAnyValue(
181     const brillo::Any& any_value_in,
182     XmlRpc::XmlRpcValue* xml_rpc_value_out) {
183   if (any_value_in.IsTypeCompatible<bool>()) {
184     *xml_rpc_value_out =  any_value_in.Get<bool>();
185     return;
186   }
187   if (any_value_in.IsTypeCompatible<uint8_t>()) {
188     *xml_rpc_value_out =  any_value_in.Get<uint8_t>();
189     return;
190   }
191   if (any_value_in.IsTypeCompatible<uint16_t>()) {
192     *xml_rpc_value_out =  any_value_in.Get<uint16_t>();
193     return;
194   }
195   if (any_value_in.IsTypeCompatible<int>()) {
196     *xml_rpc_value_out =  any_value_in.Get<int>();
197     return;
198   }
199   if (any_value_in.IsTypeCompatible<double>()) {
200     *xml_rpc_value_out =  any_value_in.Get<double>();
201     return;
202   }
203   if (any_value_in.IsTypeCompatible<std::string>()) {
204     *xml_rpc_value_out =  any_value_in.Get<std::string>();
205     return;
206   }
207   if (any_value_in.IsTypeCompatible<dbus::ObjectPath>()) {
208     *xml_rpc_value_out =  any_value_in.Get<dbus::ObjectPath>().value();
209     return;
210   }
211   if (any_value_in.IsTypeCompatible<std::vector<bool>>()) {
212     GetXmlRpcArrayFromVector(
213         any_value_in.Get<std::vector<bool>>(), xml_rpc_value_out);
214     return;
215   }
216   if (any_value_in.IsTypeCompatible<std::vector<uint8_t>>()) {
217     GetXmlRpcArrayFromVector(
218         any_value_in.Get<std::vector<uint8_t>>(), xml_rpc_value_out);
219     return;
220   }
221   if (any_value_in.IsTypeCompatible<std::vector<uint16_t>>()) {
222     GetXmlRpcArrayFromVector(
223         any_value_in.Get<std::vector<uint16_t>>(), xml_rpc_value_out);
224     return;
225   }
226   if (any_value_in.IsTypeCompatible<std::vector<int>>()) {
227     GetXmlRpcArrayFromVector(
228         any_value_in.Get<std::vector<int>>(), xml_rpc_value_out);
229     return;
230   }
231   if (any_value_in.IsTypeCompatible<std::vector<double>>()) {
232     GetXmlRpcArrayFromVector(
233         any_value_in.Get<std::vector<double>>(), xml_rpc_value_out);
234     return;
235   }
236   if (any_value_in.IsTypeCompatible<std::vector<std::string>>()) {
237     GetXmlRpcArrayFromVector(
238         any_value_in.Get<std::vector<std::string>>(), xml_rpc_value_out);
239     return;
240   }
241   if (any_value_in.IsTypeCompatible<std::vector<dbus::ObjectPath>>()) {
242     std::vector<std::string> string_vec;
243     for (const auto& object : any_value_in.Get<std::vector<dbus::ObjectPath>>()) {
244       string_vec.push_back(object.value());
245     }
246     GetXmlRpcArrayFromVector(string_vec, xml_rpc_value_out);
247     return;
248   }
249   if (any_value_in.IsTypeCompatible<std::map<std::string, std::string>>()) {
250     GetXmlRpcStructFromStringMap(
251         any_value_in.Get<std::map<std::string, std::string>>(), xml_rpc_value_out);
252     return;
253   }
254   if (any_value_in.IsTypeCompatible<brillo::VariantDictionary>()) {
255     GetXmlRpcStructFromBrilloVariantDictionary(
256         any_value_in.Get<brillo::VariantDictionary>(), xml_rpc_value_out);
257     return;
258   }
259   LOG(FATAL) << __func__ << ". Unhandled type: "
260              << any_value_in.GetUndecoratedTypeName();
261 }
262 
GetBrilloAnyValueFromXmlRpcValue(XmlRpc::XmlRpcValue * xml_rpc_value_in,brillo::Any * any_value_out)263 void GetBrilloAnyValueFromXmlRpcValue(
264     XmlRpc::XmlRpcValue* xml_rpc_value_in,
265     brillo::Any* any_value_out) {
266   switch (xml_rpc_value_in->getType()) {
267     case XmlRpc::XmlRpcValue::TypeBoolean:
268       *any_value_out = static_cast<bool>(*xml_rpc_value_in);
269       return;
270     case XmlRpc::XmlRpcValue::TypeInt:
271       *any_value_out = static_cast<int>(*xml_rpc_value_in);
272       return;
273     case XmlRpc::XmlRpcValue::TypeDouble:
274       *any_value_out = static_cast<double>(*xml_rpc_value_in);
275       return;
276     case XmlRpc::XmlRpcValue::TypeString:
277       *any_value_out = static_cast<std::string>(*xml_rpc_value_in);
278       return;
279     case XmlRpc::XmlRpcValue::TypeArray:
280       GetBrilloAnyVectorFromXmlRpcArray(xml_rpc_value_in, any_value_out);
281       return;
282     default:
283       LOG(FATAL) << __func__ << ". Unhandled type: "
284                  << xml_rpc_value_in->getType();
285   }
286 }
287 
GetBoolValueFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,bool default_value,bool * value_out)288 bool GetBoolValueFromXmlRpcValueStructMember(
289     XmlRpc::XmlRpcValue* xml_rpc_value_in,
290     const std::string& member_name,
291     bool default_value,
292     bool* value_out) {
293   return GetValueFromXmlRpcValueStructMember(
294       xml_rpc_value_in, member_name, default_value, value_out);
295 }
296 
GetIntValueFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,int default_value,int * value_out)297 bool GetIntValueFromXmlRpcValueStructMember(
298     XmlRpc::XmlRpcValue* xml_rpc_value_in,
299     const std::string& member_name,
300     int default_value,
301     int* value_out) {
302   return GetValueFromXmlRpcValueStructMember(
303       xml_rpc_value_in, member_name, default_value, value_out);
304 }
305 
GetDoubleValueFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,double default_value,double * value_out)306 bool GetDoubleValueFromXmlRpcValueStructMember(
307     XmlRpc::XmlRpcValue* xml_rpc_value_in,
308     const std::string& member_name,
309     double default_value,
310     double* value_out){
311   return GetValueFromXmlRpcValueStructMember(
312       xml_rpc_value_in, member_name, default_value, value_out);
313 }
314 
GetStringValueFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,const std::string & default_value,std::string * value_out)315 bool GetStringValueFromXmlRpcValueStructMember(
316     XmlRpc::XmlRpcValue* xml_rpc_value_in,
317     const std::string& member_name,
318     const std::string& default_value,
319     std::string* value_out) {
320   return GetValueFromXmlRpcValueStructMember(
321       xml_rpc_value_in, member_name, default_value, value_out);
322 }
323 
GetStringVectorFromXmlRpcValueStructMember(XmlRpc::XmlRpcValue * xml_rpc_value_in,const std::string & member_name,const std::vector<std::string> & default_value,std::vector<std::string> * value_out)324 bool GetStringVectorFromXmlRpcValueStructMember(
325     XmlRpc::XmlRpcValue* xml_rpc_value_in,
326     const std::string& member_name,
327     const std::vector<std::string>& default_value,
328     std::vector<std::string>* value_out) {
329   return GetVectorFromXmlRpcValueStructMember(
330       xml_rpc_value_in, member_name, default_value, value_out);
331 }
332