2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "common/app_control.h"
20 #include <app_control_internal.h>
21 #include <bundle_internal.h>
26 #include <regex> // NOLINT
30 #include "common/file_utils.h"
31 #include "common/logger.h"
32 #include "common/string_utils.h"
37 static bool BundleAddData(bundle* target, const std::string& key,
38 const std::string& value) {
39 int result = appsvc_add_data(target, key.c_str(), value.c_str());
41 LOGGER(ERROR) << "Failed to add data to appsvc.";
48 static bool BundleAddDataArray(bundle* target, const std::string& key,
49 const std::vector<std::string>& value_array) {
50 int n = value_array.size();
51 std::vector<const char*> v;
52 std::for_each(value_array.begin(), value_array.end(),
53 [&v] (const std::string& str) {
54 v.push_back(static_cast<const char*>(str.c_str()));
57 int result = appsvc_add_data_array(target, key.c_str(),
60 LOGGER(ERROR) << "Failed to add an array of data to appsvc.";
67 static const std::string GetOperationFromScheme(const std::string& scheme) {
68 static std::map<const std::string, const std::string> table = {
69 {"sms", APP_CONTROL_OPERATION_COMPOSE},
70 {"mmsto", APP_CONTROL_OPERATION_COMPOSE},
71 {"mailto", APP_CONTROL_OPERATION_COMPOSE},
72 {"tel", APP_CONTROL_OPERATION_CALL}
74 auto found = table.find(scheme);
75 if (found == table.end()) {
77 return APP_CONTROL_OPERATION_VIEW;
82 static void AppendExtraDatafromUrl(AppControl* request,
83 const std::string& url) {
84 static std::vector<std::pair<std::string, std::string> > patterns = {
85 {".*[?&]body=([^&]+).*", APP_CONTROL_DATA_TEXT},
86 {".*[?&]cc=([^&]+).*", APP_CONTROL_DATA_CC},
87 {".*[?&]bcc=([^&]+).*", APP_CONTROL_DATA_BCC},
88 {".*[?&]subject=([^&]+).*", APP_CONTROL_DATA_SUBJECT},
89 {".*[?&]to=([^&]+).*", APP_CONTROL_DATA_TO},
90 {"sms:([^?&]+).*", APP_CONTROL_DATA_TO},
91 {"mmsto:([^?&]+).*", APP_CONTROL_DATA_TO},
92 {"mailto:([^?&]+).*", APP_CONTROL_DATA_TO}
95 for (auto& param : patterns) {
96 std::regex pattern(param.first, std::regex_constants::icase);
98 if (std::regex_match(url, result, pattern) && result.size() >= 2) {
99 std::string extra_data = result[1].str();
102 utils::UrlDecode(extra_data));
110 AppControl::AppControl(app_control_h app_control) {
111 app_control_clone(&app_control_, app_control);
112 app_control_to_bundle(app_control_, &app_control_bundle_);
115 AppControl:: AppControl() {
116 app_control_create(&app_control_);
117 app_control_to_bundle(app_control_, &app_control_bundle_);
120 AppControl::~AppControl() {
121 if (app_control_ != NULL) {
122 app_control_destroy(app_control_);
126 std::string AppControl::operation() const {
127 const char* operation = appsvc_get_operation(app_control_bundle_);
129 if (operation != NULL) {
130 return std::string(operation);
132 return std::string();
136 void AppControl::set_operation(const std::string& operation) {
137 appsvc_set_operation(app_control_bundle_, operation.c_str());
140 std::string AppControl::mime() const {
141 const char* mime = appsvc_get_mime(app_control_bundle_);
144 return std::string(mime);
146 return std::string();
150 void AppControl::set_mime(const std::string& mime) {
151 appsvc_set_mime(app_control_bundle_, mime.c_str());
154 std::string AppControl::uri() const {
155 const char* uri = appsvc_get_uri(app_control_bundle_);
158 return std::string(uri);
160 return std::string();
164 void AppControl::set_uri(const std::string& uri) {
165 appsvc_set_uri(app_control_bundle_, uri.c_str());
168 std::string AppControl::category() const {
169 const char* category = appsvc_get_category(app_control_bundle_);
171 if (category != NULL) {
172 return std::string(category);
174 return std::string();
178 void AppControl::set_category(const std::string& category) {
179 appsvc_set_category(app_control_bundle_, category.c_str());
182 std::string AppControl::data(const std::string& key) const {
183 const char* data = appsvc_get_data(app_control_bundle_, key.c_str());
186 return std::string(data);
188 return std::string();
192 std::vector<std::string> AppControl::data_array(const std::string& key) const {
193 int data_array_len = 0;
194 const char** data_array = appsvc_get_data_array(app_control_bundle_,
195 key.c_str(), &data_array_len);
196 std::vector<std::string> data_vector;
197 if (data_array) { // checking whether the 'data_array' is valid
198 if (data_array_len > 0) {
199 for (int i = 0; i < data_array_len; i++) {
200 data_vector.push_back(data_array[i]);
207 std::string AppControl::encoded_bundle() {
208 bundle_raw* encoded_data;
210 bundle_encode(app_control_bundle_, &encoded_data, &len);
211 std::unique_ptr<bundle_raw*, decltype(bundle_free_encoded_rawdata)*>
212 ptr { &encoded_data, bundle_free_encoded_rawdata};
213 return std::string(reinterpret_cast<char*>(encoded_data), len);
216 bool AppControl::IsDataArray(const std::string& key) {
217 return appsvc_data_is_array(app_control_bundle_, key.c_str());
220 bool AppControl::AddData(const std::string& key, const std::string& value) {
221 return BundleAddData(app_control_bundle_, key, value);
226 bool AppControl::AddDataArray(const std::string& key,
227 const std::vector<std::string>& value_array) {
228 return BundleAddDataArray(app_control_bundle_, key, value_array);
232 bool AppControl::Reply(const std::map<std::string,
233 std::vector<std::string>>& data) {
235 if (appsvc_create_result_bundle(app_control_bundle_,
236 &result) != APPSVC_RET_OK) {
237 LOGGER(ERROR) << "Failed to craete result bundle.";
240 auto it = data.begin();
241 for ( ; it != data.end(); ++it) {
242 const std::string& key = it->first;
243 if (it->second.size() == 1) {
244 BundleAddData(result, key, it->second[0]);
246 BundleAddDataArray(result, key, it->second);
250 int ret = appsvc_send_result(result, APPSVC_RES_OK);
253 return ret == APPSVC_RET_OK ? true : false;
256 bool AppControl::LaunchRequest() {
257 return (app_control_send_launch_request(app_control_, NULL, NULL) ==
258 APP_CONTROL_ERROR_NONE);
261 std::unique_ptr<AppControl> AppControl::MakeAppcontrolFromURL(
262 const std::string& url) {
263 std::string smsto_scheme("smsto");
265 std::string request_url(url);
266 std::string scheme = utils::SchemeName(request_url);
267 // smsto: does not supported by platform. change to sms:
268 if (scheme == smsto_scheme) {
269 request_url = "sms" + request_url.substr(smsto_scheme.length());
273 std::unique_ptr<AppControl> request(new AppControl());
274 request->set_uri(request_url);
275 request->set_operation(GetOperationFromScheme(scheme));
276 AppendExtraDatafromUrl(request.get(), request_url);
278 return std::move(request);
281 } // namespace common