1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
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 * http://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 <sstream>
16 #include "calendar_log.h"
17 #include "native_util.h"
18
19 namespace OHOS::CalendarApi::Native {
DumpCalendarAccount(const CalendarAccount & account)20 void DumpCalendarAccount(const CalendarAccount &account)
21 {
22 LOG_DEBUG("account.name:%{public}s", account.name.c_str());
23 LOG_DEBUG("account.type:%{public}s", account.type.c_str());
24 LOG_DEBUG("account.displayName:%{public}s", account.displayName.value_or("").c_str());
25 }
26
DumpEvent(const Event & event)27 void DumpEvent(const Event &event)
28 {
29 LOG_DEBUG("id :%{public}d", event.id.value_or(-1));
30 LOG_DEBUG("type :%{public}d", event.type);
31 LOG_DEBUG("title :%{public}s", event.title.value_or("[null]").c_str());
32 if (event.location) {
33 auto location = event.location.value();
34 LOG_DEBUG("location.location :%{public}s", location.location.value_or("[null]").c_str());
35 LOG_DEBUG("location.longitude :%{public}d", location.longitude.value_or(-1));
36 LOG_DEBUG("location.latitude :%{public}d", location.latitude.value_or(-1));
37 } else {
38 LOG_DEBUG("location [null]");
39 }
40 if (event.service) {
41 auto service = event.service.value();
42 LOG_DEBUG("service.type :%{public}s", service.type.c_str());
43 LOG_DEBUG("service.description :%{public}s", service.description.value_or("[null]").c_str());
44 LOG_DEBUG("service.uri :%{public}s", service.uri.c_str());
45 } else {
46 LOG_DEBUG("service [null]");
47 }
48 LOG_DEBUG("title :%{public}s", event.title.value_or("").c_str());
49 LOG_DEBUG("startTime :%{public}s", std::to_string(event.startTime).c_str());
50 LOG_DEBUG("endTime :%{public}s", std::to_string(event.endTime).c_str());
51 LOG_DEBUG("isAllDay :%{public}d", event.isAllDay.value_or(0));
52
53 for (const auto &attendee : event.attendees) {
54 LOG_DEBUG("attendee.name :%{public}s", attendee.name.c_str());
55 LOG_DEBUG("attendee.email :%{public}s", attendee.email.c_str());
56 }
57
58 LOG_DEBUG("timeZone :%{public}s", event.timeZone.value_or("[null]").c_str());
59 LOG_DEBUG("description :%{public}s", event.description.value_or("[null]").c_str());
60 }
61
BuildEventLocation(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)62 void BuildEventLocation(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
63 {
64 if (!event.location) {
65 return;
66 }
67 auto location = event.location.value();
68 if (location.location) {
69 valuesBucket.Put("eventLocation", location.location.value());
70 }
71 if (location.longitude) {
72 // longitude is string in db
73 valuesBucket.Put("location_longitude", std::to_string(location.longitude.value()));
74 }
75 if (location.latitude) {
76 // latitude is string in db
77 valuesBucket.Put("location_latitude", std::to_string(location.latitude.value()));
78 }
79 }
80
BuildEventService(DataShare::DataShareValuesBucket & valuesBucket,const Event & event)81 void BuildEventService(DataShare::DataShareValuesBucket &valuesBucket, const Event &event)
82 {
83 if (!event.service) {
84 return;
85 }
86 const auto service = event.service.value();
87 if (service.description) {
88 valuesBucket.Put("service_description", service.description.value());
89 }
90 valuesBucket.Put("service_type", service.type);
91 valuesBucket.Put("service_cp_bz_uri", service.uri);
92 }
93
BuildValueEvent(const Event & event,int calendarId)94 DataShare::DataShareValuesBucket BuildValueEvent(const Event &event, int calendarId)
95 {
96 DataShare::DataShareValuesBucket valuesBucket;
97 valuesBucket.Put("calendar_id", calendarId);
98
99 LOG_DEBUG("title %{public}s", event.title.value_or("").c_str());
100 valuesBucket.Put("title", event.title.value_or(""));
101 valuesBucket.Put("event_calendar_type", event.type);
102 valuesBucket.Put("dtstart", event.startTime);
103 valuesBucket.Put("dtend", event.endTime);
104
105 BuildEventLocation(valuesBucket, event);
106 BuildEventService(valuesBucket, event);
107
108 LOG_DEBUG("description %{public}s", event.description.value_or("").c_str());
109
110 valuesBucket.Put("description", event.description.value_or(""));
111 if (event.timeZone) {
112 valuesBucket.Put("eventTimezone", event.timeZone.value());
113 }
114 if (event.isAllDay) {
115 valuesBucket.Put("allDay", event.isAllDay.value() ? 1 : 0);
116 }
117 valuesBucket.Put("allDay", event.isAllDay ? (event.isAllDay.value() ? 1 : 0) : 0);
118 return valuesBucket;
119 }
120
BuildAttendeeValue(const Attendee & attendee,int eventId)121 DataShare::DataShareValuesBucket BuildAttendeeValue(const Attendee &attendee, int eventId)
122 {
123 DataShare::DataShareValuesBucket valuesBucket;
124 valuesBucket.Put("event_id", eventId);
125 valuesBucket.Put("attendeeName", attendee.name);
126 LOG_DEBUG("attendeeName %{public}s", attendee.name.c_str());
127 valuesBucket.Put("attendeeEmail", attendee.email);
128 LOG_DEBUG("attendeeEmail %{public}s", attendee.email.c_str());
129 return valuesBucket;
130 }
131
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,int & out)132 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, int& out)
133 {
134 int index = 0;
135 auto ret = resultSet->GetColumnIndex(string(fieldName), index);
136 if (ret != DataShare::E_OK) {
137 return ret;
138 }
139 return resultSet->GetInt(index, out);
140 }
141
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,std::string & out)142 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, std::string& out)
143 {
144 return resultSet->GetString(index, out);
145 }
146
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int & out)147 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int& out)
148 {
149 return resultSet->GetInt(index, out);
150 }
151
GetIndexValue(const DataShareResultSetPtr & resultSet,int index,int64_t & out)152 int GetIndexValue(const DataShareResultSetPtr &resultSet, int index, int64_t& out)
153 {
154 return resultSet->GetLong(index, out);
155 }
156
GetValue(DataShareResultSetPtr & resultSet,string_view fieldName,std::string & out)157 int GetValue(DataShareResultSetPtr &resultSet, string_view fieldName, std::string& out)
158 {
159 int index = 0;
160 auto fieldNameStr = string(fieldName);
161 auto ret = resultSet->GetColumnIndex(fieldNameStr, index);
162 if (ret != DataShare::E_OK) {
163 LOG_WARN("GetValue [%{public}s] failed [%{public}d]", fieldNameStr.c_str(), ret);
164 return ret;
165 }
166 return resultSet->GetString(index, out);
167 }
168
169
ResultSetToCalendars(DataShareResultSetPtr & resultSet)170 std::vector<std::shared_ptr<Calendar>> ResultSetToCalendars(DataShareResultSetPtr &resultSet)
171 {
172 std::vector<std::shared_ptr<Calendar>> result;
173 int rowCount = 0;
174 resultSet->GetRowCount(rowCount);
175 LOG_INFO("GetRowCount is %{public}d", rowCount);
176 if (rowCount == 0) {
177 return result;
178 }
179 auto err = resultSet->GoToFirstRow();
180 if (err != DataShare::E_OK) {
181 LOG_INFO("Failed GoToFirstRow %{public}d", err);
182 return result;
183 }
184 do {
185 int idValue = -1;
186 if (GetValue(resultSet, "_id", idValue) != DataShare::E_OK) {
187 break;
188 }
189 LOG_DEBUG("id: %{public}d", idValue);
190 std::string nameValue;
191 if (GetValue(resultSet, "account_name", nameValue) != DataShare::E_OK) {
192 break;
193 }
194 LOG_DEBUG("account_name: %{public}s", nameValue.c_str());
195 std::string typeValue;
196 if (GetValue(resultSet, "account_type", typeValue) != DataShare::E_OK) {
197 break;
198 }
199 LOG_DEBUG("account_type: %{public}s", typeValue.c_str());
200
201 std::string displayNameValue;
202 GetValue(resultSet, "calendar_displayName", displayNameValue);
203 LOG_DEBUG("calendar_displayName: %{public}s", displayNameValue.c_str());
204
205 int canReminder = -1;
206 GetValue(resultSet, "canReminder", canReminder);
207 LOG_DEBUG("canReminder: %{public}d", canReminder);
208
209 int colorValue = 0;
210 GetValue(resultSet, "calendar_color", colorValue);
211 LOG_DEBUG("calendar_color: %{public}d", colorValue);
212 CalendarConfig config {canReminder, "todo"};
213 CalendarAccount curAccount {nameValue, typeValue, displayNameValue};
214 result.emplace_back(std::make_shared<Calendar>(curAccount, idValue));
215 } while (resultSet->GoToNextRow() == DataShare::E_OK);
216 return result;
217 }
218
219
ResultSetToLocation(DataShareResultSetPtr & resultSet)220 std::optional<Location> ResultSetToLocation(DataShareResultSetPtr &resultSet)
221 {
222 Location out;
223 string value;
224 auto ret = GetValue(resultSet, "eventLocation", value);
225 out.location = std::make_optional<string>(value);
226 ret = GetValue(resultSet, "location_longitude", value);
227 int longitudeValue = -1;
228 std::stringstream str2digit;
229 str2digit << value;
230 str2digit >> longitudeValue;
231 if (longitudeValue != -1) {
232 out.longitude = std::make_optional<int>(longitudeValue);
233 }
234 ret = GetValue(resultSet, "location_latitude", value);
235 int latitudeValue = -1;
236 str2digit.clear();
237 str2digit << value;
238 str2digit >> latitudeValue;
239 if (latitudeValue != -1) {
240 out.latitude = std::make_optional<int>(latitudeValue);
241 }
242
243 if (ret != DataShare::E_OK) {
244 return std::nullopt;
245 }
246 return std::make_optional<Location>(out);
247 }
248
ResultSetToEventService(DataShareResultSetPtr & resultSet)249 std::optional<EventService> ResultSetToEventService(DataShareResultSetPtr &resultSet)
250 {
251 EventService out;
252 string value;
253 auto ret = GetValue(resultSet, "service_type", value);
254 if (ret != DataShare::E_OK) {
255 return std::nullopt;
256 }
257 out.type = value;
258 ret = GetValue(resultSet, "service_cp_bz_uri", value);
259 if (ret != DataShare::E_OK) {
260 return std::nullopt;
261 }
262 out.uri = value;
263 ret = GetValue(resultSet, "service_description", value);
264 if (ret == DataShare::E_OK) {
265 out.description = std::make_optional<string>(value);
266 }
267 return std::make_optional<EventService>(out);
268 }
269
ResultSetToEvent(Event & event,DataShareResultSetPtr & resultSet)270 void ResultSetToEvent(Event &event, DataShareResultSetPtr &resultSet)
271 {
272 GetValueOptional(resultSet, "_id", event.id);
273 int type = 0;
274 GetValue(resultSet, "event_calendar_type", type);
275 event.type = static_cast<EventType>(type);
276 GetValueOptional(resultSet, "title", event.title);
277 GetValue(resultSet, "dtstart", event.startTime);
278 GetValue(resultSet, "dtend", event.endTime);
279 int isAllDay = 0;
280 GetValue(resultSet, "allDay", isAllDay);
281 event.isAllDay = static_cast<bool>(isAllDay);
282 GetValueOptional(resultSet, "description", event.description);
283 GetValueOptional(resultSet, "eventTimezone", event.timeZone);
284 event.location = ResultSetToLocation(resultSet);
285 event.service = ResultSetToEventService(resultSet);
286 }
287
ResultSetToEvents(std::vector<Event> & events,DataShareResultSetPtr & resultSet,const std::vector<std::string> & columns)288 int ResultSetToEvents(std::vector<Event> &events, DataShareResultSetPtr &resultSet,
289 const std::vector<std::string>& columns)
290 {
291 int rowCount = 0;
292 resultSet->GetRowCount(rowCount);
293 LOG_INFO("GetRowCount is %{public}d", rowCount);
294 if (rowCount <= 0) {
295 return -1;
296 }
297 auto err = resultSet->GoToFirstRow();
298 if (err != DataShare::E_OK) {
299 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
300 return -1;
301 }
302 do {
303 Event event;
304 ResultSetToEvent(event, resultSet);
305 events.emplace_back(event);
306 } while (resultSet->GoToNextRow() == DataShare::E_OK);
307 return 0;
308 }
309
ResultSetToAttendees(std::vector<Attendee> & attendees,DataShareResultSetPtr & resultSet)310 int ResultSetToAttendees(std::vector<Attendee> &attendees, DataShareResultSetPtr &resultSet)
311 {
312 int rowCount = 0;
313 resultSet->GetRowCount(rowCount);
314 LOG_INFO("GetRowCount is %{public}d", rowCount);
315 if (rowCount <= 0) {
316 return -1;
317 }
318 auto err = resultSet->GoToFirstRow();
319 if (err != DataShare::E_OK) {
320 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
321 return -1;
322 }
323 do {
324 Attendee attendee;
325 GetValue(resultSet, "attendeeName", attendee.name);
326 GetValue(resultSet, "attendeeEmail", attendee.email);
327 attendees.emplace_back(attendee);
328 } while (resultSet->GoToNextRow() == DataShare::E_OK);
329 return 0;
330 }
331
ResultSetToReminders(std::vector<int> & reminders,DataShareResultSetPtr & resultSet)332 int ResultSetToReminders(std::vector<int> &reminders, DataShareResultSetPtr &resultSet)
333 {
334 int rowCount = 0;
335 resultSet->GetRowCount(rowCount);
336 LOG_INFO("GetRowCount is %{public}d", rowCount);
337 if (rowCount <= 0) {
338 return -1;
339 }
340 auto err = resultSet->GoToFirstRow();
341 if (err != DataShare::E_OK) {
342 LOG_ERROR("Failed GoToFirstRow %{public}d", err);
343 return -1;
344 }
345 do {
346 int minutes;
347 GetValue(resultSet, "minutes", minutes);
348 reminders.emplace_back(minutes);
349 } while (resultSet->GoToNextRow() == DataShare::E_OK);
350 return 0;
351 }
352
IsValidHexString(const std::string & colorStr)353 bool IsValidHexString(const std::string& colorStr)
354 {
355 if (colorStr.empty()) {
356 return false;
357 }
358 for (char ch : colorStr) {
359 if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
360 continue;
361 }
362 return false;
363 }
364 return true;
365 }
366
ColorParse(const std::string & colorStr,uint32_t & colorValue)367 bool ColorParse(const std::string& colorStr, uint32_t& colorValue)
368 {
369 if (colorStr.empty()) {
370 LOG_ERROR("color string is empty");
371 return false;
372 }
373
374 if (colorStr[0] != '#') { // start with '#'
375 LOG_ERROR("color string not start with #");
376 return false;
377 }
378
379 std::string color = colorStr.substr(1);
380 if (!IsValidHexString(color)) {
381 return false;
382 }
383 char* ptr;
384 colorValue = std::strtoul(color.c_str(), &ptr, 16); // 16 is convert hex string to number
385 if (colorStr.size() == 7) { // 7 #RRGGBB: RRGGBB -> AARRGGBB
386 colorValue |= 0xff000000;
387 return true;
388 }
389 if (colorStr.size() == 9) { // 9 #AARRGGBB
390 return true;
391 }
392 return false;
393 }
394 }