Remove hardcoded path for multiuser support
[platform/core/messaging/msg-service.git] / utils / MsgSqliteWrapper.cpp
1 /*
2 * Copyright 2012-2013  Samsung Electronics Co., Ltd
3 *
4 * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 <stdio.h>
18 #include <stddef.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <sys/stat.h>
23 #include <errno.h>
24 #include <sys/wait.h>
25
26 #include "MsgDebug.h"
27 #include "MsgSqliteWrapper.h"
28
29 extern "C"
30 {
31         #include <db-util.h>
32 }
33
34 #define MSGFW_DB_INIT_SCRIPT    tzplatform_mkpath(TZ_SYS_SHARE,"msg-service/msg_service-init-DB.sh")
35
36 /*==================================================================================================
37                                      VARIABLES
38 ==================================================================================================*/
39 __thread sqlite3 *handle = NULL;
40 __thread sqlite3_stmt *stmt = NULL;
41 //__thread char **result = NULL;
42
43
44 /*==================================================================================================
45                                      IMPLEMENTATION OF MsgDbHandler - Member Functions
46 ==================================================================================================*/
47 MsgDbHandler::MsgDbHandler()
48 {
49         result = NULL;
50 }
51
52
53 MsgDbHandler::~MsgDbHandler()
54 {
55         if(result != NULL)
56                 freeTable();
57 }
58
59 msg_error_t MsgDbHandler::connect()
60 {
61         int ret = 0;
62         struct stat sts;
63
64         if (handle == NULL)
65         {
66                 char strDBName[64];
67
68                 memset(strDBName, 0x00, sizeof(strDBName));
69                 if (strlen(MSGFW_DB_NAME) >= 64){
70                         MSG_DEBUG("DB path is too long");
71                         return MSG_ERR_DB_CONNECT;
72                 }
73                 snprintf(strDBName, 64, "%s", MSGFW_DB_NAME);
74
75                 /* Check if the DB exists; if not, create it and initialize it */
76                 ret = stat(MSGFW_DB_NAME, &sts);
77                 if (ret == -1 && errno == ENOENT){
78                         const char *argv_script[] = {"/bin/sh", MSGFW_DB_INIT_SCRIPT, NULL };
79                         ret = XSystem(argv_script);
80                 }
81
82                 ret = db_util_open(strDBName, &handle, DB_UTIL_REGISTER_HOOK_METHOD);
83
84                 if (ret == SQLITE_OK)
85                 {
86                         MSG_DEBUG("DB Connect Success : [%p]", handle);
87                         return MSG_SUCCESS;
88                 }
89                 else
90                 {
91                         MSG_DEBUG("DB Connect Fail [%d]", ret);
92                         return MSG_ERR_DB_CONNECT;
93                 }
94         }
95         else
96         {
97                 MSG_DEBUG("DB Connect exist : [%p]", handle);
98         }
99
100         return MSG_SUCCESS;
101 }
102
103
104 msg_error_t MsgDbHandler::disconnect()
105 {
106         int ret = 0;
107
108         if (handle != NULL)
109         {
110                 ret = db_util_close(handle);
111
112                 if (ret == SQLITE_OK)
113                 {
114                         handle = NULL;
115                         MSG_DEBUG("DB Disconnect Success");
116                         return MSG_SUCCESS;
117                 }
118                 else
119                 {
120                         MSG_DEBUG("DB Disconnect Fail [%d]", ret);
121                         return MSG_ERR_DB_DISCONNECT;
122                 }
123         }
124
125         return MSG_SUCCESS;
126 }
127
128
129 bool MsgDbHandler::checkTableExist(const char *pTableName)
130 {
131         char strQuery[256];
132         int nRowCnt = 0, nResult = 0;
133
134         /* Formulate the Query */
135         memset(strQuery, 0x00, sizeof(strQuery));
136         snprintf(strQuery, sizeof(strQuery), "select count(name) from sqlite_master where name='%s'", pTableName);
137
138         if (getTable(strQuery, &nRowCnt) != MSG_SUCCESS)
139         {
140                 freeTable();
141                 return false;
142         }
143
144         nResult = getColumnToInt(1);
145         MSG_DEBUG("Result [%d]", nResult);
146
147         freeTable();
148
149         if (nResult > 0)
150                 return true;
151         else
152                 return false;
153 }
154
155
156 msg_error_t MsgDbHandler::execQuery(const char *pQuery)
157 {
158         int ret = 0;
159
160         if (!pQuery)
161                 return MSG_ERR_INVALID_PARAMETER;
162
163         if(connect() != MSG_SUCCESS)
164                 return MSG_ERR_DB_DISCONNECT;
165
166         ret = sqlite3_exec(handle, pQuery, 0, 0, NULL);
167
168         if (ret == SQLITE_OK)
169         {
170                 MSG_DEBUG("Execute Query Success");
171                 return MSG_SUCCESS;
172         }
173         else
174         {
175                 MSG_DEBUG("Execute Query Fail [%d]", ret);
176                 return MSG_ERR_DB_EXEC;
177         }
178
179         return MSG_SUCCESS;
180 }
181
182
183 msg_error_t MsgDbHandler::getTable(const char *pQuery, int *pRowCnt)
184 {
185         int ret = 0;
186
187         *pRowCnt = 0;
188
189         if(connect() != MSG_SUCCESS)
190                 return MSG_ERR_DB_DISCONNECT;
191
192         freeTable();
193         ret = sqlite3_get_table(handle, pQuery, &result, pRowCnt, 0, NULL);
194
195         if (ret == SQLITE_OK)
196         {
197                 if (*pRowCnt == 0)    // when the no record return 'MSG_ERR_DB_NORECORD'
198                 {
199                         MSG_DEBUG("No Query Result");
200                         return MSG_ERR_DB_NORECORD;
201                 }
202
203                 MSG_DEBUG("Get Table Success");
204                 return MSG_SUCCESS;
205         }
206         else
207         {
208                 MSG_DEBUG("Get Table Fail [%d]", ret);
209                 return MSG_ERR_DB_GETTABLE;
210         }
211
212         return MSG_SUCCESS;
213 }
214
215
216 void MsgDbHandler::freeTable()
217 {
218         if (result)
219         {
220                 sqlite3_free_table(result);
221                 result = NULL;
222         }
223 }
224
225
226 msg_error_t MsgDbHandler::bindText(const char *pBindStr, int index)
227 {
228         int ret = 0;
229
230         if (pBindStr != NULL)
231                 ret = sqlite3_bind_text(stmt, index, pBindStr, (strlen(pBindStr) + sizeof(unsigned char)), SQLITE_STATIC);
232
233         return ret;
234 }
235
236
237 msg_error_t MsgDbHandler::bindBlob(const void * pBindBlob, int size, int index)
238 {
239         int ret = 0;
240
241         ret = sqlite3_bind_blob(stmt, index, pBindBlob, size, SQLITE_STATIC);
242
243         return ret;
244 }
245
246
247 msg_error_t MsgDbHandler::prepareQuery(const char *pQuery)
248 {
249         int ret = 0;
250
251         stmt = NULL;
252
253         if(connect() != MSG_SUCCESS)
254                 return MSG_ERR_DB_DISCONNECT;
255
256
257         if ((ret = sqlite3_prepare_v2(handle, pQuery, strlen(pQuery), &stmt, NULL)) == SQLITE_OK)
258         {
259                 MSG_DEBUG("Prepare Query Success");
260                 return MSG_SUCCESS;
261         }
262         else
263         {
264                 MSG_DEBUG("Prepare Query Fail [%d]", ret);
265                 return MSG_ERR_DB_PREPARE;
266         }
267
268         return MSG_SUCCESS;
269 }
270
271
272 msg_error_t MsgDbHandler::stepQuery()
273 {
274         int ret = 0;
275
276         ret = sqlite3_step(stmt);
277
278         if (ret == SQLITE_ROW)
279         {
280                 MSG_DEBUG("MsgStepQuery() SQLITE_ROW");
281                 return MSG_ERR_DB_ROW;
282         }
283         else if (ret == SQLITE_DONE)
284         {
285                 MSG_DEBUG("MsgStepQuery() SQLITE_DONE");
286                 return MSG_ERR_DB_DONE;
287         }
288         else
289         {
290                 MSG_DEBUG("MsgStepQuery() Fail [%d]", ret);
291                 return MSG_ERR_DB_STEP;
292         }
293
294         return MSG_SUCCESS;
295 }
296
297
298 void MsgDbHandler::finalizeQuery()
299 {
300         if(stmt != NULL)
301                 sqlite3_finalize(stmt);
302         stmt = NULL;
303 }
304
305
306 int MsgDbHandler::columnInt(int ColumnIndex)
307 {
308         return sqlite3_column_int(stmt, ColumnIndex);
309 }
310
311
312 const unsigned char* MsgDbHandler::columnText(int ColumnIndex)
313 {
314         return sqlite3_column_text(stmt, ColumnIndex);
315 }
316
317
318 const void* MsgDbHandler::columnBlob(int ColumnIndex)
319 {
320         return sqlite3_column_blob(stmt, ColumnIndex);
321 }
322
323
324 msg_error_t MsgDbHandler::beginTrans()
325 {
326         int ret = 0;
327
328         if(connect() != MSG_SUCCESS)
329                 return MSG_ERR_DB_DISCONNECT;
330
331
332         ret = sqlite3_exec(handle, "BEGIN deferred;", 0, 0, NULL);
333
334         if (ret == SQLITE_OK)
335         {
336                 MSG_DEBUG("Begin Transaction Success");
337                 return MSG_SUCCESS;
338         }
339         else
340         {
341                 MSG_DEBUG("Begin Transaction Fail [%d]", ret);
342                 return MSG_ERR_DB_EXEC;
343         }
344
345         return MSG_SUCCESS;
346 }
347
348
349 msg_error_t MsgDbHandler::endTrans(bool Success)
350 {
351         int ret = 0;
352
353         if(connect() != MSG_SUCCESS)
354                 return MSG_ERR_DB_DISCONNECT;
355
356
357         if (Success == true)
358         {
359                 ret = sqlite3_exec(handle, "END;", 0, 0, NULL);
360         }
361         else
362         {
363                 ret = sqlite3_exec(handle, "rollback", 0, 0, NULL);
364                 ret = sqlite3_exec(handle, "END;", 0, 0, NULL);
365         }
366
367         if (ret == SQLITE_OK)
368         {
369                 MSG_DEBUG("End Transaction Success");
370                 return MSG_SUCCESS;
371         }
372         else
373         {
374                 MSG_DEBUG("End Transaction Fail [%d]", ret);
375                 return MSG_ERR_DB_EXEC;
376         }
377
378         return MSG_SUCCESS;
379 }
380
381
382 int MsgDbHandler::getColumnToInt(int RowIndex)
383 {
384         char* pTemp = result[RowIndex];
385
386         int nTemp = 0;
387
388         if (pTemp == NULL)
389         {
390                 MSG_DEBUG("NULL");
391                 return nTemp;
392         }
393
394         nTemp = (int)strtol(pTemp, (char**)NULL, 10);
395
396         return nTemp;
397 }
398
399
400 char MsgDbHandler::getColumnToChar(int RowIndex)
401 {
402         char* pTemp = result[RowIndex];
403
404         if (pTemp == NULL)
405         {
406                 MSG_DEBUG("NULL");
407                 return '\0';
408         }
409
410         return *pTemp;
411 }
412
413
414 void MsgDbHandler::getColumnToString(int RowIndex, int Length, char *pString)
415 {
416         char* pTemp = result[RowIndex];
417
418         if (pTemp == NULL)
419         {
420                 MSG_DEBUG("NULL");
421                 return;
422         }
423
424         strncpy(pString, pTemp, Length);
425 }
426
427
428 msg_error_t MsgDbHandler::getRowId(const char *pTableName, unsigned int *pRowId)
429 {
430         int ret = 0, nRowId = 0, nRowCnt = 0;
431         char strQuery[256];
432
433         if (pTableName == NULL || pRowId == NULL)
434                 return MSG_ERR_INVALID_PARAMETER;
435
436         MSG_DEBUG("Table Name [%s]", pTableName);
437
438         memset(strQuery, 0x00, sizeof(strQuery));
439         snprintf(strQuery, sizeof(strQuery), "select max(rowid) from %s", pTableName);
440
441         ret = getTable(strQuery, &nRowCnt);
442
443         if (ret == SQLITE_OK)
444         {
445                 nRowId = getColumnToInt(1);
446
447                 if ((nRowCnt <= 1) && (nRowId == 0))
448                         *pRowId = 1;
449                 else
450                         *pRowId = nRowId + 1;
451         }
452         else
453         {
454                 MSG_DEBUG("MsgGetRowId failed");
455                 *pRowId = 0;
456                 freeTable();
457                 return MSG_ERR_DB_GETTABLE;
458         }
459
460         freeTable();
461
462         MSG_DEBUG("Row ID [%d]", *pRowId);
463
464         return MSG_SUCCESS;
465 }
466
467
468 /*==================================================================================================
469                                      FUNCTION IMPLEMENTATION
470 ==================================================================================================*/
471 void MsgReleaseMemoryDB()
472 {
473         int freeSize = 0;
474
475         freeSize = sqlite3_release_memory(-1);
476
477         MSG_DEBUG("freed memory size (bytes) : [%d]", freeSize);
478 }
479
480
481 msg_error_t MsgConvertStrWithEscape(const char *input, char **output)
482 {
483         if (input == NULL || output == NULL || strlen(input) == 0) {
484                 MSG_DEBUG("MSG_ERR_INVALID_PARAMETER");
485                 return MSG_ERR_INVALID_PARAMETER;
486         }
487
488         int inputSize = 0;
489         int i = 0;
490         int j = 0;
491
492         inputSize = strlen(input);
493         MSG_DEBUG("Size of input string [%d]", inputSize);
494
495         char tmpStr[(inputSize*2)+3];
496         memset(tmpStr, 0x00, sizeof(tmpStr));
497
498         tmpStr[j++] = '%';
499
500         for(i=0;i<inputSize;i++) {
501                 if (input[i] == '\'' || input[i] == '_' || input[i] == '%' || input[i] == '\\') {
502                         tmpStr[j++] = MSGFW_DB_ESCAPE_CHAR;
503                 }
504                 tmpStr[j++] = input[i];
505         }
506         tmpStr[j++] = '%';
507         tmpStr[j] = '\0';
508
509         *output = strdup(tmpStr);
510
511         return MSG_SUCCESS;
512 }
513
514 int XSystem(const char *argv[])
515 {
516         int status = 0;
517         pid_t pid;
518         pid = fork();
519         switch (pid) {
520         case -1:
521                 perror("fork failed");
522                 return -1;
523         case 0:
524                 /* child */
525                 execvp(argv[0], (char *const *)argv);
526                 _exit(-1);
527         default:
528                 /* parent */
529                 break;
530         }
531         if (waitpid(pid, &status, 0) == -1) {
532                 perror("waitpid failed");
533                 return -1;
534         }
535         if (WIFSIGNALED(status)) {
536                 perror("signal");
537                 return -1;
538         }
539         if (!WIFEXITED(status)) {
540                 /* shouldn't happen */
541                 perror("should not happen");
542                 return -1;
543         }
544         return WEXITSTATUS(status);
545 }