Adding DLM feature 28/145528/4
authorSaulo Moraes <s.moraes@samsung.com>
Tue, 22 Aug 2017 17:13:53 +0000 (14:13 -0300)
committerSaulo Aldighieri Moraes <s.moraes@samsung.com>
Fri, 25 Aug 2017 19:19:38 +0000 (16:19 -0300)
Change-Id: Ic6612ca4cb4dede3a5eeab02ff86c500759bff93

65 files changed:
CMakeLists.txt
ahocorasick/ahocorasick.c [new file with mode: 0644]
ahocorasick/ahocorasick.h [new file with mode: 0644]
ahocorasick/node.c [new file with mode: 0644]
ahocorasick/node.h [new file with mode: 0644]
ahocorasick/types.h [new file with mode: 0644]
client/CMakeLists.txt
client/inc/DlpLogsManager.h [new file with mode: 0644]
client/inc/DlpPacketParser.h [new file with mode: 0644]
client/inc/DlpPacketParserResult.h [new file with mode: 0644]
client/inc/DlpRulesManager.h [new file with mode: 0644]
client/inc/PrivacyChecker.h
client/inc/PrivacyGuardClient.h [changed mode: 0755->0644]
client/inc/SocketClient.h
client/src/DlpLogsManager.cpp [new file with mode: 0644]
client/src/DlpPacketParser.cpp [new file with mode: 0644]
client/src/DlpRulesManager.cpp [new file with mode: 0644]
client/src/PrivacyChecker.cpp
client/src/PrivacyGuardClient.cpp [changed mode: 0755->0644]
client/src/SocketClient.cpp
client/src/privacy_guard_client.cpp [changed mode: 0755->0644]
client/src/privacy_guard_client_internal_types.h
client/src/privacy_guard_dlp.cpp [new file with mode: 0644]
common/inc/DlpUtils.h [new file with mode: 0644]
common/inc/IPrivacyGuard.h
common/inc/PrivacyGuardCommon.h
common/inc/PrivacyGuardTypes.h [changed mode: 0755->0644]
common/inc/PrivacyIdInfo.h
common/inc/SocketConnection.h
common/inc/SocketStream.h
common/inc/Utils.h
common/src/DlpUtils.cpp [new file with mode: 0644]
common/src/PrivacyIdInfo.cpp
common/src/SocketConnection.cpp
common/src/SocketStream.cpp
common/src/Utils.cpp
common/src/pg_strlcpy.c [new file with mode: 0644]
include/privacy_guard_client.h
include/privacy_guard_client_types.h [changed mode: 0755->0644]
include/privacy_guard_dlp.h [new file with mode: 0644]
packaging/privacy-guard.spec
res/usr/bin/privacy_guard_db.sql [changed mode: 0755->0644]
server/CMakeLists.txt
server/inc/CynaraService.h
server/inc/DlpPrivacyInfoData.h [new file with mode: 0644]
server/inc/DlpRuleChangeNotification.h [new file with mode: 0644]
server/inc/ICommonDb.h
server/inc/PrivacyGuardDaemon.h
server/inc/PrivacyGuardDb.h
server/inc/PrivacyInfoService.h
server/inc/SocketService.h
server/inc/privacy_guard_daemon.h
server/src/CynaraService.cpp
server/src/DlpRuleChangeNotification.cpp [new file with mode: 0644]
server/src/PrivacyGuardDaemon.cpp
server/src/PrivacyGuardDb.cpp [changed mode: 0755->0644]
server/src/SocketService.cpp
server/src/main.cpp
server/src/privacy_guard_daemon.cpp
server/src/service/DlpPrivacyInfoData.cpp [new file with mode: 0644]
server/src/service/PrivacyInfoService.cpp
test/CMakeLists.txt [changed mode: 0755->0644]
test/tc-dlp-performance.c [new file with mode: 0644]
test/tc-dlp.c [new file with mode: 0644]
test/tc-privacy-guard.c

index 9d20264..1b2672f 100755 (executable)
@@ -17,4 +17,4 @@ ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"")
 ADD_SUBDIRECTORY(server)
 ADD_SUBDIRECTORY(client)
 ADD_SUBDIRECTORY(pkgmgr_plugin)
-ADD_SUBDIRECTORY(test)
+ADD_SUBDIRECTORY(test)
\ No newline at end of file
diff --git a/ahocorasick/ahocorasick.c b/ahocorasick/ahocorasick.c
new file mode 100644 (file)
index 0000000..e4e1ac3
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       ahocorasick.c
+ * @brief      API level functions for aho-corasick
+ */
+
+#include <stdlib.h>
+#include "node.h"
+
+ac_instance *ahocorasick_init()
+{
+       ac_instance *ac = (ac_instance *)malloc(sizeof(ac_instance));
+       memset(ac, 0, sizeof(ac_instance));
+       return ac;
+}
+
+int ahocorasick_add_string(ac_instance *ac, const char *string, void *user_data)
+{
+       add_node(ac, string, user_data);
+       return ac->added;
+}
+
+void ahocorasick_set_text(ac_instance *ac, const char *text, size_t textlen, int cont)
+{
+       ac->text = text;
+       ac->textlen = textlen;
+       if (!cont)
+               clear_sposns(ac->root);
+       ac->offs = 0;
+}
+
+ac_match *ahocorasick_find_next(ac_instance *ac)
+{
+       if (ac->match != NULL) {
+               free(ac->match);
+               ac->match = NULL;
+       }
+
+       while (ac->match == NULL && ac->offs < ac->textlen) {
+               ac->match = parse_char(ac->text[ac->offs], ac->offs, ac->root);
+               if (ac->match == NULL) {
+                       reset_checks(ac->root);
+                       ac->offs++;
+               }
+       }
+
+       return ac->match;
+}
+
+void ahocorasick_free(ac_instance *ac)
+{
+       if (ac->match != NULL)
+               free(ac->match);
+
+       if (ac->root != NULL)
+               tree_free(ac->root);
+
+       free(ac);
+}
+
diff --git a/ahocorasick/ahocorasick.h b/ahocorasick/ahocorasick.h
new file mode 100644 (file)
index 0000000..2c87847
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       ahocorasick.h
+ * @brief      API level functions for aho-corasick
+ */
+
+#ifndef _AHOCORASICK_AHOCORASICK_H_
+#define _AHOCORASICK_AHOCORASICK_H_
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @fn                                 ac_instance *ahocorasick_init()
+ * @brief                              Create a new aho-corasick instance. It should freed with ahocorasick_free() when no longer needed.
+ * @return                             The new instance
+ * @callgraph
+ */
+EXTERN_API ac_instance *ahocorasick_init(void);
+
+/**
+ * @fn                                         int ahocorasick_add_string(ac_instance *ac, const char *string, void *user_data)
+ * @brief                              Add another string to the list for matching *
+ * @param[in] ac               An instance returned from ahocorasick_init()
+ * @param[in] string   The string to add
+ * @param[in] user_data        User data to associate with any resulting matches
+ * @return                             Count of total strings added
+ * @callgraph
+ */
+EXTERN_API int ahocorasick_add_string(ac_instance *ac, const char *string, void *user_data);
+
+/**
+ * @fn                                 void ahocorasick_set_text(ac_instance *ac, const char *text, size_t textlen, int cont)
+ * @brief                              Set the text to be scanned for matches
+ * @param[in] ac               An instance returned from ahocorasick_init()
+ * @param[in] text             The text to be scanned
+ * @param[in] textlen   The length of the text to be scanned, in bytes
+ * @param[in] cont             if 0 then all partial matches are reset before scanning the packet
+ * @callgraph
+ */
+EXTERN_API void ahocorasick_set_text(ac_instance *ac, const char *text, size_t textlen, int cont);
+
+/**
+ * @fn                                 ac_match *ahocorasick_find_next(ac_instance *ac)
+ * @brief                              Find the next match in the text
+ * @param[in] ac        An instance returned from ahocorasick_init()
+ * @return                             The next match in the text, or NULL. Matches are returned
+ *                                             in the order in which they end in the text, in alphanumeric order.
+ * @callgraph
+ */
+EXTERN_API ac_match *ahocorasick_find_next(ac_instance *ac);
+
+/**
+ * @fn                                         oid ahocorasick_free(ac_instance *ac);
+ * @brief                              Free an ahocorasick instance
+ * @param[in] ac        An instance returned from ahocorasick_init()
+ * @callgraph
+ */
+EXTERN_API void ahocorasick_free(ac_instance *ac);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_AHOCORASICK_AHOCORASICK_H_
+
diff --git a/ahocorasick/node.c b/ahocorasick/node.c
new file mode 100644 (file)
index 0000000..1b2dd9e
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       node.c
+ * @brief      Low level functions for aho-corasick API
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "ahocorasick.h"
+#include "node.h"
+
+#define CASE_INSENSITIVE
+
+/**
+   Create a new node using the given rule id and text string
+ */
+static ac_node *new_node(void *user_data, const char *text)
+{
+       ac_node *node = (ac_node *)malloc(sizeof(ac_node));
+       memset(node, 0, sizeof(ac_node));
+       node->branch = strdup(text);
+       node->user_data = user_data;
+       node->is_match = TRUE;
+       return node;
+}
+
+/**
+   Append child (leaf) node to parent at position idx
+ */
+static void add_child(ac_node *parent, int idx, ac_node *child)
+{
+
+       int nleaves = 2;
+       int i;
+       ac_node **old_leaves = parent->leaves;
+       if (parent->leaves != NULL) {
+               while (parent->leaves[nleaves - 2] != NULL)
+                       nleaves++;
+       }
+       parent->leaves = (ac_node **)malloc(nleaves * sizeof(ac_node *));
+       if (parent->leaves != NULL) {
+               for (i = 0; i < nleaves - 1; i++) {
+                       if (i < idx)
+                               parent->leaves[i] = old_leaves[i];
+                       else if (i == idx)
+                               parent->leaves[i] = child;
+                       else
+                               parent->leaves[i] = old_leaves[i - 1];
+               }
+               parent->leaves[i] = NULL;
+       }
+       child->stem = parent;
+       free(old_leaves);
+}
+
+/**
+       Compare string s1 with string s2
+       return value:
+        0                              => s1 before s2
+        -1                     => s1 after s2
+        other values   => Number of initial letters in common
+*/
+static int compare(const char *s1, const char *s2)
+{
+       int i;
+       size_t commonlen, s2len;
+
+       if (strlen(s1) == 0)
+               return 0;
+
+       if (strlen(s2) == 0)
+               return -1;
+
+#ifdef CASE_INSENSITIVE
+       if (tolower(s1[0]) < tolower(s2[0]))
+               return 0;
+
+       if (tolower(s2[0]) < tolower(s1[0]))
+               return -1;
+
+#else
+       if (s1[0] < s2[0])
+               return 0;
+
+       if (s2[0] < s1[0])
+               return -1;
+
+#endif
+       commonlen = strlen(s1);
+       if ((s2len = strlen(s2)) < commonlen)
+               commonlen = s2len;
+
+       for (i = 1; i < commonlen; i++) {
+#ifdef CASE_INSENSITIVE
+               if (tolower(s1[i]) != tolower(s2[i]))
+                       return i;
+#else
+               if (s1[i] != s2[i])
+                       return i;
+#endif
+       }
+       return commonlen;
+}
+
+/**
+   Create a match from the given id, position and length
+*/
+static ac_match *create_match(void *user_data, int pos, int size)
+{
+       ac_match *match = (ac_match *)malloc(sizeof(ac_match));
+
+       if(match) {
+               match->user_data = user_data;
+               match->position = pos;
+               match->size = size;
+       }
+
+       return match;
+}
+
+/**
+   Add to the total of possible start positions for children. The value count is added to node and all of its ancestors.
+   When checking for matches we only check the children of a node if this value is > 0. This avoids parsing the entire tree.
+*/
+static void ancestors_increment_sposns(ac_node *node, int count)
+{
+       while (node != NULL) {
+               node->child_sposns += count;
+               node = node->stem;
+       }
+}
+
+/**
+   Subtract from the count of possible start positions for children. The value count is subtracted from all of the ancestors of node.
+   When checking for matches we only check the children of a node if this value is > 0. This avoids parsing the entire tree.
+*/
+static void ancestors_decrement_sposns(ac_node *node, int count)
+{
+       node = node->stem;
+       while (node != NULL) {
+               node->child_sposns -= count;
+               node = node->stem;
+       }
+}
+
+/**
+   Add a new entry to the list of possible start positions for the string fragment contained in node.
+*/
+static void add_sposn(ac_node *node, int offs)
+{
+       int *old_sposns = node->sposns;
+       int i;
+
+       /* do not add same position twice */
+       if (node->nsposns > 0 && node->sposns[0] == offs)
+               return;
+
+       node->nsposns++;
+       node->sposns = (int *)malloc(node->nsposns * sizeof(int));
+
+       if(node->sposns) {
+               node->sposns[0] = offs;
+
+               for (i = 1; i < node->nsposns; i++)
+                       node->sposns[i] = old_sposns[i - 1];
+       }
+
+       if (old_sposns != NULL)
+               free(old_sposns);
+
+}
+
+/**
+   If a character does not match with the string fragment + offset then we mark the corresponding possible start position as invalid.
+   in this function we remove all invalid start positions from the node.
+*/
+static void clean_bad_sposns(ac_node *node)
+{
+       int *old_sposns = node->sposns;
+       int nbad = 0;
+       int i, j = 0;
+
+       for (i = 0; i < node->nsposns; i++) {
+               if (node->sposns[i] == -1)
+                       nbad++;
+       }
+
+       if (nbad == 0)
+               return;
+
+       ancestors_decrement_sposns(node, nbad);
+       node->nsposns -= nbad;
+
+       if (node->nsposns == 0) {
+               node->sposns = NULL;
+       } else {
+               node->sposns = (int *)malloc(node->nsposns * sizeof(int));
+
+               for (i = 0; i < node->nsposns; i++) {
+                       while (old_sposns[j] == -1)
+                               j++;
+
+                       node->sposns[i] = old_sposns[j++];
+               }
+       }
+       free(old_sposns);
+}
+
+/**
+   Here we get the total length of the string calculated from the length of the current node fragment plus all of its ancestors
+*/
+static int get_totlen(ac_node *node)
+{
+       size_t len = strlen(node->branch);
+       while (node->stem != NULL) {
+               node = node->stem;
+               len += strlen(node->branch);
+       }
+       return (int)len;
+}
+
+void add_node(ac_instance *ac, const char *string, void *user_data)
+{
+       char *ptr = (char *)string;
+       ac_node *node = ac->root, *xnode;
+       int finished = 0;
+       int res;
+       int i = 0;
+
+       while (!finished) {
+               if (node != NULL && node->leaves != NULL) {
+                       /* starting with the root node, we look at each leaf in turn */
+                       for (i = 0; (xnode = node->leaves[i]) != NULL; i++) {
+                               /* we have 3 possibilities:
+                                * a) xnode->branch < text : go to next
+                                * b) xnode->branch and text have some letters in common
+                                *  - if common is all of branch, remove branch and check leaves
+                                *  - if common is l.t branch, common part becomes node, and branch and node become children
+                                * c) xnode->branch > text, insert node before xnode */
+
+                               res = compare(xnode->branch, ptr);
+
+                               if (res == 0)
+                                       /* xnode before new node */
+                                       continue;
+
+                               if (res == -1) {
+                                       /* xnode after new node */
+                                       xnode = new_node(user_data, (const char *)ptr);
+                                       ac->added++;
+                                       add_child(node, i, xnode);
+                               } else {
+                                       ac_node *child1;
+                                       /* res letters were in common */
+                                       if (res == strlen(xnode->branch)) {
+                                               /* all letters in common, so now we check the leaves */
+                                               node = xnode;
+                                               ptr += res;
+                                               if (strlen(ptr) == 0) {
+                                                       /* duplicate string */
+                                                       node->user_data = user_data;
+                                                       node->is_match = TRUE;
+                                                       return;
+                                               }
+                                               /* leave for() loop and continue in while (!finished) */
+                                               i = 0;
+                                               break;
+                                       }
+                                       /* the common part was l.t. all
+                                        * the common part becomes the new node
+                                        * we add both this node with all its children and the new node as children */
+                                       child1 = new_node(xnode->user_data, (const char *)(xnode->branch + res));
+                                       child1->leaves = xnode->leaves;
+                                       child1->stem = xnode;
+                                       if (child1->leaves != NULL) {
+                                               for (i = 0; (node = child1->leaves[i]) != NULL; i++) {
+                                                       /* adjust stems for each of these */
+                                                       node->stem = child1;
+                                               }
+                                       }
+                                       /* remove xnodes leaves and shorten its text */
+                                       memset(xnode->branch + res, 0, 1);
+
+                                       if (strlen(ptr) > res) {
+                                               ac_node *child2;
+                                               /* remainder of new string is added as child2 */
+                                               xnode->is_match = FALSE;
+                                               xnode->leaves = (ac_node **)malloc(3 * sizeof(ac_node *));
+                                               if (xnode->leaves != NULL) {
+                                                 child2 = new_node(user_data, (const char *)(ptr + res));
+                                                 ac->added++;
+                                                 child2->stem = xnode;
+
+                                                 res = compare(child1->branch, child2->branch);
+                                                 if (res == 0) {
+                                                       /* child1 before child2 */
+                                                       xnode->leaves[0] = child1;
+                                                       xnode->leaves[1] = child2;
+                                                 } else {
+                                                       /* child1 before child2 */
+                                                       xnode->leaves[0] = child2;
+                                                       xnode->leaves[1] = child1;
+                                                 }
+                                                 xnode->leaves[2] = NULL;
+                                               }
+                                       } else {
+                                               /* the common part consumed all of new string, so we only have 1 child to add */
+                                               xnode->leaves = (ac_node **)malloc(2 * sizeof(ac_node *));
+                                               if (xnode->leaves != NULL) {
+                                                 xnode->user_data = user_data;
+                                                 xnode->leaves[0] = child1;
+                                                 xnode->leaves[1] = NULL;
+                                               }
+                                       }
+                               }
+                               return;
+                       }
+               }
+               finished = 1;
+       }
+
+       /* we checked all children and none were after ptr */
+       xnode = new_node(user_data, (const char *)ptr);
+       ac->added++;
+       if (ac->root == NULL) {
+               /* new root - make a root node and add us as a leaf */
+               node = ac->root = new_node(NULL, "");
+               ac->root->is_match = FALSE;
+       }
+       add_child(node, i, xnode);
+}
+
+/**
+ * @callgraph
+ */
+ac_match *parse_char(char ch, int offs, ac_node *node)
+{
+       ac_match *acm = NULL;
+       ac_node *xnode;
+       size_t brlen;
+       int child_sposns = 0;
+       int i, j;
+
+       if (node->checked)
+               return NULL;
+
+       brlen = strlen(node->branch);
+       if (brlen > 0) {
+#ifdef CASE_INSENSITIVE
+               if (node->stem->stem == NULL && tolower(node->branch[0]) == tolower(ch)) {
+                       /* leaf of root node, and first char matched, start a new sposn */
+                       add_sposn(node, offs);
+               }
+#else
+               if (node->stem->stem == NULL && node->branch[0] == ch) {
+                       /* leaf of root node, and first char matched, start a new sposn */
+                       add_sposn(node, offs);
+               }
+#endif
+               if (node->nsposns > 0) {
+                       /* first check the ongoing matches in sposns */
+                       for (i = 0; i < node->nsposns; i++) {
+                               if (node->sposns[i] > offs)
+                                       continue;
+
+#ifdef CASE_INSENSITIVE
+                               if (tolower(node->branch[offs - node->sposns[i]]) != tolower(ch)) {
+                                       /* mark for removal */
+                                       node->sposns[i] = -1;
+                               } else {
+#else
+                               if (node->branch[offs - node->sposns[i]] != ch) {
+                                       /* mark for removal */
+                                       node->sposns[i] = -1;
+                               } else {
+#endif
+                                       /* continuing match */
+                                       if (offs - node->sposns[i] == brlen - 1) {
+                                               /* the entirety of this branch was matched */
+                                               if (node->leaves == NULL || node->is_match) {
+                                                       /* we got a match ! */
+                                                       int totlen = get_totlen(node);
+                                                       acm = create_match(node->user_data, node->sposns[i] - totlen + brlen, totlen);
+                                               }
+                                               if (node->leaves != NULL) {
+                                                       /* otherwise place possible matches at next char for all children */
+                                                       for (j = 0; (xnode = node->leaves[j]) != NULL; j++) {
+                                                               add_sposn(xnode, offs + 1);
+                                                               child_sposns++;
+                                                       }
+                                               }
+                                               /* mark for removal */
+                                               node->sposns[i] = -1;
+                                       }
+                               }
+                       }
+               }
+
+               /* after checking all sposns we clean up bad matches */
+               clean_bad_sposns(node);
+       }
+
+
+       if (acm == NULL) {
+               if (node->leaves != NULL && (brlen == 0 || node->child_sposns != 0)) {
+                       /* starting from the root, we look at each leaf in turn and check for matches
+                        * (skip if there are no child_sposns, to avoid parsing the whole tree) */
+                       for (i = 0; (xnode = node->leaves[i]) != NULL; i++) {
+                               acm = parse_char(ch, offs, xnode);
+                               if (acm != NULL)
+                                       return acm;
+                       }
+               }
+       }
+
+       /* increase child sposn count for node and all ancestors */
+       if (child_sposns != 0)
+               ancestors_increment_sposns(node, child_sposns);
+
+       /* mark this node as checked for this position */
+       node->checked = 1;
+       return acm;
+}
+
+void reset_checks(ac_node *node)
+{
+       int i;
+       node->checked = 0;
+       if (node->leaves != NULL) {
+               ac_node *xnode;
+
+               for (i = 0; (xnode = node->leaves[i]) != NULL; i++)
+                       reset_checks(xnode);
+       }
+}
+
+void tree_free(ac_node *node)
+{
+       int i;
+       if (node->branch != NULL)
+               free(node->branch);
+
+       if (node->leaves != NULL) {
+               ac_node *xnode;
+
+               for (i = 0; (xnode = node->leaves[i]) != NULL; i++)
+                       tree_free(xnode);
+
+               free(node->leaves);
+       }
+
+       free(node);
+}
+
+void dump_tree(ac_node *node)
+{
+       int i;
+       ac_node *xnode;
+       printf("%s (%p)", node->branch, node->user_data);
+
+       if (node->leaves == NULL) {
+               printf("\n");
+               return;
+       }
+
+       printf(" ");
+
+       for (i = 0; (xnode = node->leaves[i]) != NULL; i++)
+               dump_tree(xnode);
+}
+
+void clear_sposns(ac_node *node)
+{
+       int i;
+
+       if (node == NULL)
+               return;
+
+       if (node->sposns != NULL)
+               free(node->sposns);
+
+       node->nsposns = 0;
+       node->child_sposns = 0;
+
+       if (node->leaves != NULL) {
+               ac_node *xnode;
+
+               for (i = 0; (xnode = node->leaves[i]) != NULL; i++)
+                       clear_sposns(xnode);
+       }
+}
diff --git a/ahocorasick/node.h b/ahocorasick/node.h
new file mode 100644 (file)
index 0000000..6ca983b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       node.h
+ * @brief      low level functions for aho-corasick
+ */
+
+#ifndef _AHOCORASICK_NODE_H_
+#define _AHOCORASICK_NODE_H_
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @fn                                 void add_node(ac_instance *ac, const char *string, void *user_data)
+ * @brief                              Add a new node to the tree
+ * @param[in] ac        The instance whose root to create / add to
+ * @param[in] string   The string to add
+ * @param[in] user_data User data to associate with any resulting matches
+ * @callgraph
+ */
+void add_node(ac_instance *ac, const char *string, void *user_data);
+
+/**
+ * @fn                                 ac_match *parse_char(char ch, int offs, ac_node *node)
+ * @brief                              Parse char at offs in the source text, using the tree rooted at node
+ * @param[in] ch        The character at offs in the source text
+ * @param[in] offs      The offset of the character in the source text
+ * @param[in] node      The root of the tree to be parsed
+ * @return                             The next match at position offs, or NULL if no more matches.
+ * @callgraph
+ */
+ac_match *parse_char(char ch, int offs, ac_node *node);
+
+/**
+ * @fn                                 void clear_sposns(ac_node *node)
+ * @brief                              Clear potential start positions from the tree nodes. This is called when a new non-continuous text packet is sent.
+ * @param[in] node      The root of the tree to be parsed
+ * @callgraph
+ */
+void clear_sposns(ac_node *node);
+
+/**
+ * @fn                                 void tree_free(ac_node *node)
+ * @brief                              Free a tree of string fragments
+ * @param[in] node      The root of the tree to be freed
+ * @callgraph
+ */
+void tree_free(ac_node *node);
+
+/**
+ * @fn                                 void reset_checks(ac_node *node)
+ * @brief                              Each node is marked checked as the tree is traversed. When there are no more matches
+ *                                             at a position, this function is called to clear the checks.
+ * @param[in] node      the root of the tree to be traversed.
+ * @callgraph
+ */
+void reset_checks(ac_node *node);
+
+/**
+ * @fn                                 void dump_tree(ac_node *node)
+ * @brief                              This is a test function which prints out the current tree of string fragments.
+ * @param[in] node      The root of the tree to be traversed.
+ * @callgraph
+ */
+void dump_tree(ac_node *node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_AHOCORASICK_NODE_H_
diff --git a/ahocorasick/types.h b/ahocorasick/types.h
new file mode 100644 (file)
index 0000000..de40ad3
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       types.h
+ * @brief      type definitions for aho-corasick
+ */
+
+#ifndef _AHOCORASICK_TYPES_H_
+#define _AHOCORASICK_TYPES_H_
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef EXTERN_API
+#define EXTERN_API __attribute__((visibility("default")))
+#endif
+
+typedef struct _ac_node ac_node;
+typedef int boolean;
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+struct _ac_node {
+       void *user_data;        ///< the user_data which was added with the string
+       boolean is_match;       ///< is this node the terminal of some match
+       ac_node *stem;          ///< node which this is a leaf of (or NULL)
+       char *branch;           ///< differential text following stem
+       ac_node **leaves;       ///< various bits of text which can be appended to stem | branch
+       int *sposns;            ///< used during matching - possible start positions of this branch
+       int nsposns;            ///< number of sposns
+       int child_sposns;       ///< number of sposns of descendents
+       int checked;            ///< if the node has been checked for the current position
+};
+
+typedef struct {
+       int position;           ///< position in source text of start of match (bytes)
+       int size;                       ///< the length of the match in bytes
+       void *user_data;        ///< the user_data which was added with the string
+} ac_match;
+
+typedef struct {
+       char const *text;       ///< the data packet to be examined
+       size_t textlen;         ///< the length of the data packet
+       int offs;                       ///< how far we have parsed
+       ac_match *match;        ///< latest match
+       ac_node *root;          ///< pointer to the string matching tree
+       int added;                      ///< how many nodes added
+} ac_instance;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_AHOCORASICK_TYPES_H_
index 8c9f025..116a8fe 100755 (executable)
@@ -1,6 +1,8 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 #PROJECT(privacy-guard-client)
 
+FIND_PACKAGE(Threads REQUIRED)
+
 SET(CMAKE_INSTALL_PREFIX /usr)
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(EXEC_PREFIX "\${prefix}")
@@ -8,7 +10,7 @@ SET(LIBDIR ${LIB_INSTALL_DIR})
 SET(INCLUDEDIR ${INCLUDE_INSTALL_DIR})
 
 INCLUDE(FindPkgConfig)
-pkg_check_modules(privacy-guard-client REQUIRED dlog sqlite3 dbus-1 dbus-glib-1 db-util pkgmgr-info libtzplatform-config)
+pkg_check_modules(privacy-guard-client REQUIRED dlog sqlite3 dbus-1 dbus-glib-1 db-util pkgmgr-info libtzplatform-config libpcre)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
@@ -28,6 +30,7 @@ SET(client_include_dir "${CMAKE_SOURCE_DIR}/client/inc/")
 SET(common_src_dir "${CMAKE_SOURCE_DIR}/common/src/")
 SET(common_include_dir "${CMAKE_SOURCE_DIR}/common/inc/")
 SET(extern_include_dir "${CMAKE_SOURCE_DIR}/include/")
+SET(ahocorasick_dir "${CMAKE_SOURCE_DIR}/ahocorasick/")
 
 ## Additional flag
 ADD_DEFINITIONS("-fvisibility=hidden")
@@ -42,19 +45,35 @@ SET(PRIVACY_GUARD_CLIENT_SOURCES
        ${common_src_dir}/SocketConnection.cpp
        ${common_src_dir}/SocketStream.cpp
        ${common_src_dir}/PrivacyIdInfo.cpp
+       ${common_src_dir}/DlpUtils.cpp
        ${common_src_dir}/Utils.cpp
+       ${common_src_dir}/pg_strlcpy.c
        ${client_src_dir}/SocketClient.cpp
        ${client_src_dir}/PrivacyChecker.cpp
        ${client_src_dir}/PrivacyGuardClient.cpp
        ${client_src_dir}/privacy_guard_client.cpp
+       ${client_src_dir}/privacy_guard_dlp.cpp
+       ${client_src_dir}/DlpPacketParser.cpp
+       ${client_src_dir}/DlpRulesManager.cpp
+       ${client_src_dir}/DlpLogsManager.cpp
+       ${ahocorasick_dir}/ahocorasick.c
+       ${ahocorasick_dir}/node.c
        )
 SET(PRIVACY_GUARD_CLIENT_HEADERS
        ${client_include_dir}/PrivacyChecker.h
        ${client_include_dir}/PrivacyGuardClient.h
+       ${client_include_dir}/DlpPacketParserResult.h
+       ${client_include_dir}/DlpPacketParser.h
        ${client_include_dir}/privacy_guard_client_internal.h
+       ${client_include_dir}/DlpRulesManager.h
+       ${client_include_dir}/DlpLogsManager.h
+       ${ahocorasick_dir}/ahocorasick.h
+       ${ahocorasick_dir}/node.h
+       ${ahocorasick_dir}/types.h
        )
 SET(PRIVACY_GUARD_EXTERN_HEADERS
        ${extern_include_dir}/privacy_guard_client.h
+       ${extern_include_dir}/privacy_guard_dlp.h
        ${extern_include_dir}/privacy_guard_client_types.h
        )
 
@@ -63,7 +82,7 @@ SET(PRIVACY_GUARD_CLIENT_CFLAGS  " ${CFLAGS} -fPIC ")
 
 ADD_DEFINITIONS("-DLOG_TAG=\"PRIVACY-GUARD-CLIENT\"")
 ADD_LIBRARY(privacy-guard-client SHARED ${PRIVACY_GUARD_CLIENT_SOURCES})
-TARGET_LINK_LIBRARIES(privacy-guard-client ${pkgs_LDFLAGS} ${pkgs_LIBRARIES})
+TARGET_LINK_LIBRARIES(privacy-guard-client -pthread ${pkgs_LDFLAGS} ${pkgs_LIBRARIES})
 SET_TARGET_PROPERTIES(privacy-guard-client PROPERTIES COMPILE_FLAGS "${PRIVACY_GUARD_CLIENT_CFLAGS}")
 SET_TARGET_PROPERTIES(privacy-guard-client PROPERTIES SOVERSION ${API_VERSION})
 SET_TARGET_PROPERTIES(privacy-guard-client PROPERTIES VERSION ${VERSION})
@@ -71,7 +90,7 @@ SET_TARGET_PROPERTIES(privacy-guard-client PROPERTIES VERSION ${VERSION})
 
 SET(PC_NAME privacy-guard-client)
 SET(PC_DESCRIPTION "Privacy Guard Client API")
-SET(PC_LDFLAGS -lprivacy-guard-client)
+SET(PC_LDFLAGS -lprivacy-guard-client -lpcre)
 SET(PC_CFLAGS -I\${includedir}/privacy_guard)
 
 CONFIGURE_FILE(../privacy-guard-client.pc.in privacy-guard-client.pc @ONLY)
@@ -79,4 +98,4 @@ CONFIGURE_FILE(../privacy-guard-client.pc.in privacy-guard-client.pc @ONLY)
 INSTALL(TARGETS privacy-guard-client DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/privacy-guard-client.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 INSTALL(FILES ${PRIVACY_GUARD_CLIENT_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/privacy_guard/client)
-INSTALL(FILES ${PRIVACY_GUARD_EXTERN_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/privacy_guard)
\ No newline at end of file
+INSTALL(FILES ${PRIVACY_GUARD_EXTERN_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/privacy_guard)
diff --git a/client/inc/DlpLogsManager.h b/client/inc/DlpLogsManager.h
new file mode 100644 (file)
index 0000000..0c948f9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef _DLPLOGSMANAGER_H_
+#define _DLPLOGSMANAGER_H_
+
+#include <string>
+#include <mutex>
+#include <list>
+#include "DlpPacketParser.h"
+#include "DlpPacketParserResult.h"
+#include "PrivacyGuardClient.h"
+#include "PrivacyGuardTypes.h"
+
+typedef struct _leak_log_queue_entry_s {
+       std::string hostname;
+       char *mem;
+       size_t len;
+       std::list<leak_log_insert_data_s> llist;
+       current_rules_list rlist;
+} leak_log_queue_entry_s;
+
+
+class EXTERN_API DlpLogsManager
+{
+private:
+       static std::mutex m_singletonMutex;
+       static DlpLogsManager *m_pInstance;
+       std::list<leak_log_queue_entry_s> m_logQueue;
+       PrivacyGuardClient *m_privacyGuardClient;
+       std::mutex m_logQueueMutex;
+       std::mutex m_leakLogSendMutex;
+
+       DlpLogsManager();
+       ~DlpLogsManager();
+
+       /**
+        * @fn                                  static void *LeakLogSendThreadFunc(void *_this)
+        * @brief                               Set the rules for the packet parser
+        *
+        * @param[in] _this             Pointer to the object
+        */
+       static void *LeakLogSendThreadFunc(void *_this);
+
+       /**
+        * @fn                                  PgDlpResult ParseAndLogLeakNow(leak_log_queue_entry_s &entry)
+        * @brief                               Set the rules for the packet parser
+        *
+        * @param[in] entry             The leaked information to be verified
+        *
+        * @return                      The overall action to be taken given the individual results,
+        *                              either PRIV_GUARD_DLP_RESULT_ALLOW (all results allow or sanitize),
+        *                              or PRIV_GUARD_DLP_RESULT_DENY.
+        */
+       PgDlpResult ParseAndLogLeakNow(leak_log_queue_entry_s &entry);
+
+public:
+       static DlpLogsManager *getInstance(void);
+       PgDlpResult ParseAndLogLeak(const char *hostname, char *mem, size_t len, const current_rules_list &rules);
+
+protected:
+       virtual void *LeakLogSendThread();
+};
+
+#endif // _DLPLOGSMANAGER_H_
diff --git a/client/inc/DlpPacketParser.h b/client/inc/DlpPacketParser.h
new file mode 100644 (file)
index 0000000..8cd3f5f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpPacketParser.h
+ * @brief      Definitions for DlpPacketParser class and related things.
+ */
+
+#ifndef __DLP_PACKET_PARSER_H__
+#define __DLP_PACKET_PARSER_H__
+
+#include <string>
+#include "PrivacyGuardTypes.h"
+#include "DlpUtils.h"
+
+class DlpPacketParser
+{
+public:
+       DlpPacketParser();
+       ~DlpPacketParser();
+
+       /**
+        * @fn                                  int setRules(const current_rules_list &rules)
+        * @brief                               Set the rules for the packet parser
+        *
+        * @param[in] rules             Pointer to a std::list of current_rules_s.
+        *                      The rules are not copied so they must remain valid while parsePacket() and getAction() are called.
+        *
+        * @return                              count of rules in the list
+        */
+       int setRules(const current_rules_list &rules);
+
+       /**
+        * @fn                                  PgDlpResult parsePacket(char * const pdata, size_t length, DlpPacketParserResultList &rl)
+        * @brief                               Parse a packet of data and return a std::list of DlpPacketParserResult.
+        *                              Before calling this it is necessary to set rules (once) with setRules().
+        *                              After calling this you should call getResult() to sanitize the packet.
+        *
+        * @param[in]  pdata    pointer to the packet data to be parsed. If sanitization is to be performed,
+        *                      the data must not be freed until after getResult() is called.
+        * @param[in]  length   byte length of the packet data to be parsed
+        * @param[out] rl       std::list of DlpPacketParserResult. List may be empty.
+        *
+        * @return                      The overall action to be taken given the individual results,
+        *                              either PRIV_GUARD_DLP_RESULT_ALLOW (all results allow or sanitize),
+        *                              or PRIV_GUARD_DLP_RESULT_DENY.
+        */
+       PgDlpResult parsePacket(char * const pdata, size_t length, DlpPacketParserResultList &rl);
+
+       /**
+        * @fn                                  void sanitize(char * const pdata, size_t length, DlpPacketParserResultList &rl)
+        * @brief                               Get the overall action given a list of DlpPacketParserResult.
+        *
+        * @param[in]  pdata    pointer to the packet data to be parsed. If sanitization is to be performed,
+        *                              the data must not be freed until after getResult() is called.
+        * @param[in]  length   byte length of the packet data to be parsed
+        * @param[in]  rl               std::list of DlpPacketParserResult. List may be empty.
+        *
+        */
+       void sanitize(char * const pdata, size_t length, DlpPacketParserResultList &rl);
+
+private:
+       void cleanup();
+       SUB_PARSER_PTR m_pcre;
+       SUB_PARSER_PTR m_ahocorasick;
+};
+
+#endif /* __DLP_PACKET_PARSER_H__ */
+
+
diff --git a/client/inc/DlpPacketParserResult.h b/client/inc/DlpPacketParserResult.h
new file mode 100644 (file)
index 0000000..329cf74
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpPacketParserResult.h
+ * @brief      Definitions for PrivacyGuardDLPPacketParserResult class and related things.
+ */
+
+#ifndef __DLP_PACKET_PARSER_RESULT_H__
+#define __DLP_PACKET_PARSER_RESULT_H__
+
+#include <string>
+#include <list>
+#include "PrivacyGuardTypes.h"
+
+typedef std::list<class DlpPacketParserResult> DlpPacketParserResultList;
+
+#include "DlpUtils.h"
+
+class DlpPacketParserResult
+{
+       friend void dlp_ac_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl);
+       friend void dlp_pcre_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl);
+       friend class DlpPacketParser;
+
+public:
+       /**
+        * @fn          int getpatternId()
+        * @brief       get the id of the pattern which caused this result match.
+        *
+        * @return  pattern_id
+        *
+        * @see DlpPacketParser::setRules()
+        */
+       int getPatternId()
+       {
+               return m_pattern_id;
+       }
+
+       /**
+        * @fn          PgDlpAction getaction()
+        * @brief       get the action for the rule which caused the match.
+        *
+        * @return  the action
+        *
+        * @see DlpPacketParser::setRules()
+        */
+       PgDlpAction getAction()
+       {
+               return m_action;
+       }
+
+       /**
+        * @fn          int getOffset()
+        * @brief       returns byte offset in buffer of match start
+        *
+        * @return byte offset in buffer of match start
+        */
+       int getOffset()
+       {
+               return m_offset;
+       }
+
+       /**
+        * @fn          int getLength()
+        * @brief       returns length of match in bytes
+        *
+        * @return length of match in bytes
+        */
+       int getLength()
+       {
+               return m_length;
+       }
+
+protected:
+       DlpPacketParserResult(int pattern_id, PgDlpAction action, int offset, int length)
+       {
+               m_pattern_id = pattern_id;
+               m_action = action;
+               m_offset = offset;
+               m_length = length;
+       }
+
+private:
+       int m_pattern_id;
+       PgDlpAction m_action;
+       int m_offset;
+       int m_length;
+};
+
+#endif /* __DLP_PACKET_PARSER_RESULT_H__ */
diff --git a/client/inc/DlpRulesManager.h b/client/inc/DlpRulesManager.h
new file mode 100644 (file)
index 0000000..eb1a5b5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef _DLPRULESMANAGER_H_
+#define _DLPRULESMANAGER_H_
+
+#include <string>
+#include <mutex>
+#include <list>
+#include "PrivacyGuardClient.h"
+#include "PrivacyGuardTypes.h"
+
+class EXTERN_API DlpRulesManager
+{
+private:
+       static std::mutex m_singletonMutex;
+       static DlpRulesManager *m_pInstance;
+       std::list<current_rules_s> m_currentRules;
+       PrivacyGuardClient *m_privacyGuardClient;
+       std::mutex m_rulesMutex;
+
+       DlpRulesManager();
+       ~DlpRulesManager();
+
+       static void *NewRulesNotificationThreadFunc(void *_this);
+
+public:
+       static DlpRulesManager *getInstance(void);
+       std::list<current_rules_s> PgGetDlpCurrentRules();
+
+protected:
+   virtual void *NewRulesNotificationThread();
+};
+
+#endif // _DLPRULESMANAGER_H_
index 87a923a..9f01a8a 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyChecker.h
+ */
+
 #ifndef _PRIVACY_CHECKER_H_
 #define _PRIVACY_CHECKER_H_
 
@@ -49,12 +53,12 @@ private:
 private:
        static int initializeDbus(void);
        static int finalizeDbus(void);
-       static int updateCache(const std::string pkgId, std::string privacyId, std::map < std::string, bool >& pkgCacheMap);
-       static int updateCache(const std::string pkgId, std::map < std::string, bool >& pkgCacheMap);
+       static int updateCache(const std::string pkgId, std::string privacyId, std::map<std::string, bool> &pkgCacheMap);
+       static int updateCache(const std::string pkgId, std::map<std::string, bool> &pkgCacheMap);
        static void printCache(void);
-       static void* runSignalListenerThread(voidpData);
-       static int getCurrentPkgId(std::stringpkgId);
-       static int check(const std::string privacyId, std::map < std::string, bool >& privacyMap);
+       static void* runSignalListenerThread(void *pData);
+       static int getCurrentPkgId(std::string &pkgId);
+       static int check(const std::string privacyId, std::map<std::string, bool> &privacyMap);
 
 public:
        // for Checking in App Process
@@ -73,7 +77,7 @@ public:
 
        // common
        static int finalize(void);
-       static DBusHandlerResult handleNotification(DBusConnection* connection, DBusMessage* message, void* user_data);
+       static DBusHandlerResult handleNotification(DBusConnection *connection, DBusMessage *message, void *user_data);
 };
 
 #endif // _PRIVACY_CHECKER_H_
old mode 100755 (executable)
new mode 100644 (file)
index ce175f9..79c5d92
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyGuardClient.h
+ */
+
 #ifndef _PRIVACYGUARDCLIENT_H_
 #define _PRIVACYGUARDCLIENT_H_
 
 #include "PrivacyGuardTypes.h"
 #include <sqlite3.h>
 
-class SocketClient;
-
 class EXTERN_API PrivacyGuardClient
 {
 private:
-       std::mutex m_dbMutex;
-       sqlite3* m_sqlHandler;
-       sqlite3_stmt* m_stmt;
-       bool m_bDBOpen;
+std::mutex m_dbMutex;
+sqlite3* m_sqlHandler;
+sqlite3_stmt* m_stmt;
+bool m_bDBOpen;
+char m_applicationId[LEN_APPLICATION_ID] = { 0 };
+char m_applicationName[LEN_APPLICATION_NAME] = { 0 };
+char m_applicationVersion[LEN_APPLICATION_VERSION] = { 0 };
+char m_applicationIcon[LEN_APPLICATION_ICON] = { 0 };
+char m_packageId[LEN_PACKAGE_ID] = { 0 };
+
+static PrivacyGuardClient* m_pInstance;
+static const std::string INTERFACE_NAME;
 
-       static PrivacyGuardClient* m_pInstance;
-       static const std::string INTERFACE_NAME;
+static std::mutex m_singletonMutex;
+static char m_categories[MAX_CATEGORIES][LEN_CATEGORY];
 
-       std::unique_ptr< SocketClient > m_pSocketClient;
+PrivacyGuardClient();
+~PrivacyGuardClient();
 
-       static std::mutex m_singletonMutex;
+void loadApplicationInfo();
+int loadDlpCategories(void);
 
-       PrivacyGuardClient();
-       ~PrivacyGuardClient();
+static void category_id_to_text(category_u *category);
+static int category_text_to_id(const char *);
 
 public:
-       static PrivacyGuardClient* getInstance(void);
+static PrivacyGuardClient* getInstance(void);
+
+virtual void openSqliteDB(void);
+
+int PgAddMonitorPolicyOffline(const int userId, const std::string packageId, const std::list < std::string > privacyList, bool monitorPolicy);
+
+int PgAddPrivacyAccessLog(const int userId, const std::string packageId, const std::string privacyId, const time_t accessTime);
+
+int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::list<std::string> &list, int monitorPolicy);
+
+int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int monitorPolicy);
+
+int PgDeleteAllLogs(void);
+
+int PgDeleteLogsByPackageId(const std::string packageId);
+
+int PgDeleteMonitorPolicyByPackageId(const std::string packageId);
+
+int PgForeachTotalPrivacyCountOfPackage(const int userId, const int startDate, const int endDate, std::list < std::pair <std::string, int > > & packageInfoList) const;
+
+int PgForeachTotalPrivacyCountOfPrivacy(const int userId, const int startDate, const int endDate, std::list < std::pair <std::string, int > > & privacyInfoList) const;
+
+int PgForeachPrivacyCountByPrivacyId(const int userId, const int startDate, const int endDate, const std::string privacyId, std::list < std::pair <std::string, int > > & packageInfoList) const;
+
+int PgForeachPrivacyCountByPackageId(const int userId, const int startDate, const int endDate, const std::string packageId, std::list < std::pair <std::string, int > > & privacyInfoList) const;
+
+int PgForeachPackageIdUsingPrivacy(const int userId, std::list < std::string > & packageList) const;
+
+int PgForeachPackageInfoByPrivacyId(const int userId, const std::string privacyId, std::list < package_data_s > & packageList) const;
+
+int PgForeachMonitorPolicyByPackageId(const int userId, const std::string packageId, std::list <privacy_data_s> & privacyInfoList) const;
+
+int PgGetMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int & monitorPolicy) const;
+
+int PgGetAllMonitorPolicy(std::list < std::pair < std::string, int > > & monitorPolicyList) const;
+
+int PgCheckPrivacyPackage(const int userId, const std::string packageId, bool &isPrivacyPackage);
+
+int PgUpdateMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, const int monitorPolicy);
+
+int PgGetMainMonitorPolicy(const int userId, int &mainMonitorPolicy) const;
+
+int PgUpdateMainMonitorPolicy(const int userId, const int mainMonitorPolicy);
 
-       virtual void openSqliteDB(void);
+// DLP features
+int PgAddLeakLog(const int userId, const char *destination, const void *rawPacket, const size_t len, const std::list<leak_log_insert_data_s> &logList) const;
 
-       int PgAddMonitorPolicyOffline(const int userId, const std::string packageId, const std::list < std::string > privacyList, bool monitorPolicy);
+int PgForeachLeakLogs(const int userId, std::list<leak_log_get_data_s> &logList) const;
 
-       int PgAddPrivacyAccessLog(const int userId, const std::string packageId, const std::string privacyId, const time_t accessTime);
+int PgForeachLeakLogsByAppName(const int userId, const char *appName, std::list<leak_log_get_data_s> &logList) const;
 
-       int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::list < std::string >& list, int monitorPolicy);
+int PgForeachLeakLogsByCategory(const int userId, const char *category, std::list<leak_log_get_data_s> &logList) const;
 
-       int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int monitorPolicy);
+int PgForeachAppLeakCount(const int userId, std::list<leak_log_get_app_count_s> &logList) const;
 
-       int PgDeleteAllLogs(void);
+int PgForeachCategoryLeakCount(const int userId, std::list<leak_log_get_category_count_s> &logList) const;
 
-       int PgDeleteLogsByPackageId(const std::string packageId);
+int PgForeachLeakLogsByTimestamp(const int userId, const time_t start, const time_t end, std::list<leak_log_get_data_s> &logList) const;
 
-       int PgDeleteMonitorPolicyByPackageId(const std::string packageId);
+int PgGetLeakLogDetails(int userId, int logId, leak_log_get_detail_data_s *logDetail) const;
 
-       int PgForeachTotalPrivacyCountOfPackage(const int userId, const int startDate, const int endDate, std::list < std::pair <std::string, int > > & packageInfoList) const;
+int PgPurgeLeakLogs(const int userId) const;
 
-       int PgForeachTotalPrivacyCountOfPrivacy(const int userId, const int startDate, const int endDate, std::list < std::pair <std::string, int > > & privacyInfoList) const;
+int PgPurgeLeakLogsByLogId(const std::list<int> &logId) const;
 
-       int PgForeachPrivacyCountByPrivacyId(const int userId, const int startDate, const int endDate, const std::string privacyId, std::list < std::pair <std::string, int > > & packageInfoList) const;
+int PgSetDlpProfile(const int userId, const dlp_profile_s *profile) const;
 
-       int PgForeachPrivacyCountByPackageId(const int userId, const int startDate, const int endDate, const std::string packageId, std::list < std::pair <std::string, int > > & privacyInfoList) const;
+int PgGetDlpProfile(const int userId, dlp_profile_s *profile) const;
 
-       int PgForeachPackageIdUsingPrivacy(const int userId, std::list < std::string > & packageList) const;
+int PgGetDlpCurrentRules(const int userId, const int pId, std::list<current_rules_s> &currentRules) const;
 
-       int PgForeachPackageInfoByPrivacyId(const int userId, const std::string privacyId, std::list < package_data_s > & packageList) const;
+int PgAddDlpCustomRule(int userId, PgDlpAction action, int patternId, const char *ruleName, const char *ruleDescription, const char *applicationId) const;
 
-       int PgForeachMonitorPolicyByPackageId(const int userId, const std::string packageId, std::list <privacy_data_s> & privacyInfoList) const;
+int PgUpdateDlpCustomRule(int ruleId, PgDlpAction action, int patternId, const char *ruleName, const char *ruleDescription, const char *applicationId) const;
 
-       int PgGetMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int& monitorPolicy) const;
+int PgDeleteDlpCustomRule(int ruleId) const;
 
-       int PgGetAllMonitorPolicy(std::list < std::pair < std::string, int > > & monitorPolicyList) const;
+int PgForeachDlpRules(int userId, PgDlpProfile profile, std::list<get_custom_rule_s> &rules) const;
 
-       int PgCheckPrivacyPackage(const int userId, const std::string packageId, bool &isPrivacyPackage);
+int PgAddDlpPattern(const char *name, const char *description, const char *category, const char *pattern, PgDlpPatternType type) const;
 
-       int PgUpdateMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, const int monitorPolicy);
+int PgDeleteDlpPattern(int pattern_id) const;
 
-       int PgGetMainMonitorPolicy(const int userId, int &mainMonitorPolicy) const;
+int PgForeachDlpPatterns(std::list<get_pattern_s> &patterns) const;
 
-       int PgUpdateMainMonitorPolicy(const int userId, const int mainMonitorPolicy);
+int PgForeachDlpCategories(std::list<std::string> &categories) const;
 };
 
-#endif // _PRIVACYGUARDCLIENT_H_
\ No newline at end of file
+#endif // _PRIVACYGUARDCLIENT_H_
index 7e80dda..956e312 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketClient.h
+ */
+
 #ifndef _SOCKETCLIENT_H_
 #define _SOCKETCLIENT_H_
 
@@ -90,13 +94,13 @@ public:
        }
 
        template<typename T>
-       int read(Toutvalue)
+       int read(T *outvalue)
        {
                return m_socketConnector->read(outvalue);
        }
 private:
        template<typename T, typename ...Args>
-       int make_call(const Tinvalue, const Args&... args)
+       int make_call(const T &invalue, const Args&... args)
        {
                int res = make_call(invalue);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "make_call : %d", res);
@@ -107,13 +111,13 @@ private:
        }
 
        template<typename T>
-       int make_call(const Tinvalue)
+       int make_call(const T &invalue)
        {
                return m_socketConnector->write(invalue);
        }
 
        template<typename T, typename ...Args>
-       int make_call(const Tinvalue, const Args&... args)
+       int make_call(const T *invalue, const Args&... args)
        {
                int res = make_call(invalue);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "make_call : %d", res);
@@ -124,13 +128,13 @@ private:
        }
 
        template<typename T>
-       int make_call(const Tinvalue)
+       int make_call(const T *invalue)
        {
                return m_socketConnector->write(invalue);
        }
 
        template<typename T, typename ...Args>
-       int make_call(T * outvalue, const Args&... args)
+       int make_call(T *outvalue, const Args&... args)
        {
                int res = make_call(outvalue);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "make_call : %d", res);
@@ -141,7 +145,7 @@ private:
        }
 
        template<typename T>
-       int make_call(Toutvalue)
+       int make_call(T *outvalue)
        {
                return m_socketConnector->read(outvalue);
     }
@@ -153,4 +157,4 @@ private:
        int m_socketFd;
 };
 
-#endif // _SOCKETCLIENT_H_
\ No newline at end of file
+#endif // _SOCKETCLIENT_H_
diff --git a/client/src/DlpLogsManager.cpp b/client/src/DlpLogsManager.cpp
new file mode 100644 (file)
index 0000000..02e493a
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "DlpLogsManager.h"
+#include "PrivacyGuardClient.h"
+#include "Utils.h"
+
+std::mutex DlpLogsManager::m_singletonMutex;
+DlpLogsManager *DlpLogsManager::m_pInstance = NULL;
+
+DlpLogsManager::DlpLogsManager(void)
+{
+       pthread_t notify_thread;
+       m_privacyGuardClient = PrivacyGuardClient::getInstance();
+
+       // launch leak log send thread
+       m_leakLogSendMutex.lock();
+       if (pthread_create(&notify_thread, NULL, LeakLogSendThreadFunc, this)) {
+               m_leakLogSendMutex.unlock();
+               PG_LOGE("Error creating privacy guard leak log send thread");
+       }
+}
+
+DlpLogsManager*
+DlpLogsManager::getInstance(void)
+{
+       std::lock_guard<std::mutex> guard(m_singletonMutex);
+       if (m_pInstance == NULL)
+               m_pInstance = new(std::nothrow) DlpLogsManager();
+       return m_pInstance;
+}
+
+PgDlpResult
+DlpLogsManager::ParseAndLogLeak(const char *hostname, char *mem, size_t len, const current_rules_list &rules)
+{
+       PgDlpResult res = PRIV_GUARD_DLP_RESULT_ALLOW;
+       leak_log_queue_entry_s entry;
+
+       // populate the entry to be added to the m_logQueue
+       entry.hostname.assign(hostname);
+       entry.mem = new char[len];
+       memcpy(entry.mem, mem, len);
+       entry.len = len;
+       entry.rlist = rules;
+
+       // check if we have only ALLOW actions on the rules list
+       for (auto &it : rules) {
+               if (it.action != PRIV_GUARD_DLP_ACTION_ALLOW) {
+                       // if we have any rule different from ALLOW we need to parse now
+                       res = ParseAndLogLeakNow(entry);
+                       break;
+               }
+       }
+
+       if (!entry.rlist.empty() || !entry.llist.empty()) {
+               // add entry to the m_logQueue to be processed when the thread awakes
+               m_logQueueMutex.lock();
+               m_logQueue.push_back(entry);
+               m_logQueueMutex.unlock();
+
+               // signal the leak log send thread
+               m_leakLogSendMutex.unlock();
+       }
+
+       return res;
+}
+
+PgDlpResult
+DlpLogsManager::ParseAndLogLeakNow(leak_log_queue_entry_s &entry)
+{
+       PgDlpResult res;
+       DlpPacketParser pp;
+       DlpPacketParserResultList results;
+
+       // parse the packet seting the results
+       pp.setRules(entry.rlist);
+       res = pp.parsePacket(entry.mem, entry.len, results);
+
+       // interact over the results looking for detected leaks
+       for (auto &it : results) {
+               leak_log_insert_data_s ll = { it.getPatternId(), it.getAction(), it.getOffset(), it.getLength() };
+               entry.llist.push_back(ll);
+               PG_LOGD("Found Leak: destination: %s, patternid: %d, action: %d, offset: %d, len: %d", entry.hostname.c_str(), it.getPatternId(), it.getAction(), it.getOffset(), it.getLength());
+       }
+
+       // sanitize packet and get the final result
+       pp.sanitize(entry.mem, entry.len, results);
+
+       entry.rlist.clear();
+
+       return res;
+}
+
+void *
+DlpLogsManager::LeakLogSendThreadFunc(void *_this)
+{
+       return ((DlpLogsManager *)_this)->LeakLogSendThread();
+}
+
+void*
+DlpLogsManager::LeakLogSendThread()
+{
+       uid_t uid = getuid();
+
+       for (;;) {
+               // wait for new entries on the queue
+               m_leakLogSendMutex.lock();
+
+               // with new entries, try to process them
+               m_logQueueMutex.lock();
+               for (auto &it : m_logQueue) {
+                       // if packet has not been parsed yet, parse now
+                       if (!it.rlist.empty())
+                               ParseAndLogLeakNow(it);
+
+                       if (!it.llist.empty())
+                               m_privacyGuardClient->PgAddLeakLog(uid, it.hostname.c_str(), it.mem, it.len, it.llist);
+               }
+
+               // all entries processed, call clear destroying each element from queue
+               m_logQueue.clear();
+               m_logQueueMutex.unlock();
+       }
+       return NULL;
+}
diff --git a/client/src/DlpPacketParser.cpp b/client/src/DlpPacketParser.cpp
new file mode 100644 (file)
index 0000000..aaab095
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpPacketParser.cpp
+ * @brief      Implementation of DlpPacketParser class.
+ */
+
+#include "PrivacyGuardTypes.h"
+#include "DlpPacketParserResult.h"
+#include "DlpPacketParser.h"
+#include "Utils.h"
+
+#define DEF_SANITIZE_ALPHA 'X'
+#define DEF_SANITIZE_NUMBER '9'
+
+/**
+   replace detected leak with sanitized characters
+   returns number of characters replaced
+*/
+static int repl_substring(char *data, int datalen, int offset, int leaklen)
+{
+       int i;
+       int leakend = offset + leaklen;
+       for (i = offset; i < datalen && i < leakend; i++) {
+               if ((data[i] >= 'a' && data[i] <= 'z') || (data[i] >= 'A' && data[i] <= 'Z'))
+                       data[i] = DEF_SANITIZE_ALPHA;
+               else if (data[i] >= '0' && data[i] <= '9')
+                       data[i] = DEF_SANITIZE_NUMBER;
+       }
+       return i - offset;
+}
+
+/**
+ * @callgraph
+ */
+void DlpPacketParser::cleanup()
+{
+       if (m_pcre != NULL)
+               dlp_pcre_free(m_pcre);
+
+       if (m_ahocorasick != NULL)
+               dlp_ac_free(m_ahocorasick);
+}
+
+DlpPacketParser::DlpPacketParser()
+{
+       m_pcre = m_ahocorasick = NULL;
+}
+
+DlpPacketParser::~DlpPacketParser()
+{
+       cleanup();
+}
+
+/**
+ * @callgraph
+ */
+int DlpPacketParser::setRules(const current_rules_list &rules)
+{
+       // Received rules are not copied (duplicated), so it is up to the caller to not
+       // free them until they are no longer needed
+       int str_count = 0;
+       int regex_count = 0;
+
+       cleanup();
+
+       m_pcre = dlp_pcre_init();
+       m_ahocorasick = dlp_ac_init();
+
+       // Iterate through rules, and add any strings to ahocorasick, add any regex to pcre
+       for (auto &it : rules) {
+               switch (it.type) {
+               case PRIV_GUARD_DLP_PATTERN_STRING:
+                       str_count = dlp_ac_add_string(m_ahocorasick, it.pattern, (void *)&it);
+                       break;
+
+               case PRIV_GUARD_DLP_PATTERN_REGEX:
+                       regex_count = dlp_pcre_add_pattern(m_pcre, it.pattern, (void *)&it);
+                       break;
+
+               default:
+                       PG_LOGE("Pattern search type unknown (not string or regex)");
+                       break;
+               }
+       }
+
+       return str_count + regex_count;
+}
+
+/**
+ * @callgraph
+ */
+PgDlpResult DlpPacketParser::parsePacket(char * const pdata, size_t length, DlpPacketParserResultList &rl)
+{
+       if (m_ahocorasick != NULL) {
+               // Search for string match
+               dlp_ac_search(m_ahocorasick, pdata, length, rl);
+       }
+
+       if (m_pcre != NULL) {
+               // Regex search
+               dlp_pcre_search(m_pcre, pdata, length, rl);
+       }
+
+       for (auto &it : rl) {
+               if (it.getAction() == PRIV_GUARD_DLP_ACTION_DENY)
+                       return PRIV_GUARD_DLP_RESULT_DENY;
+       }
+
+       return PRIV_GUARD_DLP_RESULT_ALLOW;
+}
+
+/**
+ * @callgraph
+ */
+void DlpPacketParser::sanitize(char * const pdata, size_t length, DlpPacketParserResultList &rl)
+{
+       PgDlpAction act;
+
+       for (auto &it : rl) {
+               if ((act = it.getAction()) == PRIV_GUARD_DLP_ACTION_DENY)
+                       return;
+               if (act == PRIV_GUARD_DLP_ACTION_SANITIZE)
+                       repl_substring(pdata, length, it.getOffset(), it.getLength());
+       }
+}
diff --git a/client/src/DlpRulesManager.cpp b/client/src/DlpRulesManager.cpp
new file mode 100644 (file)
index 0000000..24082c1
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "DlpRulesManager.h"
+#include "Utils.h"
+
+#define BUF_SIZE 256
+
+std::mutex DlpRulesManager::m_singletonMutex;
+DlpRulesManager *DlpRulesManager::m_pInstance = NULL;
+
+DlpRulesManager::DlpRulesManager(void)
+{
+       pthread_t notify_thread;
+       m_privacyGuardClient = PrivacyGuardClient::getInstance();
+
+       // Launch privacy guard notification thread
+       m_rulesMutex.lock();
+       if(pthread_create(&notify_thread, NULL, NewRulesNotificationThreadFunc, this)) {
+               m_rulesMutex.unlock();
+               PG_LOGE("Error creating privacy guard notification thread");
+       }
+}
+
+DlpRulesManager*
+DlpRulesManager::getInstance(void)
+{
+       std::lock_guard<std::mutex> guard(m_singletonMutex);
+       if (m_pInstance == NULL)
+               m_pInstance = new(std::nothrow) DlpRulesManager();
+       return m_pInstance;
+}
+
+std::list<current_rules_s>
+DlpRulesManager::PgGetDlpCurrentRules()
+{
+       std::lock_guard<std::mutex> guard(m_rulesMutex);
+       return m_currentRules;
+};
+
+void *
+DlpRulesManager::NewRulesNotificationThreadFunc(void *_this)
+{
+       return ((DlpRulesManager *)_this)->NewRulesNotificationThread();
+}
+
+void*
+DlpRulesManager::NewRulesNotificationThread()
+{
+       pid_t pid = getpid();
+       uid_t uid = getuid();
+       char buf[BUF_SIZE];
+
+       // Creating named semaphore to use in new rules notification
+       char sem_name[sizeof(PRIVACY_SEM_INITVAL)+5];
+       snprintf(sem_name, sizeof(PRIVACY_SEM_INITVAL)+5, PRIVACY_SEM_INITVAL, pid);
+       mode_t umask_value = umask(0111);
+       sem_t *semaphore = sem_open(sem_name, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 0);
+       if (semaphore == SEM_FAILED) {
+               PG_LOGE("errro unlink sem: %s - %s", sem_name, strerror_r(errno, buf, sizeof(buf)));
+               return NULL;
+       }
+       umask(umask_value);
+
+       // Get rules from server for the first time
+       m_privacyGuardClient->PgGetDlpCurrentRules(uid, pid, m_currentRules);
+
+       // Removing semaphore reference
+       if (sem_unlink(sem_name) < 0)
+               PG_LOGE("errro unlink sem: %s - %s", sem_name, strerror_r(errno, buf, sizeof(buf)));
+
+       for (;;) {
+               // Wait for privacy guard server rules change notification
+               m_rulesMutex.unlock();
+
+               sem_wait(semaphore);
+
+               // Get rules from server
+               m_rulesMutex.lock();
+               m_privacyGuardClient->PgGetDlpCurrentRules(uid, pid, m_currentRules);
+       }
+
+       return NULL;
+}
index 9578a4e..8bc8b92 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyChecker.cpp
+ */
+
 #include <algorithm>
 #include <memory>
 #include <sqlite3.h>
@@ -54,10 +58,10 @@ PrivacyChecker::initialize(void)
        std::lock_guard < std::mutex > guard(m_cacheMutex);
 
        int res = initMonitorPolicyCache();
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, ,"Failed to update cache (%d)", res);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "Failed to update cache (%d)", res);
 
        res = initializeGMain();
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, ,"Failed to initialize() (%d)", res);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "Failed to initialize() (%d)", res);
 
        return PRIV_GUARD_ERROR_SUCCESS;
 }
@@ -70,10 +74,10 @@ PrivacyChecker::initializeGMain(void)
        TryReturn(!m_isInitialized, PRIV_GUARD_ERROR_SUCCESS, , "Already Initalized");
 
        m_pHandlerGMainContext = g_main_context_new();
-       TryReturn(m_pHandlerGMainContext != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, ,"cannot create m_pHandlerGMainContext");
+       TryReturn(m_pHandlerGMainContext != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "cannot create m_pHandlerGMainContext");
 
        m_pLoop = g_main_loop_new(m_pHandlerGMainContext, FALSE);
-       TryReturn(m_pLoop != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, ,"cannot create m_pLoop");
+       TryReturn(m_pLoop != NULL, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "cannot create m_pLoop");
 
        std::unique_lock<std::mutex> lock(m_dbusMutex);
        char buf[BUF_SIZE];
@@ -112,21 +116,20 @@ PrivacyChecker::initMonitorPolicyCache(void)
 int
 PrivacyChecker::getMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int &monitorPolicy)
 {
+       int res = PRIV_GUARD_ERROR_SUCCESS;
        PG_LOGD("m_isInitialized: %d", m_isInitialized);
 
        if (m_isInitialized == false) {
                initialize();
        }
-//     printMonitorPolicyCache();
 
        std::string userPkgIdPrivacyId = std::to_string(userId) + std::string("|") + packageId + std::string("|") + privacyId;
        PG_LOGD("key: %s", userPkgIdPrivacyId.c_str());
        std::map<std::string, int>::iterator itr = m_monitorPolicyCache.find(userPkgIdPrivacyId);
-       int res = PRIV_GUARD_ERROR_SUCCESS;
+
        if(itr != m_monitorPolicyCache.end()) {
                monitorPolicy = itr->second;
-       }
-       else {
+       } else  {
                monitorPolicy = 0;
                res = PRIV_GUARD_ERROR_NO_DATA;
        }
@@ -139,10 +142,9 @@ PrivacyChecker::checkMonitorByPrivilege(const std::string privilegeId)
 {
        PG_LOGD("checkMonitorByPrivilege called with privilege: [%s]", privilegeId.c_str());
 
-       if (privilege_info_is_privacy(privilegeId.c_str())) {
+       if (privilege_info_is_privacy(privilegeId.c_str()))     {
                m_isMonitorEnable = true;
-       }
-       else {
+       } else  {
                PG_LOGD("[%s] is not related to a privacy.", privilegeId.c_str());
                m_isMonitorEnable = false;
        }
@@ -209,8 +211,7 @@ PrivacyChecker::handleNotification(DBusConnection* connection, DBusMessage* mess
        char* pPkgId;
        char* pPrivacyId;
 
-       if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_SETTING_CHANGED.c_str()))
-       {
+       if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_SETTING_CHANGED.c_str())) {
                r = dbus_message_get_args(message, &error,
                        DBUS_TYPE_STRING, &pPkgId,
                        DBUS_TYPE_STRING, &pPrivacyId,
@@ -227,15 +228,11 @@ PrivacyChecker::handleNotification(DBusConnection* connection, DBusMessage* mess
                }
 
                std::map < std::string, std::map < std::string, bool > > :: iterator iter = m_privacyInfoCache.find(std::string(pPkgId));
-               if (iter != m_privacyInfoCache.end())
-               {
+               if (iter != m_privacyInfoCache.end()) {
                        PG_LOGI("Current pkg privacy is in cache");
                        updateCache(std::string(pPkgId), pPrivacyId, iter->second);
                }
-
-       }
-       else if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_PKG_REMOVED.c_str()))
-       {
+       } else if (dbus_message_is_signal(message, DBUS_SIGNAL_INTERFACE.c_str(), DBUS_SIGNAL_PKG_REMOVED.c_str())) {
                r = dbus_message_get_args(message, &error,
                        DBUS_TYPE_STRING, &pPkgId,
                        DBUS_TYPE_INVALID);
@@ -244,8 +241,7 @@ PrivacyChecker::handleNotification(DBusConnection* connection, DBusMessage* mess
                std::lock_guard < std::mutex > guard(m_cacheMutex);
 
                std::map < std::string, std::map < std::string, bool > > :: iterator iter = m_privacyInfoCache.find(std::string(pPkgId));
-               if (iter != m_privacyInfoCache.end())
-               {
+               if (iter != m_privacyInfoCache.end()) {
                        m_privacyInfoCache.erase(iter);
                }
        }
@@ -262,13 +258,10 @@ PrivacyChecker::check(const std::string privacyId, std::map < std::string, bool
        std::map < std::string, bool >::iterator iter;
 
        iter = privacyMap.find(privacyId);
-       if (iter == privacyMap.end() )
-       {
+       if (iter == privacyMap.end()) {
                PG_LOGD("The application cannot access the privacy inforamtion.");
                return PRIV_GUARD_ERROR_USER_NOT_CONSENTED;
-       }
-       else if (!iter->second)
-       {
+       } else if (!iter->second) {
                PG_LOGD("User does not consented to access the privacy information");
                return PRIV_GUARD_ERROR_USER_NOT_CONSENTED;
        }
@@ -303,9 +296,9 @@ PrivacyChecker::check(const std::string pkgId, const std::string privacyId)
        {
                std::map < std::string, bool > pkgCacheMap;
                res = updateCache(pkgId, pkgCacheMap);
-               TryReturn( res == PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_DB_ERROR, , "Failed to update cache : %d", res);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_DB_ERROR, , "Failed to update cache : %d", res);
 
-               m_privacyInfoCache.insert( std::map < std::string, std::map < std::string, bool > >::value_type(std::string(pkgId), pkgCacheMap));
+               m_privacyInfoCache.insert(std::map <std::string, std::map<std::string, bool>>::value_type(std::string(pkgId), pkgCacheMap));
                iter = m_privacyInfoCache.find(pkgId);
        }
 
@@ -322,7 +315,7 @@ PrivacyChecker::check(const std::string pkgId, const std::string privacyId)
 int
 PrivacyChecker::finalize(void)
 {
-       std::lock_guard <std::mutex> guard (m_cacheMutex);
+       std::lock_guard<std::mutex> guard(m_cacheMutex);
        m_privacyCache.clear();
        m_privacyInfoCache.clear();
 
@@ -361,16 +354,16 @@ PrivacyChecker::updateCache(const std::string pkgId, std::string privacyId, std:
        openDb(PRIVACY_DB_PATH, pDbH, SQLITE_OPEN_READONLY);
        prepareDb(pDbH, PrivacyQuery.c_str(), pPrivacyStmt);
        int res = sqlite3_bind_text(pPrivacyStmt.get(), 1, pkgId.c_str(),  -1, SQLITE_TRANSIENT);
-       TryReturn( res == 0, PRIV_GUARD_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
+       TryReturn(res == 0, PRIV_GUARD_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
 
        res = sqlite3_bind_text(pPrivacyStmt.get(), 2, privacyId.c_str(),  -1, SQLITE_TRANSIENT);
-       TryReturn( res == 0, PRIV_GUARD_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
+       TryReturn(res == 0, PRIV_GUARD_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
 
        while ( sqlite3_step(pPrivacyStmt.get()) == SQLITE_ROW )
        {
                bool privacyEnabled = sqlite3_column_int(pPrivacyStmt.get(), 0) > 0 ? true : false;
 
-               PG_LOGD("Set result : %s : %d", privacyId.c_str(), privacyEnabled );
+               PG_LOGD("Set result : %s : %d", privacyId.c_str(), privacyEnabled);
                pkgCacheMap.erase(privacyId);
                pkgCacheMap.insert(std::map < std::string, bool >::value_type(privacyId, privacyEnabled));
        }
@@ -388,7 +381,7 @@ PrivacyChecker::updateCache(std::string pkgId, std::map < std::string, bool >& p
        openDb(PRIVACY_DB_PATH, pDbH, SQLITE_OPEN_READONLY);
        prepareDb(pDbH, PrivacyQuery.c_str(), pPrivacyStmt);
        int res = sqlite3_bind_text(pPrivacyStmt.get(), 1, pkgId.c_str(), -1, SQLITE_TRANSIENT);
-       TryReturn( res == SQLITE_OK, PRIV_GUARD_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
+       TryReturn(res == SQLITE_OK, PRIV_GUARD_ERROR_DB_ERROR, , "sqlite3_bind_text : %d", res);
 
        while ( (res = sqlite3_step(pPrivacyStmt.get())) == SQLITE_ROW )
        {
old mode 100755 (executable)
new mode 100644 (file)
index 3899005..55d0902
 
 #include <algorithm>
 #include <memory>
+#include <fcntl.h>
+#include <strings.h>
+#include <aul.h>
+#include <pkgmgr-info.h>
 #include "Utils.h"
+#include "DlpUtils.h"
 #include "PrivacyGuardClient.h"
 #include "SocketClient.h"
 #include "PrivacyIdInfo.h"
@@ -27,21 +32,88 @@ std::mutex PrivacyGuardClient::m_singletonMutex;
 PrivacyGuardClient* PrivacyGuardClient::m_pInstance = NULL;
 const std::string PrivacyGuardClient::INTERFACE_NAME("PrivacyInfoService");
 
-PrivacyGuardClient::PrivacyGuardClient(void)
-       : m_sqlHandler(NULL)
-       , m_stmt(NULL)
-       , m_bDBOpen(false)
+char PrivacyGuardClient::m_categories[MAX_CATEGORIES][LEN_CATEGORY];
+
+PrivacyGuardClient::PrivacyGuardClient(void):m_sqlHandler(NULL), m_stmt(NULL), m_bDBOpen(false)
+{
+       loadApplicationInfo();
+       int res = loadDlpCategories();
+       if (res != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("fail : loadDlpCategories (%d)", res);
+       }
+}
+
+void
+PrivacyGuardClient::category_id_to_text(category_u *category)
 {
-       std::unique_ptr<SocketClient> pSocketClient(new SocketClient(INTERFACE_NAME));
-       m_pSocketClient = std::move(pSocketClient);
+       pg_strlcpy(category->text, m_categories[category->id - 1], LEN_CATEGORY);
 }
 
+int
+PrivacyGuardClient::category_text_to_id(const char *txt)
+{
+  for (int i = 0; i < MAX_CATEGORIES; i++) {
+    if (!strcmp(m_categories[i], txt)) {
+      return i + 1;
+    }
+  }
+  return -1;
+}
+
+void
+PrivacyGuardClient::loadApplicationInfo()
+{
+       int ret;
+       char *data = NULL;
+       pkgmgrinfo_appinfo_h appinfo = NULL;
+       pkgmgrinfo_pkginfo_h pkginfo = NULL;
+
+       // load application ID
+       ret = aul_app_get_appid_bypid(getpid(), m_applicationId, LEN_APPLICATION_ID);
+       if (ret == 0) {
+               // load application info
+               ret = pkgmgrinfo_appinfo_get_usr_appinfo(m_applicationId, getuid(), &appinfo);
+               if (ret == 0) {
+                       // load application name
+                       ret = pkgmgrinfo_appinfo_get_label(appinfo, &data);
+                       if (ret == 0)
+                               pg_strlcpy(m_applicationName, data, LEN_APPLICATION_NAME);
+
+                       // load package ID
+                       ret = pkgmgrinfo_appinfo_get_pkgid(appinfo, &data);
+                       if (ret == 0)
+                               pg_strlcpy(m_packageId, data, LEN_PACKAGE_ID);
+
+                       // load application icon
+                       ret = pkgmgrinfo_appinfo_get_icon(appinfo, &data);
+                       if (ret == 0)
+                               pg_strlcpy(m_applicationIcon, data, LEN_APPLICATION_ICON);
+
+                       // load package info
+                       ret = pkgmgrinfo_pkginfo_get_pkginfo(m_packageId, &pkginfo);
+                       if (ret == 0) {
+                               // load application version
+                               ret = pkgmgrinfo_pkginfo_get_version(pkginfo, &data);
+                               if (ret == 0)
+                                       pg_strlcpy(m_applicationVersion, data, LEN_APPLICATION_VERSION);
+
+                               pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+                       }
+
+                       pkgmgrinfo_appinfo_destroy_appinfo(appinfo);
+               }
+       }
+}
+
+/**
+ * @callgraph
+ */
 PrivacyGuardClient*
 PrivacyGuardClient::getInstance(void)
 {
        std::lock_guard<std::mutex> guard(m_singletonMutex);
        if (m_pInstance == NULL)
-               m_pInstance = new PrivacyGuardClient();
+               m_pInstance = new(std::nothrow) PrivacyGuardClient();
        return m_pInstance;
 }
 
@@ -53,13 +125,41 @@ PrivacyGuardClient::openSqliteDB(void)
        if(res == SQLITE_OK) {
                PG_LOGI("monitor db is opened successfully");
                m_bDBOpen = true;
-       }
-       else {
+       } else {
                PG_LOGE("fail : monitor db open(%d)", res);
        }
 }
 
 int
+PrivacyGuardClient::loadDlpCategories(void)
+{
+       std::list<std::string> categories;
+
+       int i;
+       for (i = 0; i < MAX_CATEGORIES; m_categories[i++][0] = 0);
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgGetDlpCategories", &result, &categories);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       i = 0;
+       for (std::list <std::string>::const_iterator iter = categories.begin(); iter != categories.end(); ++iter) {
+               pg_strlcpy(m_categories[i++], iter->c_str(), LEN_CATEGORY);
+       }
+
+       return result;
+}
+
+int
 PrivacyGuardClient::PgAddMonitorPolicyOffline(const int userId, const std::string packageId, const std::list < std::string > privacyList, bool monitorPolicy)
 {
        int res = -1;
@@ -111,14 +211,15 @@ int
 PrivacyGuardClient::PgAddPrivacyAccessLog(const int userId, const std::string packageId, const std::string privacyId, const time_t accessTime)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgAddPrivacyAccessLog", userId, packageId, privacyId, accessTime, &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgAddPrivacyAccessLog", userId, packageId, privacyId, accessTime, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
@@ -130,6 +231,7 @@ PrivacyGuardClient::PgAddMonitorPolicy(const int userId, const std::string packa
        PG_LOGD("userID: [%d], packageID[%s], monitorPolicy: [%d]", userId, packageId.c_str(), monitorPolicy);
 
        std::list < std::string > privacyList;
+       SocketClient socketClient(INTERFACE_NAME);
 
        int res = PrivacyIdInfo::getPrivacyIdListFromPrivilegeList(list, privacyList);
        if (res != PRIV_GUARD_ERROR_SUCCESS ) {
@@ -144,7 +246,7 @@ PrivacyGuardClient::PgAddMonitorPolicy(const int userId, const std::string packa
 
        bool isServerOperation = false;
 
-       res = m_pSocketClient->connect();
+       res = socketClient.connect();
        if(res != PRIV_GUARD_ERROR_SUCCESS) {
                PG_LOGD("Cannot connect to the socket. So change to the offline mode");
                isServerOperation = false;
@@ -155,10 +257,10 @@ PrivacyGuardClient::PgAddMonitorPolicy(const int userId, const std::string packa
        if (isServerOperation == true) {
                int result = PRIV_GUARD_ERROR_SUCCESS;
 
-               res = m_pSocketClient->call("PgAddMonitorPolicy", userId, packageId, privacyList, monitorPolicy, &result);
-               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+               res = socketClient.call("PgAddMonitorPolicy", userId, packageId, privacyList, monitorPolicy, &result);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-               res = m_pSocketClient->disconnect();
+               res = socketClient.disconnect();
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
                return result;
@@ -172,51 +274,36 @@ PrivacyGuardClient::PgAddMonitorPolicy(const int userId, const std::string packa
 {
        PG_LOGD("userID: [%d], packageID[%s], privacyID[%s], monitorPolicy: [%d]", userId, packageId.c_str(), privacyId.c_str(), monitorPolicy);
 
+       SocketClient socketClient(INTERFACE_NAME);
        std::list < std::string > privacyList;
        privacyList.push_back(privacyId);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        int result = PRIV_GUARD_ERROR_SUCCESS;
-       res = m_pSocketClient->call("PgAddMonitorPolicy", userId, packageId, privacyList, monitorPolicy, &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgAddMonitorPolicy", userId, packageId, privacyList, monitorPolicy, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
 }
 
-/*int
-PrivacyGuardClient::PgDeleteAllLogsAndMonitorPolicy(void)
-{
-       int result = PRIV_GUARD_ERROR_SUCCESS;
-
-       int res = m_pSocketClient->connect();
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
-
-       res = m_pSocketClient->call("PgDeleteAllLogsAndMonitorPolicy", &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
-
-       res = m_pSocketClient->disconnect();
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
-
-       return result;
-}*/
-
 int
 PrivacyGuardClient::PgDeleteAllLogs(void)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgDeleteAllLogs", &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgDeleteAllLogs", &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect() , "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
@@ -226,14 +313,15 @@ int
 PrivacyGuardClient::PgDeleteLogsByPackageId(const std::string packageId)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgDeleteLogsByPackageId", packageId, &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgDeleteLogsByPackageId", packageId, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
@@ -243,14 +331,15 @@ int
 PrivacyGuardClient::PgDeleteMonitorPolicyByPackageId(const std::string packageId)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgDeleteMonitorPolicyByPackageId", packageId, &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgDeleteMonitorPolicyByPackageId" , packageId, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
@@ -260,14 +349,15 @@ int
 PrivacyGuardClient::PgForeachTotalPrivacyCountOfPackage(const int userId, const int startDate, const int endDate, std::list < std::pair <std::string, int > > & packageInfoList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachTotalPrivacyCountOfPackage", userId, startDate, endDate, &result, &packageInfoList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachTotalPrivacyCountOfPackage", userId, startDate, endDate, &result, &packageInfoList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res , socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
@@ -277,14 +367,15 @@ int
 PrivacyGuardClient::PgForeachTotalPrivacyCountOfPrivacy(const int userId, const int startDate, const int endDate, std::list < std::pair <std::string, int > > & privacyInfoList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachTotalPrivacyCountOfPrivacy", userId, startDate, endDate, &result, &privacyInfoList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachTotalPrivacyCountOfPrivacy", userId, startDate, endDate, &result, &privacyInfoList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
@@ -294,53 +385,55 @@ int
 PrivacyGuardClient::PgForeachPrivacyCountByPrivacyId(const int userId, const int startDate, const int endDate, const std::string privacyId, std::list < std::pair <std::string, int > > & packageInfoList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
-
+       SocketClient socketClient(INTERFACE_NAME);
        bool isValid = PrivacyIdInfo::isValidPrivacyId(privacyId);
 
        if (!isValid)
                return PRIV_GUARD_ERROR_INVALID_PARAMETER;
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachPrivacyCountByPrivacyId", userId, startDate, endDate, privacyId, &result, &packageInfoList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachPrivacyCountByPrivacyId", userId, startDate, endDate, privacyId, &result, &packageInfoList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect() , "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
 }
 
 int
-PrivacyGuardClient::PgForeachPrivacyCountByPackageId(const int userId, const int startDate, const int endDate, const std::string packageId, std::list < std::pair <std::string, int > > & privacyInfoList) const
+PrivacyGuardClient::PgForeachPrivacyCountByPackageId(const int userId, const int startDate, const int endDate, const std::string packageId, std::list<std::pair<std::string, int>> &privacyInfoList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachPrivacyCountByPackageId", userId, startDate, endDate, packageId, &result, &privacyInfoList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachPrivacyCountByPackageId", userId, startDate, endDate, packageId, &result, &privacyInfoList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
 }
 
 int
-PrivacyGuardClient::PgForeachPackageIdUsingPrivacy(const int userId, std::list < std::string > & packageList) const
+PrivacyGuardClient::PgForeachPackageIdUsingPrivacy(const int userId, std::list<std::string> &packageList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachPackageIdUsingPrivacy", userId, &result, &packageList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachPackageIdUsingPrivacy", userId, &result, &packageList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
@@ -350,60 +443,59 @@ int
 PrivacyGuardClient::PgForeachPackageInfoByPrivacyId(const int userId, const std::string privacyId, std::list < package_data_s > & packageInfoList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
-
+       SocketClient socketClient(INTERFACE_NAME);
        bool isValid = PrivacyIdInfo::isValidPrivacyId(privacyId);
 
        if (!isValid)
                return PRIV_GUARD_ERROR_INVALID_PARAMETER;
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachPackageInfoByPrivacyId", userId, privacyId, &result, &packageInfoList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachPackageInfoByPrivacyId", userId, privacyId, &result, &packageInfoList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
 }
 
 int
-PrivacyGuardClient::PgForeachMonitorPolicyByPackageId(const int userId, const std::string packageId,
-               std::list <privacy_data_s> & privacyInfoList) const
+PrivacyGuardClient::PgForeachMonitorPolicyByPackageId(const int userId, const std::string packageId, std::list <privacy_data_s> & privacyInfoList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgForeachMonitorPolicyByPackageId", userId, packageId, &result, &privacyInfoList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgForeachMonitorPolicyByPackageId", userId, packageId, &result, &privacyInfoList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
 
        return result;
 }
 
 int
-PrivacyGuardClient::PgGetMonitorPolicy(const int userId, const std::string packageId,
-               const std::string privacyId, int &monitorPolicy) const
+PrivacyGuardClient::PgGetMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int &monitorPolicy) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
-
+       SocketClient socketClient(INTERFACE_NAME);
        bool isValid = PrivacyIdInfo::isValidPrivacyId(privacyId);
 
        if (!isValid)
                return PRIV_GUARD_ERROR_INVALID_PARAMETER;
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgGetMonitorPolicy", userId, packageId, privacyId, &result, &monitorPolicy);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgGetMonitorPolicy", userId, packageId, privacyId, &result, &monitorPolicy);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
@@ -413,14 +505,15 @@ int
 PrivacyGuardClient::PgGetAllMonitorPolicy(std::list < std::pair < std::string, int > > & monitorPolicyList) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgGetAllMonitorPolicy", &result, &monitorPolicyList);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgGetAllMonitorPolicy", &result, &monitorPolicyList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
@@ -430,14 +523,15 @@ int
 PrivacyGuardClient::PgCheckPrivacyPackage(const int userId, const std::string packageId, bool &isPrivacyPackage)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgCheckPrivacyPackage", userId, packageId, &result, &isPrivacyPackage);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgCheckPrivacyPackage", userId, packageId, &result, &isPrivacyPackage);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
@@ -448,19 +542,19 @@ PrivacyGuardClient::PgUpdateMonitorPolicy(const int userId, const std::string pa
                const std::string privacyId, const int monitorPolicy)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
-
+       SocketClient socketClient(INTERFACE_NAME);
        bool isValid = PrivacyIdInfo::isValidPrivacyId(privacyId);
 
        if (!isValid)
                return PRIV_GUARD_ERROR_INVALID_PARAMETER;
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgUpdateMonitorPolicy", userId, packageId, privacyId, monitorPolicy, &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgUpdateMonitorPolicy", userId, packageId, privacyId, monitorPolicy, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
@@ -470,14 +564,15 @@ int
 PrivacyGuardClient::PgGetMainMonitorPolicy(const int userId, int &mainMonitorPolicy) const
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgGetMainMonitorPolicy", userId, &result, &mainMonitorPolicy);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgGetMainMonitorPolicy", userId, &result, &mainMonitorPolicy);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
        return result;
@@ -487,15 +582,476 @@ int
 PrivacyGuardClient::PgUpdateMainMonitorPolicy(const int userId, const int mainMonitorPolicy)
 {
        int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgUpdateMainMonitorPolicy", userId, mainMonitorPolicy, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       return result;
+}
+
+/**
+ * @callgraph
+ */
+int
+PrivacyGuardClient::PgAddLeakLog(const int userId, const char *destination, const void *rawPacket, const size_t len, const std::list<leak_log_insert_data_s> &logList) const
+{
+       if (destination == NULL || rawPacket == NULL)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+       packet_data_s packetData = { (int)len, (void *)rawPacket};
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgAddLeakLog", userId, (const char *)m_applicationId,
+                                                               (const char *)m_applicationName, (const char *)m_applicationVersion,
+                                                               (const char *)m_applicationIcon, (const char *)m_packageId,
+                                                               destination, packetData, logList, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachLeakLogs(const int userId, std::list<leak_log_get_data_s> &logList) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachLeakLogs", userId, &result, &logList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachLeakLogsByAppName(const int userId, const char *appName, std::list<leak_log_get_data_s> &logList) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachLeakLogsByAppName", userId, appName, &result, &logList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachLeakLogsByCategory(const int userId, const char *category, std::list<leak_log_get_data_s> &logList) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       int category_id = category_text_to_id(category);
+
+       res = socketClient.call("PgForeachLeakLogsByCategory", userId, category_id, &result, &logList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachAppLeakCount(const int userId, std::list<leak_log_get_app_count_s> &logList) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachAppLeakCount", userId, &result, &logList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachCategoryLeakCount(const int userId, std::list<leak_log_get_category_count_s> &logList) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachCategoryLeakCount", userId, &result, &logList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       for (std::list <leak_log_get_category_count_s>::iterator iter = logList.begin(); iter != logList.end(); ++iter) {
+         category_id_to_text(&(iter->category));
+       }
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachLeakLogsByTimestamp(const int userId, const time_t start, const time_t end, std::list<leak_log_get_data_s> &logList) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachLeakLogsByTimestamp", userId, start, end, &result, &logList);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgGetLeakLogDetails(int userId, int logId, leak_log_get_detail_data_s *logDetail) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgGetLeakLogDetails", userId, logId, &result, logDetail);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       category_id_to_text(&(logDetail->category));
+       return result;
+}
+
+int
+PrivacyGuardClient::PgPurgeLeakLogs(const int userId) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
 
-       int res = m_pSocketClient->connect();
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
-       res = m_pSocketClient->call("PgUpdateMainMonitorPolicy", userId, mainMonitorPolicy, &result);
-       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, m_pSocketClient->disconnect(), "call : %d", res);
+       res = socketClient.call("PgPurgeLeakLogs", userId, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
 
-       res = m_pSocketClient->disconnect();
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgPurgeLeakLogsByLogId(const std::list<int> &logId) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgPurgeLeakLogsByLogId", logId, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgSetDlpProfile(const int userId, const dlp_profile_s *profile) const
+{
+       if (profile == NULL)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgSetDlpProfile", userId, profile, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgGetDlpProfile(const int userId, dlp_profile_s *profile) const
+{
+       if (profile == NULL)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgGetDlpProfile", userId, &result, profile);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+/**
+ * @callgraph
+ */
+int
+PrivacyGuardClient::PgGetDlpCurrentRules(const int userId, const int pId, std::list<current_rules_s> &currentRules) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
 
+       currentRules.clear();
+       res = socketClient.call("PgGetDlpCurrentRules", userId, (const char *)m_applicationId,
+                                                               pId, &result, &currentRules);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgAddDlpCustomRule(int userId, PgDlpAction action, int patternId, const char *ruleName, const char *ruleDescription, const char *applicationId) const
+{
+       if (userId < 0                                                          ||      \
+               action < PRIV_GUARD_DLP_ACTION_ALLOW    ||      \
+               action > PRIV_GUARD_DLP_ACTION_SANITIZE ||      \
+               patternId == 0                                                  ||      \
+               ruleName == NULL                                                ||      \
+               ruleDescription == NULL                                 ||      \
+               applicationId == NULL)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       custom_rule_s rule;
+       rule.action = action;
+       rule.pattern_id = patternId;
+       pg_strlcpy(rule.name, ruleName, LEN_NAME);
+       pg_strlcpy(rule.description, ruleDescription, LEN_DESCRIPTION);
+       pg_strlcpy(rule.application_id, applicationId, LEN_APPLICATION_ID);
+
+       res = socketClient.call("PgAddDlpCustomRule", userId, rule, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgUpdateDlpCustomRule(int ruleId, PgDlpAction action, int patternId, const char *ruleName, const char *ruleDescription, const char *applicationId) const
+{
+       if (ruleId < 1                                                          ||      \
+               action < PRIV_GUARD_DLP_ACTION_ALLOW    ||      \
+               action > PRIV_GUARD_DLP_ACTION_SANITIZE ||      \
+               patternId == 0                                                  ||      \
+               ruleName == NULL                                                ||      \
+               ruleDescription == NULL                                 ||      \
+               applicationId == NULL)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       custom_rule_s rule;
+       rule.id = ruleId;
+       rule.action = action;
+       rule.pattern_id = patternId;
+       pg_strlcpy(rule.name, ruleName, LEN_NAME);
+       pg_strlcpy(rule.description, ruleDescription, LEN_DESCRIPTION);
+       pg_strlcpy(rule.application_id, applicationId, LEN_APPLICATION_ID);
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgUpdateDlpCustomRule", rule, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgDeleteDlpCustomRule(int ruleId) const
+{
+       if (ruleId < 1)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgDeleteDlpCustomRule", ruleId, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachDlpRules(int userId, PgDlpProfile profile, std::list<get_custom_rule_s> &rules) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachDlpRules", userId, (int)profile, &result, &rules);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgAddDlpPattern(const char *name, const char *description, const char *category, const char *pattern_text, PgDlpPatternType type) const
+{
+       if (name == NULL || description == NULL || category == NULL || pattern_text == NULL || !strlen(pattern_text) ||
+           (type != PRIV_GUARD_DLP_PATTERN_STRING && type != PRIV_GUARD_DLP_PATTERN_REGEX)) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (dlp_pattern_validate(type, pattern_text) != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Invalid pattern.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       pattern_s pattern;
+       pg_strlcpy(pattern.pattern, pattern_text, LEN_PATTERN);
+       pg_strlcpy(pattern.name, name, LEN_NAME);
+       pg_strlcpy(pattern.description, description, LEN_DESCRIPTION);
+       pattern.type = type;
+       pattern.category.id = category_text_to_id(category);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgAddDlpPattern", pattern, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgDeleteDlpPattern(int pattern_id) const
+{
+       if (pattern_id < 1) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgDeleteDlpPattern", pattern_id, &result);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachDlpPatterns(std::list<get_pattern_s> &patterns) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       SocketClient socketClient(INTERFACE_NAME);
+
+       int res = socketClient.connect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "connect : %d", res);
+
+       res = socketClient.call("PgForeachDlpPatterns", &result, &patterns);
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, socketClient.disconnect(), "call : %d", res);
+
+       res = socketClient.disconnect();
+       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "disconnect : %d", res);
+
+       for (std::list <get_pattern_s>::iterator iter = patterns.begin(); iter != patterns.end(); ++iter) {
+         category_id_to_text(&(iter->category));
+       }
+       return result;
+}
+
+int
+PrivacyGuardClient::PgForeachDlpCategories(std::list<std::string> &categories) const
+{
+       int result = PRIV_GUARD_ERROR_SUCCESS;
+       for (int i = 0; i < MAX_CATEGORIES && strlen(m_categories[i]); i++) {
+         categories.push_back(m_categories[i]);
+       }
        return result;
 }
index 64a4948..df1884d 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketClient.cpp
+ */
+
 #include <sys/socket.h>
 #include <string.h>
 #include <fcntl.h>
 
 #define BUF_SIZE 256
 
-#define throwWithErrnoMessage(specificInfo)    do {\
-                                                                                               PG_LOGE("%s : %s", specificInfo, strerror(errno)); \
-                                                                                               return -1; \
-                                                                                       } while(0)
+#define throwWithErrnoMessage(specificInfo) do {                                                                                                       \
+                                                                                               PG_LOGE("%s : %s", specificInfo, strerror_r(errno));    \
+                                                                                               return -1;                                                                                      \
+                                                                                       } while (0)
 
 SocketClient::SocketClient(const std::string& interfaceName)
        : m_socketFd(-1)
@@ -44,7 +48,7 @@ int SocketClient::connect()
 {
        struct sockaddr_un remote;
        char buf[BUF_SIZE];
-       m_socketFd = socket(AF_UNIX, SOCK_STREAM,0);
+       m_socketFd = socket(AF_UNIX, SOCK_STREAM, 0);
        TryReturn( m_socketFd != -1, PRIV_GUARD_ERROR_IPC_ERROR, , "socket : %s", strerror_r(errno, buf, sizeof(buf)));
 
        int res;
old mode 100755 (executable)
new mode 100644 (file)
index 980f69c..34d2b8d
  * limitations under the License.
  */
 
+/**
+ * @file       privacy_guard_client.cpp
+ */
+
 #include <string.h>
 #include <string>
 #include <memory>
@@ -23,6 +27,7 @@
 #include "privacy_guard_client_internal.h"
 #include "privacy_guard_client_internal_types.h"
 #include "Utils.h"
+#include "DlpUtils.h"
 
 #define MONITOR_POLICY_OFF 0
 #define MONITOR_POLICY_ON 1
 #define TIZEN_PATH_MAX 1024
 #endif
 
-/*int privacy_guard_client_delete_all_logs_and_monitor_policy(void)
-{
-       PrivacyGuardClient *pInst = PrivacyGuardClient::getInstance();
-
-       int retval = pInst->PgDeleteAllLogsAndMonitorPolicy();
-       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
-               PG_LOGE("Failed to do PrivacyGuardClient::PgDeleteAllLogsAndMonitorPolicy() [%d]", retval);
-               return retval;
-       }
-
-       return PRIV_GUARD_ERROR_SUCCESS;
-}*/
-
 int privacy_guard_client_delete_all_logs(void)
 {
        PrivacyGuardClient *pInst = PrivacyGuardClient::getInstance();
@@ -79,8 +71,11 @@ int privacy_guard_client_delete_logs_by_package_id(const char *package_id)
        return PRIV_GUARD_ERROR_SUCCESS;
 }
 
-int privacy_guard_client_foreach_total_privacy_count_of_package(const int user_id, const time_t start_date,
-               const time_t end_date, privacy_guard_client_privacy_count_of_package_cb callback, void *user_data)
+int privacy_guard_client_foreach_total_privacy_count_of_package(const int user_id,
+                                                                                                                               const time_t start_date,
+                                                                                                                               const time_t end_date,
+                                                                                                                               privacy_guard_client_privacy_count_of_package_cb callback,
+                                                                                                                               void *user_data)
 {
        if (user_id < 0 || start_date > end_date || start_date <= 0) {
                PG_LOGE("Invalid parameters. user id: [%d], start date: [%d], end date: [%d]", user_id, start_date, end_date);
@@ -106,8 +101,11 @@ int privacy_guard_client_foreach_total_privacy_count_of_package(const int user_i
        return PRIV_GUARD_ERROR_SUCCESS;
 }
 
-int privacy_guard_client_foreach_total_privacy_count_of_privacy(const int user_id, const time_t start_date,
-               const time_t end_date, privacy_guard_client_privacy_count_cb callback, void *user_data)
+int privacy_guard_client_foreach_total_privacy_count_of_privacy(const int user_id,
+                                                                                                                               const time_t start_date,
+                                                                                                                               const time_t end_date,
+                                                                                                                               privacy_guard_client_privacy_count_cb callback,
+                                                                                                                               void *user_data)
 {
        if (user_id < 0 || start_date > end_date || start_date <= 0) {
                PG_LOGE("Invalid parameters.");
@@ -133,9 +131,12 @@ int privacy_guard_client_foreach_total_privacy_count_of_privacy(const int user_i
        return PRIV_GUARD_ERROR_SUCCESS;
 }
 
-int privacy_guard_client_foreach_privacy_count_by_privacy_id(const int user_id, const time_t start_date,
-               const time_t end_date, const char *privacy_id,
-               privacy_guard_client_privacy_count_of_package_cb callback, void *user_data)
+int privacy_guard_client_foreach_privacy_count_by_privacy_id(const int user_id,
+                                                                                                                        const time_t start_date,
+                                                                                                                        const time_t end_date,
+                                                                                                                        const char *privacy_id,
+                                                                                                                        privacy_guard_client_privacy_count_of_package_cb callback,
+                                                                                                                        void *user_data)
 {
        if (user_id < 0 || start_date > end_date || start_date <= 0 || privacy_id == NULL) {
                PG_LOGE("Invalid parameters.");
@@ -161,9 +162,12 @@ int privacy_guard_client_foreach_privacy_count_by_privacy_id(const int user_id,
        return PRIV_GUARD_ERROR_SUCCESS;
 }
 
-int privacy_guard_client_foreach_privacy_count_by_package_id(const int user_id, const time_t start_date,
-               const time_t end_date, const char *package_id,
-               privacy_guard_client_privacy_count_cb callback, void *user_data)
+int privacy_guard_client_foreach_privacy_count_by_package_id(const int user_id,
+                                                                                                                        const time_t start_date,
+                                                                                                                        const time_t end_date,
+                                                                                                                        const char *package_id,
+                                                                                                                        privacy_guard_client_privacy_count_cb callback,
+                                                                                                                        void *user_data)
 {
        if (user_id < 0 || start_date > end_date || start_date <= 0 || package_id == NULL) {
                PG_LOGE("Invalid parameters.");
@@ -189,7 +193,10 @@ int privacy_guard_client_foreach_privacy_count_by_package_id(const int user_id,
        return retval;
 }
 
-int privacy_guard_client_update_monitor_policy(const int user_id, const char *package_id, const char *privacy_id, const int monitor_policy)
+int privacy_guard_client_update_monitor_policy(const int user_id,
+                                                                                          const char *package_id,
+                                                                                          const char *privacy_id,
+                                                                                          const int monitor_policy)
 {
        if (user_id < 0 || package_id == NULL || privacy_id == NULL || monitor_policy < 0) {
                PG_LOGE("Invalid parameters. UserID[%d], PkgID[%s], PrivacyID[%s], Policy[%d]", user_id, package_id, privacy_id, monitor_policy);
@@ -207,8 +214,10 @@ int privacy_guard_client_update_monitor_policy(const int user_id, const char *pa
     return PRIV_GUARD_ERROR_SUCCESS;
 }
 
-int privacy_guard_client_foreach_monitor_policy_by_package_id(const int user_id, const char *package_id,
-               privacy_guard_client_monitor_policy_cb callback, void *user_data)
+int privacy_guard_client_foreach_monitor_policy_by_package_id(const int user_id,
+                                                                                                                         const char *package_id,
+                                                                                                                         privacy_guard_client_monitor_policy_cb callback,
+                                                                                                                         void *user_data)
 {
        if (user_id < 0 || package_id == NULL) {
                PG_LOGE("Invalid parameters.");
@@ -281,7 +290,10 @@ int privacy_guard_client_foreach_package_id_using_privacy(const int user_id, pri
        return PRIV_GUARD_ERROR_SUCCESS;
 }
 
-int privacy_guard_client_foreach_package_info_by_privacy_id(const int user_id, const char *privacy_id, privacy_guard_client_package_info_cb callback, void *user_data)
+int privacy_guard_client_foreach_package_info_by_privacy_id(const int user_id,
+                                                                                                                       const char *privacy_id,
+                                                                                                                       privacy_guard_client_package_info_cb callback,
+                                                                                                                       void *user_data)
 {
        if (user_id < 0 || privacy_id == NULL) {
                PG_LOGE("Invalid parameters.");
@@ -314,10 +326,14 @@ int privacy_guard_client_foreach_package_info_by_privacy_id(const int user_id, c
 }
 
 //////////////////////// INTERNAL APIs ////////////////////////////////////
-int privacy_guard_client_add_privacy_access_log(const int user_id, const char *package_id, const char *privacy_id, const time_t access_time)
+int privacy_guard_client_add_privacy_access_log(const int user_id,
+                                                                                               const char *package_id,
+                                                                                               const char *privacy_id,
+                                                                                               const time_t access_time)
 {
        if (user_id < 0 || package_id == NULL || privacy_id == NULL || access_time < 0) {
-               PG_LOGE("Invalid parameters. [user_id: %d, package_id: %s, privacy_id: %s, time: %ld", user_id, package_id, privacy_id, access_time);
+               PG_LOGE("Invalid parameters. [user_id: %d, package_id: %s, privacy_id: %s, time: %ld",
+                               user_id, package_id, privacy_id, access_time);
                return PRIV_GUARD_ERROR_INVALID_PARAMETER;
        }
 
@@ -350,4 +366,437 @@ int privacy_guard_client_add_monitor_policy(const int user_id, const char *packa
     return PRIV_GUARD_ERROR_SUCCESS;
 }
 
+//////////////////////////// DLP APIs ////////////////////////////////////
+int privacy_guard_client_foreach_leak_logs(const int user_id, privacy_guard_client_leak_logs_cb callback, void *user_data)
+{
+       if (user_id < 0 || callback == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<leak_log_get_data_s> logList;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachLeakLogs(user_id, logList);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachLeakLogs() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : logList) {
+               bool ret = callback(it.id, it.time_stamp, (PgDlpAction)it.action, it.application_name,
+                                                       it.application_icon, it.destination, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_leak_logs_by_app_name(const int user_id,
+                                                                                                          const char *application_name,
+                                                                                                          privacy_guard_client_leak_logs_cb callback,
+                                                                                                          void *user_data)
+{
+       if (user_id < 0 || callback == NULL || application_name == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<leak_log_get_data_s> logList;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachLeakLogsByAppName(user_id, application_name, logList);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachLeakLogsByAppName() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : logList) {
+               bool ret = callback(it.id, it.time_stamp, (PgDlpAction)it.action, it.application_name,
+                                                       it.application_icon, it.destination, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_leak_logs_by_category(const int user_id,
+                                                                                                          const char *category_text,
+                                                                                                          privacy_guard_client_leak_logs_cb callback,
+                                                                                                          void *user_data)
+{
+       if (user_id < 0 || callback == NULL || category_text == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<leak_log_get_data_s> logList;
 
+       int retval = PrivacyGuardClient::getInstance()->PgForeachLeakLogsByCategory(user_id, category_text, logList);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachLeakLogsByCategory() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : logList) {
+               bool ret = callback(it.id, it.time_stamp, (PgDlpAction)it.action, it.application_name,
+                                                       it.application_icon, it.destination, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_app_leak_count(const int user_id, privacy_guard_client_app_leak_count_cb callback, void *user_data)
+{
+       if (user_id < 0 || callback == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<leak_log_get_app_count_s> logList;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachAppLeakCount(user_id, logList);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachAppLeakCount() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : logList) {
+               bool ret = callback(it.application_name, it.first_time_stamp, it.last_time_stamp,
+                                                       it.application_icon, it.leak_count, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_category_leak_count(const int user_id,
+                                                                                                        privacy_guard_client_category_leak_count_cb callback,
+                                                                                                        void *user_data)
+{
+       if (user_id < 0 || callback == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<leak_log_get_category_count_s> logList;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachCategoryLeakCount(user_id, logList);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachCategoryLeakCount() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : logList) {
+               bool ret = callback(it.category.text, it.first_time_stamp, it.last_time_stamp,
+                                                       it.leak_count, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_get_leak_logs(const int user_id,
+                                                                          const time_t start,
+                                                                          const time_t end,
+                                                                          privacy_guard_client_leak_logs_cb callback,
+                                                                          void *user_data)
+{
+       if (user_id < 0 || end < start || callback == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<leak_log_get_data_s> logList;
+       int retval = PrivacyGuardClient::getInstance()->PgForeachLeakLogsByTimestamp(user_id, start, end, logList);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachLeakLogsByTimestamp() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : logList) {
+               bool ret = callback(it.id, it.time_stamp, (PgDlpAction)it.action, it.application_name,
+                                                       it.application_icon, it.destination, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_get_leak_log_detail(int user_id, int log_id, leak_log_get_detail_data_s *log_detail)
+{
+       if (user_id < 0 || log_id < 1 || log_detail == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgGetLeakLogDetails(user_id, log_id, log_detail);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgGetLeakLogDetails() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_purge_leak_logs(const int user_id)
+{
+       if (user_id < 0) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgPurgeLeakLogs(user_id);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgPurgeLeakLogs() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_purge_leak_logs_by_logid(const int log_id[], const size_t log_id_size)
+{
+       if (log_id == NULL || log_id_size == 0) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       const std::list<int> log_id_list{ log_id, log_id + log_id_size };
+       const auto retval = PrivacyGuardClient::getInstance()->PgPurgeLeakLogsByLogId(log_id_list);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgPurgeLeakLogsByLogId() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_set_dlp_profile(const int user_id, const dlp_profile_s *profile)
+{
+       if (user_id < 0 || profile == NULL || profile->profile > PRIV_GUARD_DLP_PROFILE_CUSTOM || profile->keep_log_days < 1) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgSetDlpProfile(user_id, profile);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgSetDlpProfile() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_get_dlp_profile(const int user_id, dlp_profile_s *profile)
+{
+       if (user_id < 0 || profile == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgGetDlpProfile(user_id, profile);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgGetDlpProfile() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_add_dlp_custom_rule(int user_id,
+                                                                                        PgDlpAction action,
+                                                                                        int pattern_id,
+                                                                                        const char *ruleName,
+                                                                                        const char *ruleDescription,
+                                                                                        const char *application_id)
+{
+       if (user_id < 0 || action > PRIV_GUARD_DLP_ACTION_SANITIZE ||
+                       pattern_id == 0 || ruleName == NULL || ruleDescription == NULL || application_id == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgAddDlpCustomRule(user_id,
+                                                                                                                                          action,
+                                                                                                                                          pattern_id,
+                                                                                                                                          ruleName,
+                                                                                                                                          ruleDescription,
+                                                                                                                                          application_id);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgAddDlpCustomRule() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_update_dlp_custom_rule(int rule_id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id)
+{
+       if (rule_id < 1)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int retval = PrivacyGuardClient::getInstance()->PgUpdateDlpCustomRule(rule_id, action, pattern_id, name, description, application_id);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgUpdateDlpCustomRule() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_delete_dlp_custom_rule(int rule_id)
+{
+       if (rule_id < 1)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       int retval = PrivacyGuardClient::getInstance()->PgDeleteDlpCustomRule(rule_id);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgDeleteDlpCustomRule() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_dlp_rules(int user_id,
+                                                                                  PgDlpProfile profile,
+                                                                                  privacy_guard_client_dlp_rule_cb callback,
+                                                                                  void *user_data)
+{
+       if (profile > PRIV_GUARD_DLP_PROFILE_CUSTOM || callback == NULL ||
+                       (profile == PRIV_GUARD_DLP_PROFILE_CUSTOM && user_id < 0)) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<get_custom_rule_s> rules;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachDlpRules(user_id, profile, rules);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachDlpRules() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : rules) {
+               bool ret = callback(it.id, (PgDlpAction)it.action, it.pattern_id, it.name, it.description, it.application_id,
+                                   it.leaks_count, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_add_dlp_pattern(const char *name, const char *description, const char *category, const char *pattern, PgDlpPatternType type)
+{
+       if (name == NULL || description == NULL || category == NULL || pattern == NULL || !strlen(pattern) ||
+                       (type != PRIV_GUARD_DLP_PATTERN_STRING && type != PRIV_GUARD_DLP_PATTERN_REGEX)) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (dlp_pattern_validate(type, pattern) != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Invalid pattern.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgAddDlpPattern(name, description, category, pattern, type);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgAddDlpPattern() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_delete_dlp_pattern(int pattern_id)
+{
+       if (pattern_id < 1) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       int retval = PrivacyGuardClient::getInstance()->PgDeleteDlpPattern(pattern_id);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgDeleteDlpPattern() [%d]", retval);
+               return retval;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_dlp_patterns(privacy_guard_client_dlp_pattern_cb callback, void *user_data)
+{
+       if (callback == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<get_pattern_s> patterns;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachDlpPatterns(patterns);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachDlpPatterns() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : patterns) {
+               bool ret = callback(it.id, it.pattern, it.name, it.description, it.type, it.category.text,
+                                   it.undeletable, it.leaks_count, user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int privacy_guard_client_foreach_dlp_categories(privacy_guard_client_dlp_category_cb callback, void *user_data)
+{
+       if (callback == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       std::list<std::string> categories;
+
+       int retval = PrivacyGuardClient::getInstance()->PgForeachDlpCategories(categories);
+       if (retval != PRIV_GUARD_ERROR_SUCCESS) {
+               PG_LOGE("Failed to do PrivacyGuardClient::PgForeachDlpCategories() [%d]", retval);
+               return retval;
+       }
+
+       for (const auto &it : categories) {
+               bool ret = callback((const char *)it.c_str(), user_data);
+               if (ret == false)
+                       break;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+EXTERN_API int privacy_guard_client_validate_pattern(PgDlpPatternType type, const char* pattern)
+{
+       if ((type != PRIV_GUARD_DLP_PATTERN_STRING && type != PRIV_GUARD_DLP_PATTERN_REGEX) || pattern == NULL) {
+               PG_LOGE("Invalid parameters.");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       const int res = dlp_pattern_validate(type, pattern);
+       if (PRIV_GUARD_ERROR_SUCCESS != res) {
+        PG_LOGE("dlp_pattern_validate() failed. Error = %d", res);
+        return res;
+       }
+
+       if (type == PRIV_GUARD_DLP_PATTERN_STRING && strlen(pattern) < MIN_PATTERN_LEN) {
+        PG_LOGE("Pattern too short");
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
\ No newline at end of file
index 7d70705..5cf4c64 100755 (executable)
  * limitations under the License. 
  */
 
+/**
+ * @file       privacy_guard_client_internal_types.h
+ */
+
 #ifndef _PRIVACY_GUARD_CLIENT_INTERNAL_TYPES_H_
 #define _PRIVACY_GUARD_CLIENT_INTERNAL_TYPES_H_
 
@@ -28,4 +32,4 @@ extern "C" {
 }
 #endif
 
-#endif //_PRIVACY_GUARD_CLIENT_INTERNAL_TYPES_H_
\ No newline at end of file
+#endif //_PRIVACY_GUARD_CLIENT_INTERNAL_TYPES_H_
diff --git a/client/src/privacy_guard_dlp.cpp b/client/src/privacy_guard_dlp.cpp
new file mode 100644 (file)
index 0000000..dd35806
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       privacy_guard_dlp.cpp
+ * @brief       external API functions for DLP
+ */
+
+#include "privacy_guard_dlp.h"
+#include "DlpRulesManager.h"
+#include "DlpLogsManager.h"
+#include "Utils.h"
+
+/**
+ *   @callgraph
+ */
+void privacy_guard_dlp_init(void)
+{
+       DlpRulesManager::getInstance();
+       DlpLogsManager::getInstance();
+       PG_LOGD("Initializing DLP");
+}
+
+/**
+ *   @callgraph
+ */
+PgDlpResult privacy_guard_dlp_check_leak(const char *hostname, char * const mem, size_t len)
+{
+#ifdef PERF_TEST
+       struct timespec tp_before, tp_after;
+       long interval;
+       clock_gettime(CLOCK_REALTIME, &tp_before);
+#endif
+       current_rules_list rules;
+       PgDlpResult res;
+       DlpRulesManager *pRules = DlpRulesManager::getInstance();
+       DlpLogsManager *pLogs = DlpLogsManager::getInstance();
+
+       /* return DENY if called with NULL values or zero len */
+       if (hostname == NULL || mem == NULL || len == 0) {
+               PG_LOGE("DLP check leak received and empty request, message denied");
+               return PRIV_GUARD_DLP_RESULT_DENY;
+       }
+
+       /* get cached rules from server */
+       rules = pRules->PgGetDlpCurrentRules();
+       if (rules.empty()) {
+#ifdef PERF_TEST
+               clock_gettime(CLOCK_REALTIME, &tp_after);
+               interval = (tp_after.tv_sec - tp_before.tv_sec) * 1000000 + (tp_after.tv_nsec - tp_before.tv_nsec) / 1000;
+               PG_LOGD("DLP check time: %ld us", interval);
+#endif
+               PG_LOGD("No rules found, packet allowed");
+               return PRIV_GUARD_DLP_RESULT_ALLOW;
+       }
+
+       res = pLogs->ParseAndLogLeak(hostname, mem, len, rules);
+
+#ifdef PERF_TEST
+       clock_gettime(CLOCK_REALTIME, &tp_after);
+       interval = (tp_after.tv_sec - tp_before.tv_sec) * 1000000 + (tp_after.tv_nsec - tp_before.tv_nsec) / 1000;
+       PG_LOGD("DLP check time: %ld us", interval);
+#endif
+
+#ifdef _PRIVACY_GUARD_DEBUG
+       if (res == PRIV_GUARD_DLP_RESULT_ALLOW) {
+               PG_LOGD("Packet allowed");
+       } else {
+               PG_LOGD("Packet denied");
+       }
+#endif
+
+       return res;
+}
+
diff --git a/common/inc/DlpUtils.h b/common/inc/DlpUtils.h
new file mode 100644 (file)
index 0000000..c76a5d0
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpUtils.h
+ * @brief      Utility functions for DLP.
+ */
+
+#ifndef __DLP_UTILS_H__
+#define __DLP_UTILS_H__
+
+#include <string>
+
+typedef void * SUB_PARSER_PTR;
+
+#include "DlpPacketParserResult.h"
+#include "privacy_guard_client_types.h"
+
+//// generic /////////////////////
+/**
+ * @fn  int dlp_pattern_validate(PgDlpPatternType ptype, const char *pattern)
+ * @brief      Check if a rule string or pattern is valid or not.
+ *
+ * @param[in] ptype     the pattern type, e.g. PRIV_GUARD_DLP_PATTERN_REGEX
+ * @param[in] pattern   the string or pattern to be checked
+ * @return PRIV_GUARD_ERROR_SUCCESS if the pattern or string is valid or PRIV_GUARD_ERROR_INVALID_PARAMETER otherwise.
+ * @callgraph
+ */
+EXTERN_API int dlp_pattern_validate(PgDlpPatternType ptype, const char *pattern);
+
+//// ahocorasick /////////////////////
+/**
+ * @fn  SUB_PARSER_PTR dlp_ac_init()
+ * @brief      Initialize ahocorasick string search, and return an opaque pointer. The pointer should be freed with dlp_ac_free().
+ *
+ * @return opaque pointer to an object
+ *
+ * @see dlp_ac_free()
+ */
+SUB_PARSER_PTR dlp_ac_init();
+
+/**
+ * @fn  int dlp_ac_add_string(SUB_PARSER_PTR ptr, const char *str, void *user_data)
+ * @brief      Add another string to be searched for.
+ *
+ * @param[in] ptr  a pointer returned from dlp_ac_init()
+ * @param[in] str  a string to be added to the target list
+ * @param[in] user_data user data to associate with any resulting matches
+ *
+ * @return a count of total strings added
+ * @callgraph
+ */
+int dlp_ac_add_string(SUB_PARSER_PTR ptr, const char *str, void *user_data);
+
+/**
+ * @fn  int dlp_ac_string_validate(const char *string)
+ * @brief      Check if a rule string is valid or not.
+ *
+ * @param[in] string   the string to be checked
+ * @return PRIV_GUARD_ERROR_SUCCESS if the string is valid or PRIV_GUARD_ERROR_INVALID_PARAMETER otherwise.
+ * @callgraph
+ */
+int dlp_ac_string_validate(const char *string);
+
+/**
+ * @fn  void dlp_ac_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl)
+ * @brief      Search the data packet for matches.
+ *
+ * @param[in] ptr     a pointer returned from dlp_ac_init()
+ * @param[in] data    a pointer to the data to be parsed
+ * @param[in] length  length in bytes of the data to be parsed
+ * @param[out] rl     search results are appended to end of rl
+ * @callgraph
+ *
+ */
+void dlp_ac_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl);
+
+/**
+ * @fn  void dlp_ac_free(SUB_PARSER_PTR ptr)
+ * @brief      Free an ac object after use
+ *
+ * @param[in] ptr  a pointer returned from dlp_ac_init()
+ * @callgraph
+ */
+void dlp_ac_free(SUB_PARSER_PTR ptr);
+
+///////// pcre ////////////////////
+/**
+ * @fn  SUB_PARSER_PTR dlp_pcre_init()
+ * @brief      Initialize regex search, and return an opaque pointer. The pointer should be freed with dlp_pcre_free().
+ *
+ * @return opaque pointer to an object
+ *
+ * @see dlp_pcre_free()
+ * @callgraph
+ */
+SUB_PARSER_PTR dlp_pcre_init();
+
+/**
+ * @fn  int dlp_pcre_pattern_validate(const char *pattern)
+ * @brief      Check if a rule pattern is valid or not.
+ *
+ * @param[in] pattern   the pattern to be checked
+ * @return PRIV_GUARD_ERROR_SUCCESS if the pattern is valid or PRIV_GUARD_ERROR_INVALID_PARAMETER otherwise.
+ * @callgraph
+ */
+int dlp_pcre_pattern_validate(const char *pattern);
+
+/**
+ * @fn  int dlp_pcre_add_pattern(SUB_PARSER_PTR ptr, const char *pat, void *user_data)
+ * @brief      Add another pattern to be searched for.
+ *
+ * @param[in] ptr  a pointer returned from dlp_pcre_init()
+ * @param[in] pat  a pattern to be added to the target list
+ * @param[in] user_data user data to associate with any resulting matches
+ *
+ * @return a count of total patterns added
+ * @callgraph
+ */
+int dlp_pcre_add_pattern(SUB_PARSER_PTR ptr, const char *pat, void *user_data);
+
+/**
+ * @fn  void dlp_pcre_search(SUB_PARSER_PTR ptr, const char *data, size_t length, PrivacyGuardDLPPacketParserResultList &rl)
+ * @brief      Search the data packet for pattern matches.
+ *
+ * @param[in] ptr     a pointer returned from dlp_pcre_init()
+ * @param[in] data    a pointer to the data to be parsed
+ * @param[in] length  length in bytes of the data to be parsed
+ * @callgraph
+ */
+void dlp_pcre_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl);
+
+/**
+ * @fn  void dlp_pcre_free(SUB_PARSER_PTR ptr)
+ * @brief      Free a pcre object after use
+ *
+ * @param[in] ptr  a pointer returned from dlp_pcre_init()
+ * @param[out] rl  search results are appended to end of rl
+ * @callgraph
+ */
+void dlp_pcre_free(SUB_PARSER_PTR ptr);
+
+#endif /* __DLP_UTILS_H__ */
index 1d85a85..61fd487 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       IPrivacyGuard.h
+ */
+
 #ifndef _IPRIVACY_GUARD_H_
 #define _IPRIVACY_GUARD_H_
 
@@ -29,15 +33,15 @@ class SocketClient;
 class EXTERN_API IPrivacyGuard
 {
 public:
-       int addAppPackagePrivacyInfo(const std::string pkgId, const std::list < std::string >& pList, bool privacyPopupRequired);
+       int addAppPackagePrivacyInfo(const std::string pkgId, const std::list<std::string> &pList, bool privacyPopupRequired);
 
        int removeAppPackagePrivacyInfo(const std::string pkgId);
 
        int setPrivacySetting(const std::string pkgId, const std::string privacyId, bool isEnabled);
 
-       int getPrivacyAppPackages(std::list < std::string >& pList);
+       int getPrivacyAppPackages(std::list<std::string> &pList);
 
-       int getAppPackagePrivacyInfo(const std::string pkgId, std::list < std::pair <std::string, bool > > & pList);
+       int getAppPackagePrivacyInfo(const std::string pkgId, std::list<std::pair<std::string, bool>> &pList);
 };
 
-#endif // _IPRIVACY_GUARD_H_
\ No newline at end of file
+#endif // _IPRIVACY_GUARD_H_
index 3fea18d..b28fcc0 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyGuardCommon.h
+ */
+
 #ifndef _PRIVACY_GUARD_COMMON_H_
 #define _PRIVACY_GUARD_COMMON_H_
 
@@ -21,4 +25,4 @@
 #include <db-util.h>
 #include <stdbool.h>
 
-#endif // _PRIVACY_GUARD_COMMON_H_
\ No newline at end of file
+#endif // _PRIVACY_GUARD_COMMON_H_
old mode 100755 (executable)
new mode 100644 (file)
index 209ee30..a2bb71a
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyGuardTypes.h
+ */
+
 #ifndef _PRIVACYGUARDTYPES_H_
 #define _PRIVACYGUARDTYPES_H_
 
 #include <string>
+#include <list>
 #include <tzplatform_config.h>
+#include <semaphore.h>
 #include "privacy_guard_client_types.h"
 
-#define PRIVACY_DB_PATH                tzplatform_mkpath(TZ_SYS_DB,".privacy_guard.db")
+#define PRIVACY_DB_PATH                tzplatform_mkpath(TZ_SYS_DB, ".privacy_guard.db")
 #define GLOBAL_USER                    tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 #define LEN_PRIVACY_ID 128
-#define LEN_PACKAGE_ID 128
 #define CYNARA_BUFFER_SIZE     100
 #define DEFAULT_MONITOR_POLICY 0
+#define KEEP_LOG_DAYS_WEEKLY 7
+#define PRIVACY_SEM_INITVAL "/privacy_guard-%d"
 
 typedef struct _privacy_data_s {
        char privacy_id[LEN_PRIVACY_ID];
@@ -45,7 +52,63 @@ typedef struct _package_privacy_data_s {
        char privacy_id[LEN_PRIVACY_ID];
 } package_privacy_data_s;
 
-static const std::string SERVER_ADDRESS ("/tmp/privacy_guard_server");
+typedef struct _leak_log_get_data_s {
+       int id;
+       time_t time_stamp;
+       PgDlpAction action;
+       char application_name[LEN_APPLICATION_NAME];
+       char application_icon[LEN_APPLICATION_ICON];
+       char destination[LEN_DESTINATION];
+} leak_log_get_data_s;
+
+typedef struct _packet_data_s {
+       int len;
+       void *buffer;
+} packet_data_s;
+
+typedef struct _leak_log_insert_common_data_s {
+       int user_id;
+       char application_id[LEN_APPLICATION_ID];
+       char application_name[LEN_APPLICATION_NAME];
+       char application_version[LEN_APPLICATION_VERSION];
+       char application_icon[LEN_APPLICATION_ICON];
+       char package_id[LEN_PACKAGE_ID];
+       char destination[LEN_DESTINATION];
+       packet_data_s pkt_data;
+} leak_log_insert_common_data_s;
+
+typedef struct _leak_log_insert_data_s {
+       int pattern_id;
+       PgDlpAction action;
+       int leak_offset;
+       int leak_len;
+} leak_log_insert_data_s;
+
+typedef struct _current_rules_s {
+       int id;
+       int pattern_id;
+       PgDlpAction action;
+       PgDlpPatternType type;
+       char pattern[LEN_PATTERN];
+} current_rules_s;
+
+typedef std::list<current_rules_s> current_rules_list;
+
+typedef struct _privacy_semaphore_s {
+       int pid;
+       sem_t *sem;
+} privacy_semaphore_s;
+
+typedef struct _custom_rule_s {
+       int id;
+       PgDlpAction action;
+       int pattern_id;
+       char name[LEN_NAME];
+       char description[LEN_DESCRIPTION];
+       char application_id[LEN_APPLICATION_ID];
+} custom_rule_s;
+
+static const std::string SERVER_ADDRESS("/tmp/privacy_guard_server");
 static const std::string DBUS_PATH("/privacy_guard/dbus_notification");
 static const std::string DBUS_SIGNAL_INTERFACE("org.tizen.privacy_guard.signal");
 static const std::string DBUS_SIGNAL_SETTING_CHANGED("privacy_setting_changed");
index 769365c..6ad471b 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyIdInfo.h
+ */
+
 #ifndef _PRIVACYIDINFO_H_
 #define _PRIVACYIDINFO_H_
 
@@ -29,10 +33,10 @@ private:
 
 public:
        static int initialize(void);
-       static int getPrivacyIdFromPrivilege(const std::string privilege, std::stringprivacyId);
-       static int getPrivacyIdListFromPrivilegeList(const std::list< std::string > privilegeList, std::list< std::string >& privacyIdList);
+       static int getPrivacyIdFromPrivilege(const std::string privilege, std::string &privacyId);
+       static int getPrivacyIdListFromPrivilegeList(const std::list<std::string> privilegeList, std::list<std::string> &privacyIdList);
        static bool isValidPrivacyId(const std::string privacyId);
-       static int getAllPrivacyId(std::list< std::string >& privacyIdList);
+       static int getAllPrivacyId(std::list<std::string> &privacyIdList);
 };
 
-#endif //_PRIVACYIDINFO_H_
\ No newline at end of file
+#endif //_PRIVACYIDINFO_H_
index 08dd212..48668ba 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketConnection.h
+ */
+
 #ifndef _SOCKETCONNECTION_H_
 #define _SOCKETCONNECTION_H_
 
 
 class EXTERN_API SocketConnection
 {
-
 public:
-       explicit SocketConnection(int socket_fd) : m_socketStream(socket_fd){
-               PG_LOGI("Created");
-       }
+       explicit SocketConnection(int socket_fd) : m_socketStream(socket_fd) { PG_LOGI("Created"); }
 
        template<typename T, typename ...Args>
-       int read(T* out, const Args&... args )
+       int read(T *out, const Args&... args)
        {
                int res = read(out);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
@@ -55,12 +56,12 @@ public:
        }
 
        template<typename T>
-       int read(Tout)
+       int read(T *out)
        {
                int length = 0;
                int res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
-               char* pBuf = new (std::nothrow) char[length + 1];
+               char* pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
 
                res = m_socketStream.readStream(length, pBuf);
@@ -81,7 +82,7 @@ public:
                int res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
 
-               char* pBuf = new (std::nothrow) char[length + 1];
+               char* pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
 
                res = m_socketStream.readStream(length, pBuf);
@@ -89,24 +90,24 @@ public:
 
                pBuf[length] = 0;
 
-               *pB = * reinterpret_cast <bool* > (pBuf);
+               *pB = * reinterpret_cast <bool * > (pBuf);
 
                delete[] pBuf;
 
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int read(boolb)
+       int read(bool &b)
        {
                return read(&b);
        }
 
-       int read(inti)
+       int read(int &i)
        {
                return read(&i);
        }
 
-       int read(time_ttime)
+       int read(time_t &time)
        {
                return read(&time);
        }
@@ -117,15 +118,15 @@ public:
                int res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
 
-               char* pBuf = new (std::nothrow) char[length + 1];
-               TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
+               char* pBuf = new(std::nothrow) char[length + 1];
+               TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d target %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY, length + 1);
 
                res = m_socketStream.readStream(length, pBuf);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, delete[] pBuf, "readStream : %d", res);
 
                pBuf[length] = 0;
 
-               *pI = * reinterpret_cast <int* > (pBuf);
+               *pI = * reinterpret_cast <int*> (pBuf);
 
                delete[] pBuf;
 
@@ -138,7 +139,7 @@ public:
                int res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
 
-               char* pBuf = new (std::nothrow) char[length + 1];
+               char* pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
 
                res = m_socketStream.readStream(length, pBuf);
@@ -146,7 +147,7 @@ public:
 
                pBuf[length] = 0;
 
-               *pUi = * reinterpret_cast <unsigned int* > (pBuf);
+               *pUi = * reinterpret_cast<unsigned int*> (pBuf);
 
                delete[] pBuf;
 
@@ -159,7 +160,7 @@ public:
                int res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
 
-               char* pBuf = new (std::nothrow) char[length + 1];
+               char* pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
 
                res = m_socketStream.readStream(length, pBuf);
@@ -174,13 +175,13 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int read(std::stringpStr)
+       int read(std::string *pStr)
        {
                int length = 0;
                int res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
 
-               char* pBuf = new (std::nothrow) char[length + 1];
+               char* pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
 
                m_socketStream.readStream(length, pBuf);
@@ -194,12 +195,42 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int read(std::stringstr)
+       int read(std::string &str)
        {
                return read(&str);
        }
 
-       int read(privacy_data_s& out)
+       int read(char *str, int size)
+       {
+               int length;
+
+               int res = m_socketStream.readStream(sizeof(length), &length);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS && length < size, res, , "readStream : %d", res);
+               res = m_socketStream.readStream(length, str);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
+               str[length] = '\0';
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int readblob(char *str, int size)
+       {
+               int length;
+
+               int res = m_socketStream.readStream(sizeof(length), &length);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
+               if (length < size)
+                 size = length;
+               res = m_socketStream.readStream(size, str);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
+               if (length > size) {
+                 res = m_socketStream.readStream(length - size, NULL);
+                 TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
+               }
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(privacy_data_s &out)
        {
                int length = 0;
                int res = 0;
@@ -207,7 +238,7 @@ public:
                // privacy id
                res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
-               pBuf = new (std::nothrow) char[length + 1];
+               pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
                m_socketStream.readStream(length, pBuf);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, delete[] pBuf, "readStream : %d", res);
@@ -223,7 +254,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int read(package_data_sout)
+       int read(package_data_s &out)
        {
                int length = 0;
                int res = 0;
@@ -232,7 +263,7 @@ public:
                // package id
                res = m_socketStream.readStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readStream : %d", res);
-               pBuf = new (std::nothrow) char[length + 1];
+               pBuf = new(std::nothrow) char[length + 1];
                TryReturn(pBuf != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
                m_socketStream.readStream(length, pBuf);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, delete[] pBuf, "readStream : %d", res);
@@ -256,17 +287,383 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
+       int read(dlp_profile_s* out)
+       {
+               // enabled
+               int res = read(&out->enabled);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // profile
+               res = read((int*)&out->profile);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // keep log days
+               res = read(&out->keep_log_days);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(leak_log_get_data_s &out)
+       {
+               // id
+               int res = read(&out.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // time stamp
+               res = read(&out.time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // action
+               res = read((int *)&out.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application name
+               res = read(out.application_name, LEN_APPLICATION_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application icon
+               res = read(out.application_icon, LEN_APPLICATION_ICON);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // destination
+               res = read(out.destination, LEN_DESTINATION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(leak_log_get_app_count_s &out)
+       {
+               // application name
+               int res = read(out.application_name, LEN_APPLICATION_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // start time stamp
+               res = read(&out.first_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // end time stamp
+               res = read(&out.last_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application icon
+               res = read(out.application_icon, LEN_APPLICATION_ICON);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leak_count
+               res = read(&out.leak_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(leak_log_get_category_count_s &out)
+       {
+               // category.id
+               int res = read(out.category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // start time stamp
+               res = read(&out.first_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // end time stamp
+               res = read(&out.last_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leak_count
+               res = read(&out.leak_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(leak_log_get_detail_data_s *out)
+       {
+               // action
+               int res = read((int*)&out->action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application id
+               res = read(out->application_id, LEN_APPLICATION_ID);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application name
+               res = read(out->application_name, LEN_APPLICATION_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application version
+               res = read(out->application_version, LEN_APPLICATION_VERSION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application icon
+               res = read(out->application_icon, LEN_APPLICATION_ICON);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // package id
+               res = read(out->package_id, LEN_PACKAGE_ID);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // destination
+               res = read(out->destination, LEN_DESTINATION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern name
+               res = read(out->pattern_name, LEN_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // category.id
+               res = read(out->category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pkt_len
+               res = read(&out->pkt_len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // raw packet
+               res = readblob(out->raw_packet, out->pkt_len < LEN_RAW_PACKET ? out->pkt_len : LEN_RAW_PACKET);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "readblob (len %d) : %d", out->pkt_len < LEN_RAW_PACKET ? out->pkt_len : LEN_RAW_PACKET, res);
+
+               // leak offset
+               res = read(&out->leak_offset);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leak length
+               res = read(&out->leak_len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(leak_log_insert_common_data_s &out)
+       {
+               // user id
+               int res = read(&out.user_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application ID
+               res = read(out.application_id, LEN_APPLICATION_ID);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application name
+               res = read(out.application_name, LEN_APPLICATION_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application version
+               res = read(out.application_version, LEN_APPLICATION_VERSION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application icon
+               res = read(out.application_icon, LEN_APPLICATION_ICON);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // package ID
+               res = read(out.package_id, LEN_PACKAGE_ID);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // destination
+               res = read(out.destination, LEN_DESTINATION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pktlen
+               res = read((int *)&out.pkt_data.len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               out.pkt_data.buffer = new(std::nothrow) char[out.pkt_data.len];
+               TryReturn(out.pkt_data.buffer != NULL, PRIV_GUARD_ERROR_OUT_OF_MEMORY, , "new : %d", PRIV_GUARD_ERROR_OUT_OF_MEMORY);
+
+               // pktdata
+               res = readblob((char *)out.pkt_data.buffer, out.pkt_data.len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(leak_log_insert_data_s &out)
+       {
+               // pattern id
+               int res = read(&out.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // action
+               res = read((int *)&out.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leak offset
+               res = read(&out.leak_offset);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leak length
+               res = read(&out.leak_len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(current_rules_s &out)
+       {
+               // id
+               int res = read(&out.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // patternId
+               res = read((int*)&out.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // action
+               res = read((int*)&out.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern type
+               res = read((int*)&out.type);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // raw packet
+               res = read(out.pattern, LEN_PATTERN);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(custom_rule_s &out)
+       {
+               // id
+               int res = read(&out.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // action
+               res = read((int *)&out.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern_id
+               res = read(&out.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // rule name
+               res = read(out.name, LEN_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // rule description
+               res = read(out.description, LEN_DESCRIPTION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application id
+               res = read(out.application_id, LEN_APPLICATION_ID);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(get_custom_rule_s &out)
+       {
+               // rule id
+               int res = read(&out.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // action
+               res = read((int *)&out.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern_id
+               res = read(&out.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern
+               res = read(out.pattern, LEN_PATTERN);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // name
+               res = read(out.name, LEN_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // description
+               res = read(out.description, LEN_DESCRIPTION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // application id
+               res = read(out.application_id, LEN_APPLICATION_ID);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leaks count
+               res = read(&out.leaks_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(get_pattern_s &out)
+       {
+               // id
+               int res = read(&out.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern
+               res = read(out.pattern, LEN_PATTERN);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern name
+               res = read(out.name, LEN_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern description
+               res = read(out.description, LEN_DESCRIPTION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern type
+               res = read((int *)&out.type);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // category.id
+               res = read(out.category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // undeletable
+               res = read(&out.undeletable);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // leaks_count
+               res = read(&out.leaks_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int read(pattern_s &out)
+       {
+               // pattern
+               int res = read(out.pattern, LEN_PATTERN);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern name
+               res = read(out.name, LEN_NAME);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern description
+               res = read(out.description, LEN_DESCRIPTION);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // pattern type
+               res = read((int *)&out.type);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               // category.id
+               res = read(out.category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
        template < typename T >
-       int  read (std::list<T>& list)
+       int read(std::list<T> &list)
        {
                int length = 0;
                int res = read(length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
 
-               for (int i = 0; i < length; ++i)
-               {
+               for (int i = 0; i < length; ++i) {
                        T obj;
-                       res = read (obj);
+                       res = read(obj);
                        TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
                        list.push_back(obj);
                }
@@ -275,30 +672,30 @@ public:
        }
 
        template < typename T >
-       int read (std::list<T>* pList)
+       int read(std::list<T> *pList)
        {
                return read(*pList);
        }
 
        template < typename K, typename P >
-       int read (std::pair<K, P>& pair)
+       int read(std::pair<K, P> &pair)
        {
-               int res = read( pair.first);
+               int res = read(pair.first);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
-               res = read( pair.second);
+               res = read(pair.second);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "read : %d", res);
 
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
        template < typename K, typename P >
-       int read (std::pair<K, P>* pPair)
+       int read(std::pair<K, P> *pPair)
        {
-               return read( *pPair);
+               return read(*pPair);
        }
 
        template<typename T, typename ...Args>
-       int write(const Tin, const Args&... args)
+       int write(const T &in, const Args&... args)
        {
                int res = write(in);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
@@ -308,7 +705,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const std::stringin)
+       int write(const std::string &in)
        {
                int length = in.size();
                int res = m_socketStream.writeStream(sizeof(length), &length);
@@ -319,7 +716,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const unsigned intin)
+       int write(const unsigned int &in)
        {
                int length = sizeof(in);
                int res = m_socketStream.writeStream(sizeof(length), &length);
@@ -330,7 +727,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const intin)
+       int write(const int &in)
        {
                int length = sizeof(in);
                int res = m_socketStream.writeStream(sizeof(length), &length);
@@ -341,7 +738,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const time_tin)
+       int write(const time_t &in)
        {
                int length = sizeof(in);
                int res = m_socketStream.writeStream(sizeof(length), &length);
@@ -352,7 +749,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const boolin)
+       int write(const bool &in)
        {
                int length = sizeof(in);
                int res = m_socketStream.writeStream(sizeof(length), &length);
@@ -363,13 +760,27 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const char*& in)
+       int write(const char* in)
        {
-               int length = strlen(in);
+               int length = (in != NULL) ? strlen(in) : 0;
                int res = m_socketStream.writeStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
-               res = m_socketStream.writeStream(length, in);
+               if (length > 0) {
+                       res = m_socketStream.writeStream(length, in);
+                       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+               }
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const char* in, int length)
+       {
+               int res = m_socketStream.writeStream(sizeof(length), &length);
                TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+               if (length > 0) {
+                       res = m_socketStream.writeStream(length, in);
+                       TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+               }
 
                return PRIV_GUARD_ERROR_SUCCESS;
        }
@@ -386,7 +797,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const privacy_data_sin)
+       int write(const privacy_data_s &in)
        {
                // privacy id
                int length = strlen(in.privacy_id);
@@ -406,7 +817,7 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
-       int write(const package_data_sin)
+       int write(const package_data_s &in)
        {
                // package id
                int length = strlen(in.package_id);
@@ -432,6 +843,347 @@ public:
                return PRIV_GUARD_ERROR_SUCCESS;
        }
 
+       int write(const dlp_profile_s* in)
+       {
+               // enabled
+               int res = write(in->enabled);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // profile
+               res = write((int)in->profile);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // keep log days
+               res = write(in->keep_log_days);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const leak_log_get_data_s &in)
+       {
+               // id
+               int res = write(in.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // time stamp
+               res = write(in.time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // action
+               res = write((int)in.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application name
+               res = write(in.application_name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application icon
+               res = write(in.application_icon);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // destination
+               res = write(in.destination);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const leak_log_get_app_count_s &in)
+       {
+               // application name
+               int res = write(in.application_name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // start time stamp
+               res = write(in.first_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // end time stamp
+               res = write(in.last_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application icon
+               res = write(in.application_icon);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leak_count
+               res = write(in.leak_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const leak_log_get_category_count_s &in)
+       {
+               // category.id
+               int res = write(in.category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // start time stamp
+               res = write(in.first_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // end time stamp
+               res = write(in.last_time_stamp);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leak_count
+               res = write(in.leak_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const leak_log_get_detail_data_s *in)
+       {
+               // action
+               int res = write((int)in->action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application ID
+               res = write(in->application_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application name
+               res = write(in->application_name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application version
+               res = write(in->application_version);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application icon
+               res = write(in->application_icon);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // package ID
+               res = write(in->package_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // destination
+               res = write(in->destination);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern name
+               res = write(in->pattern_name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // category.id
+               res = write(in->category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // packet length
+               res = write(in->pkt_len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // raw packet
+               res = write(in->raw_packet, in->pkt_len < LEN_RAW_PACKET ? in->pkt_len : LEN_RAW_PACKET);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write (blob len %d): %d", in->pkt_len < LEN_RAW_PACKET ? in->pkt_len : LEN_RAW_PACKET, res);
+
+               // leak offset
+               res = write(in->leak_offset);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leak length
+               res = write(in->leak_len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const packet_data_s &in)
+       {
+               int sizint = (int)sizeof(int);
+               int res = m_socketStream.writeStream(sizeof(sizint), &sizint);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+
+               res = m_socketStream.writeStream(sizeof(in.len), &in.len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+
+               res = m_socketStream.writeStream(sizeof(in.len), &in.len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+
+               res = m_socketStream.writeStream(in.len, in.buffer);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "writeStream : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const leak_log_insert_data_s &in)
+       {
+               // pattern id
+               int res = write(in.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // action
+               res = write((int)in.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leak offset
+               res = write(in.leak_offset);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leak length
+               res = write(in.leak_len);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const current_rules_s &in)
+       {
+               // id
+               int res = write(in.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // patternId
+               res = write((int)in.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // action
+               res = write((int)in.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // type
+               res = write((int)in.type);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern
+               res = write(in.pattern);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const custom_rule_s &in)
+       {
+               // id
+               int res = write(in.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // action
+               res = write((int)in.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern_id
+               res = write(in.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // rule name
+               res = write(in.name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // rule description
+               res = write(in.description);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application ID
+               res = write(in.application_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const get_custom_rule_s &in)
+       {
+               // rule id
+               int res = write(in.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // action
+               res = write((int)in.action);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern id
+               res = write(in.pattern_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern
+               res = write(in.pattern);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern name
+               res = write(in.name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern description
+               res = write(in.description);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // application ID
+               res = write(in.application_id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leaks count
+               res = write(in.leaks_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const get_pattern_s &in)
+       {
+               // id
+               int res = write(in.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern
+               res = write(in.pattern);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern name
+               res = write(in.name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern description
+               res = write(in.description);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern type
+               res = write((int)in.type);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // category.id
+               res = write(in.category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // state
+               res = write(in.undeletable);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // leaks count
+               res = write(in.leaks_count);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
+       int write(const pattern_s &in)
+       {
+               // pattern
+               int res = write(in.pattern);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern name
+               res = write(in.name);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern description
+               res = write(in.description);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // pattern type
+               res = write((int)in.type);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               // category.id
+               res = write(in.category.id);
+               TryReturn(res == PRIV_GUARD_ERROR_SUCCESS, res, , "write : %d", res);
+
+               return PRIV_GUARD_ERROR_SUCCESS;
+       }
+
        template<typename T, typename ...Args>
        int write(const T* in, const Args&... args)
        {
@@ -466,7 +1218,7 @@ public:
        }
 
        template<typename K, typename T>
-       int write(const std::pair<K, T&>pPair)
+       int write(const std::pair<K, T&> *pPair)
        {
                return write(*pPair);
        }
@@ -486,7 +1238,7 @@ public:
        }
 
        template<typename T>
-       int write(const std::list <T>pList)
+       int write(const std::list <T> *pList)
        {
                return write(*pList);
        }
index 460d6b6..45aa630 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketStream.h
+ */
+
 #ifndef _SOCKETSTREAM_H_
 #define _SOCKETSTREAM_H_
 
@@ -25,8 +29,6 @@ class EXTERN_API SocketStream
 public:
        explicit SocketStream(int socket_fd)
                : m_socketFd(socket_fd)
-               , m_bytesRead(0)
-               ,m_bytesWrote(0)
        {
                PG_LOGI("Created");
        }
@@ -37,8 +39,6 @@ public:
 private:
        int throwWithErrnoMessage(std::string specificInfo);
        int m_socketFd;
-       int m_bytesRead;
-       int m_bytesWrote;
 };
 
-#endif //_SOCKETSTREAM_H_
\ No newline at end of file
+#endif //_SOCKETSTREAM_H_
index c0d1851..36710fb 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       Utils.h
+ */
+
 #ifndef _UTILS_H_
 #define _UTILS_H_
 
 //////////////////////////////////////////////////////////////////////////
 
 #define IF_MATCH_RET_ERROR(condition, msgFormat, error)        \
-       if (condition) { \
-               PG_LOGE(msgFormat, error); \
-               return error; \
-       } else {;}
-#define        TryCatchLogReturn(condition, expr, r, logFormat)        if (!(condition)) { \
-               LOGE(logFormat); \
-               expr; \
-               return r; \
-       } else {;}
+       if (condition) {                                                                                \
+               PG_LOGE(msgFormat, error);                                                      \
+               return error;                                                                           \
+       } else {; }
+#define        TryCatchLogReturn(condition, expr, r, logFormat)        if (!(condition)) {     \
+               LOGE(logFormat);                                                                                                                        \
+               expr;                                                                                                                                           \
+               return r;                                                                                                                                       \
+       } else {; }
 
 #define        TryCatchResLogReturn(condition, expr, r, logFormat, res)        if (!(condition)) { \
-               LOGE(logFormat, res); \
-               expr; \
-               return r; \
+               LOGE(logFormat, res);                                                                                                                           \
+               expr;                                                                                                                                                           \
+               return r;                                                                                                                                                       \
        } else {;}
 
 
-#define TryReturn(condition, r, expr, ...) \
-       if ( !(condition) ) { \
-               LOGE(__VA_ARGS__); \
-               expr; \
-               return r; \
-       } else {;}
+#define TryReturn(condition, r, expr, ...)     \
+       if (!(condition)) {                                             \
+               LOGE(__VA_ARGS__);                                      \
+               expr;                                                           \
+               return r;                                                       \
+       } else {; }
 
-#define SAFE_FREE(var)         \
-               if(var != NULL) { \
-                       free(var);              \
-                       var = NULL;     \
+#define SAFE_FREE(var)                                         \
+               if (var != NULL) {                                      \
+                       free(var);                                              \
+                       var = NULL;                                             \
                }
 
-auto StmtDeleter = [&](sqlite3_stmt* pPtr) {  sqlite3_reset (pPtr); sqlite3_finalize(pPtr); };
+auto StmtDeleter = [&](sqlite3_stmt* pPtr) { sqlite3_reset(pPtr); sqlite3_finalize(pPtr); };
 auto DbDeleter = [&](sqlite3* pPtr) { /*sqlite3_close(pPtr);*/ db_util_close(pPtr); };
 
 #define setStmtToUniquePtr(x, y)               std::unique_ptr < sqlite3_stmt, decltype(StmtDeleter) > x (y, StmtDeleter);
 #define setDbToUniquePtr(x, y)                 std::unique_ptr < sqlite3, decltype(DbDeleter) > x (y, DbDeleter);
 
-#define openDb(dbpath, pHandler, mode) sqlite3* pHandler##Temp = NULL;\
-       {\
-               /*int res = sqlite3_open_v2(dbpath, &pHandler##Temp, mode , NULL);*/\
-               int res = db_util_open_with_options(dbpath, &pHandler##Temp, mode, NULL);\
-               TryCatchResLogReturn(res == SQLITE_OK, , PRIV_GUARD_ERROR_DB_ERROR, "db_util_open_with_options : %d", res);\
-       }\
-       setDbToUniquePtr(pHandler, pHandler##Temp);\
+#define openDb(dbpath, pHandler, mode) sqlite3* pHandler##Temp = NULL;                                                                                         \
+       {                                                                                                                                                                                                                               \
+               /*int res = sqlite3_open_v2(dbpath, &pHandler##Temp, mode , NULL);*/                                                                            \
+               int res = db_util_open_with_options(dbpath, &pHandler##Temp, mode, NULL);                                                                       \
+               TryCatchResLogReturn(res == SQLITE_OK, , PRIV_GUARD_ERROR_DB_ERROR, "db_util_open_with_options : %d", res);     \
+       }                                                                                                                                                                                                                               \
+       setDbToUniquePtr(pHandler, pHandler##Temp);                                                                                                                                             \
 
 static const int MAX_DATABASE_RETRY_COUNT = 5;
 static const int SLEEP_TIME = 50000;
-#define prepareDb(pHandler, sql, pStmt)        sqlite3_stmt* pStmt##Temp;\
-       {\
-               int res = SQLITE_OK;\
-               for (int dbRetryCount = 0; dbRetryCount < MAX_DATABASE_RETRY_COUNT; dbRetryCount++)\
-               {\
-                       res = sqlite3_prepare_v2(pHandler.get(), sql, -1, & pStmt##Temp, NULL);\
-                       if (res != SQLITE_BUSY)\
-                       {\
-                               break;\
-                       }\
-                       else\
-                       {\
-                               LOGE("[DbRetryCount][%d]: Database is busy!", dbRetryCount); \
-                               usleep(SLEEP_TIME);\
-                       }\
-               }\
-               TryCatchResLogReturn(res == SQLITE_OK, , PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);\
-       }\
+#define prepareDb(pHandler, sql, pStmt)        sqlite3_stmt* pStmt##Temp;                                                                                              \
+       {                                                                                                                                                                                                                               \
+               int res = SQLITE_OK;                                                                                                                                                                            \
+               for (int dbRetryCount = 0; dbRetryCount < MAX_DATABASE_RETRY_COUNT; dbRetryCount++) {                                           \
+                       res = sqlite3_prepare_v2(pHandler.get(), sql, -1, & pStmt##Temp, NULL);                                                                 \
+                       if (res != SQLITE_BUSY) {                                                                                                                                                               \
+                               break;                                                                                                                                                                                          \
+                       } else  {                                                                                                                                                                                               \
+                               LOGE("[DbRetryCount][%d]: Database is busy!", dbRetryCount);                                                                            \
+                               usleep(SLEEP_TIME);                                                                                                                                                                     \
+                       }                                                                                                                                                                                                               \
+               }                                                                                                                                                                                                                       \
+               TryCatchResLogReturn(res == SQLITE_OK, , PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);            \
+       }                                                                                                                                                                                                                               \
        setStmtToUniquePtr(pStmt, pStmt##Temp);
 
 class Utils
@@ -129,4 +129,13 @@ public:
        static int PgCheckAccess(void);
 };
 
+/**
+ * @brief      Copy at most (dstsize - 1) bytes from string src to string dst, appending a terminating null byte.
+ *
+ * @param[in]   dst       a pointer to the string to be written to. Must be at least dstsize bytes in length.
+ * @param[in]   src       a pointer to the string to be copied from.
+ * @param[in]   dstsize   the maximum number of bytes to be copied.
+ */
+extern "C" void pg_strlcpy(char *dst, const char *src, size_t dstsize);
+
 #endif //_UTILS_H_
diff --git a/common/src/DlpUtils.cpp b/common/src/DlpUtils.cpp
new file mode 100644 (file)
index 0000000..3c21ad9
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpUtils.cpp
+ * @brief      Utility functions for DLP.
+ */
+
+#include <string>
+#include <string.h>
+#include <stdio.h>
+#include "DlpUtils.h"
+#include "DlpPacketParserResult.h"
+#include "privacy_guard_client_types.h"
+#include "../../ahocorasick/ahocorasick.h"
+
+#include <pcre.h>
+
+////////////////// general ///////////////////////////////
+
+/**
+ * @callgraph
+ */
+int dlp_pattern_validate(PgDlpPatternType ptype, const char *pattern)
+{
+       int res = PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       switch (ptype) {
+       case PRIV_GUARD_DLP_PATTERN_REGEX:
+               res = dlp_pcre_pattern_validate(pattern);
+               break;
+       case PRIV_GUARD_DLP_PATTERN_STRING:
+               res = dlp_ac_string_validate(pattern);
+               break;
+       default:
+               break;
+       }
+       return res;
+}
+
+///////////////// ahocorasick ////////////////////////////
+
+/**
+ * @callgraph
+ */
+SUB_PARSER_PTR dlp_ac_init()
+{
+       return ahocorasick_init();
+}
+
+/**
+ * @callgraph
+ */
+int dlp_ac_string_validate(const char *string)
+{
+       if (!strlen(string)) {
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+/**
+ * @callgraph
+ */
+int dlp_ac_add_string(SUB_PARSER_PTR ptr, const char *cst, void *user_data)
+{
+       ac_instance *ac = (ac_instance *)ptr;
+       if (dlp_ac_string_validate(cst) != PRIV_GUARD_ERROR_SUCCESS) {
+               return ac->added;
+       }
+       return ahocorasick_add_string(ac, cst, user_data);
+}
+
+/**
+ * @callgraph
+ */
+void dlp_ac_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl)
+{
+       ac_match *match;
+       ac_instance *ac = (ac_instance *)ptr;
+
+       /* if we have no strings set we must return */
+       if (ac->root == NULL) {
+               return;
+       }
+       /* Set the input text */
+       ahocorasick_set_text(ac, data, length, 0);
+
+       /* The ownership of the input text belongs to the caller program. I.e. the
+        * API does not make a copy of that. It must remain valid until the end
+        * of search of the given chunk. */
+
+       /* Find matches */
+       while ((match = ahocorasick_find_next(ac))) {
+               DlpPacketParserResult res(((const current_rules_s *)match->user_data)->pattern_id, ((const current_rules_s *)match->user_data)->action, match->position, match->size);
+               rl.push_back(res);
+       }
+}
+
+/**
+ * @callgraph
+ */
+void dlp_ac_free(SUB_PARSER_PTR ptr)
+{
+       ahocorasick_free((ac_instance *)ptr);
+}
+
+///////////////// pcre ////////////////////////////
+
+typedef struct {
+       pcre *compiled;
+       pcre_extra *extra;
+       void *user_data;
+} DlpPcre;
+
+/**
+ * @callgraph
+ */
+SUB_PARSER_PTR dlp_pcre_init()
+{
+       std::list<DlpPcre> *complist = new std::list<DlpPcre>;
+       return (SUB_PARSER_PTR)(complist);
+};
+
+/**
+ * @callgraph
+ */
+int dlp_pcre_add_pattern(SUB_PARSER_PTR ptr, const char *pat, void *user_data)
+{
+       std::list<DlpPcre> *complist = (std::list<DlpPcre> *)ptr;
+
+       const char *errorptr;
+       int erroroffset;
+
+       PCRE_SPTR pattern = pat;
+
+       DlpPcre xx;
+
+       xx.user_data = user_data;
+
+       /* compile the regex */
+       xx.compiled = pcre_compile(
+                             pattern,               /* the pattern */
+                             0,                     /* default options */
+                             &errorptr,             /* for error */
+                             &erroroffset,          /* for error offset */
+                             NULL);                 /* use default compile context */
+
+       if (xx.compiled != NULL) {
+               /* Optimize the regex */
+               xx.extra = pcre_study(xx.compiled, 0, &errorptr);
+               if (errorptr == NULL) {
+                       complist->push_back(xx);
+               }
+       }
+
+       return complist->size();
+}
+
+/**
+ * @callgraph
+ */
+int dlp_pcre_pattern_validate(const char *pattern)
+{
+       SUB_PARSER_PTR sp;
+       int res = PRIV_GUARD_ERROR_SUCCESS;
+       if (!strlen(pattern)) {
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+       sp = dlp_pcre_init();
+       if (dlp_pcre_add_pattern(sp, pattern, NULL) == 0) {
+               res = PRIV_GUARD_ERROR_INVALID_PARAMETER;
+       }
+       dlp_pcre_free(sp);
+       return res;
+}
+
+/**
+ * @callgraph
+ */
+void dlp_pcre_search(SUB_PARSER_PTR ptr, const char *data, size_t length, DlpPacketParserResultList &rl)
+{
+       std::list<DlpPcre> *complist = (std::list<DlpPcre> *)ptr;
+
+       int subStrVec[30];
+       int rc, i, offs, idx = 0;
+
+       offs = 0;
+
+       for (auto it = complist->begin(); it != complist->end();) {
+               /* Try to find the regex in aLineToMatch, and report results. */
+               rc = pcre_exec((*it).compiled,
+                              (*it).extra,
+                              data,
+                              length,                 // length of string
+                              offs,                   // Start looking at this point
+                              0,                      // OPTIONS
+                              subStrVec,
+                              30);                    // Length of subStrVec
+
+               if (rc < 0) {
+                       switch (rc) {
+                       case PCRE_ERROR_NOMATCH: //printf("No match\n");
+                               break;
+                       /*
+                         Handle other special cases if you like
+                       */
+                       default: //printf("Matching error %d\n", rc);
+                               break;
+                       }
+                       offs = 0;
+                       it++;
+                       idx++; /* ref to rule number */
+                       continue;
+               }
+
+               if (rc == 0) {
+                       //printf("ovector was not big enough for all the captured substrings\n");
+                       rc = 30 / 3;
+               }
+
+               for (i = 0; i < rc; i++) {
+                       //printf("Match(%2d/%2d): (%2d,%2d)\n", i+1, rc, subStrVec[i*2], subStrVec[i*2+1]);
+                       DlpPacketParserResult res(((const current_rules_s*)(*it).user_data)->pattern_id, ((const current_rules_s*)(*it).user_data)->action, \
+                                                 subStrVec[2 * i], subStrVec[2 * i + 1] - subStrVec[2 * i]);
+                       rl.push_back(res);
+                       offs = subStrVec[i * 2 + 1];
+               }
+       }
+}
+
+/**
+ * @callgraph
+ */
+void dlp_pcre_free(SUB_PARSER_PTR ptr)
+{
+       std::list<DlpPcre> *complist = (std::list<DlpPcre> *)ptr;
+
+       for (auto &it : *complist) {
+               if (it.compiled != NULL) {
+                       /* Free up the regular expression. */
+                       pcre_free(it.compiled);
+               }
+
+               /* Free up the EXTRA PCRE value (may be NULL at this point) */
+               if (it.extra != NULL) {
+#ifdef PCRE_CONFIG_JIT
+                       pcre_free_study(it.extra);
+#else
+                       pcre_free(it.extra);
+#endif
+               }
+       }
+}
index 27f2882..b09e80d 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyIdInfo.cpp
+ */
+
 #include <set>
 #include <libintl.h>
 #include <system_info.h>
index bb9101c..ce6d713 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketConnection.cpp
+ */
+
 #include "SocketConnection.h"
 
 //
index 5672ebe..6a1301b 100755 (executable)
@@ -14,6 +14,9 @@
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketStream.cpp
+ */
 
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -27,7 +30,6 @@
 #define READ_TIMEUOT_NSEC 0
 #define WRITE_TIMEOUT_SEC 0
 #define WRITE_TIMEOUT_NSEC 100000000
-#define MAX_BUFFER 10240
 #define BUF_SIZE 256
 
 int
@@ -43,18 +45,11 @@ SocketStream::readStream(size_t num, void* pBytes)
 {
        TryReturn(pBytes != NULL, -1, , "Null pointer to buffer");
 
-       m_bytesRead += num;
-
-       TryReturn(m_bytesRead <= MAX_BUFFER, -1, , "Too big buffer requested!");
-
-       char partBuffer[MAX_BUFFER];
-       std::string wholeBuffer;
        char buf[BUF_SIZE];
 
        fd_set rset, allset;
        int maxFd;
-       ssize_t bytesRead = 0;
-       ssize_t bytesToRead = (ssize_t) num;
+       ssize_t bytesRead;
 
        timespec timeout;
 
@@ -64,9 +59,10 @@ SocketStream::readStream(size_t num, void* pBytes)
        FD_ZERO(&allset);
        FD_SET(m_socketFd, &allset);
 
-       int ret = -1;
+       int ret;
+       unsigned int currentOffset = 0;
 
-       while(bytesToRead != 0)
+       while (currentOffset < num)
        {
                timeout.tv_sec = READ_TIEMOUT_SEC;
                timeout.tv_nsec = READ_TIMEUOT_NSEC;
@@ -86,28 +82,22 @@ SocketStream::readStream(size_t num, void* pBytes)
 
                if ( FD_ISSET(m_socketFd, &rset) )
                {
-                       bytesRead = read(m_socketFd, partBuffer, num);
+                       bytesRead = read(m_socketFd, ((char *)pBytes) + currentOffset, num - currentOffset);
                        if ( bytesRead <= 0 )
                        {
                                if(errno == ECONNRESET || errno == ENOTCONN || errno == ETIMEDOUT)
                                {
                                        PG_LOGI("Connection closed : %s", strerror_r(errno, buf, sizeof(buf)));
                                        return -1;
-                               }
-                               else if (errno != EAGAIN && errno != EWOULDBLOCK){
+                               } else if (errno != EAGAIN && errno != EWOULDBLOCK){
                                        PG_LOGI("read()");
                                        return -1;
                                }
                        }
 
-                       wholeBuffer.append(partBuffer, bytesRead);
-                       bytesToRead -= bytesRead;
-                       bytesRead = 0;
-                       continue;
+                       currentOffset += bytesRead;
                }
-
        }
-       memcpy(pBytes, wholeBuffer.c_str(), num);
 
        return 0;
 }
@@ -117,10 +107,6 @@ SocketStream::writeStream(size_t num, const void* pBytes)
 {
        TryReturn(pBytes != NULL, -1, , "Null pointer to buffer");
 
-       m_bytesWrote += num;
-
-       TryReturn(m_bytesRead <= MAX_BUFFER, -1, , "Too big buffer requested!");
-
        fd_set wset, allset;
        int maxFd;
        char buf[BUF_SIZE];
@@ -134,11 +120,10 @@ SocketStream::writeStream(size_t num, const void* pBytes)
        FD_SET(m_socketFd, &allset);
 
        int res;
-       int writeRes;
-       int bytesToWrite = num;
+       ssize_t writeRes;
        unsigned int currentOffset = 0;
 
-       while(currentOffset != num)
+       while (currentOffset < num)
        {
                timeout.tv_sec = WRITE_TIMEOUT_SEC;
                timeout.tv_nsec = WRITE_TIMEOUT_NSEC;
@@ -154,23 +139,19 @@ SocketStream::writeStream(size_t num, const void* pBytes)
 
                if(FD_ISSET(m_socketFd, &wset))
                {
-                       if ( (writeRes = write(m_socketFd, reinterpret_cast<const char *>(pBytes) + currentOffset, bytesToWrite)) == -1)
+                       if ( (writeRes = write(m_socketFd, reinterpret_cast<const char *>(pBytes) + currentOffset, num - currentOffset)) == -1)
                        {
                                if(errno == ECONNRESET || errno == EPIPE)
                                {
                                        PG_LOGI("Connection closed : %s", strerror_r(errno, buf, sizeof(buf)));
                                        return -1;
-
-                               }
-                               else if(errno != EAGAIN && errno != EWOULDBLOCK)
-                               {
+                               } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
                                        PG_LOGE("write()");
                                        return -1;
                                }
                        }
                        currentOffset += writeRes;
-                       bytesToWrite -= writeRes;
                }
        }
        return 0;
-}
\ No newline at end of file
+}
index 6c4922e..6c07af5 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       Utils.cpp
+ */
+
 #include "Utils.h"
 #include "privacy_guard_client_types.h"
 #include <aul.h>
@@ -49,4 +53,4 @@ int Utils::PgCheckAccess(void)
        PG_LOGD("Normal Access");
 
        return PRIV_GUARD_ERROR_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/common/src/pg_strlcpy.c b/common/src/pg_strlcpy.c
new file mode 100644 (file)
index 0000000..d00139a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       pg_strlcpy.c
+ * @brief      Provides a safe string copy function.
+ */
+
+#include <string.h>
+
+/**
+ * @callergraph
+ */
+void pg_strlcpy(char *dst, const char *src, size_t dstsize)
+{
+       if (src == NULL) {
+               dst[0] = '\0';
+               return;
+       }
+       if (dstsize > 0) {
+               strncpy(dst, src, dstsize - 1);
+               dst[dstsize - 1] = '\0';
+       }
+}
index 59e2276..62a1b3c 100755 (executable)
@@ -32,11 +32,11 @@ extern "C" {
  * @brief      Called when the reply of the monitor policy request is delivered.
  * @since      tizen 3.0
  *
- * @param[in] privacy_id               The privacy ID
- * @param[in] monitor_policy   The monitor policy (0 or 1)
- * @param[in] user_data                The user data passed from the callback registration function
+ * @param[in] privacy_id                       The privacy ID
+ * @param[in] monitor_policy           The monitor policy (0 or 1)
+ * @param[in] user_data                                The user data passed from the callback registration function
  *
- * @returns: true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
  *
  * @see        privacy_guard_client_foreach_monitor_policy_by_package_id()
  */
@@ -46,10 +46,10 @@ typedef bool (*privacy_guard_client_monitor_policy_cb) (const char *privacy_id,
  * @brief      Called when the reply of the package id request is delivered.
  * @since      tizen 3.0
  *
- * @param[in] package_id       The package ID
- * @param[in] user_data        The user data passed from the callback registration function
+ * @param[in] package_id                       The package ID
+ * @param[in] user_data                                The user data passed from the callback registration function
  *
- * @returns: true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
  *
  * @see        privacy_guard_client_foreach_privacy_package_id()
  */
@@ -63,9 +63,9 @@ typedef bool (*privacy_guard_client_package_id_cb) (const char *package_id, void
  * @param[in] count                                    The privacy count
  * @param[in] latest_access_time       The latest access time
  * @param[in] monitor_policy           The monitor policy (0 or 1)
- * @param[in] user_data        The user data passed from the callback registration function
+ * @param[in] user_data                                The user data passed from the callback registration function
  *
- * @returns: true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
  *
  * @see        privacy_guard_client_foreach_package_info_by_privacy_id()
  */
@@ -75,11 +75,11 @@ typedef bool (*privacy_guard_client_package_info_cb) (const char *package_id, co
  * @brief      Called when the reply of the privacy count request is delivered.
  * @since      tizen 3.0
  *
- * @param[in] privacy_id       The privacy ID
- * @param[in] count            The privacy count
- * @param[in] user_data        The user data passed from the callback registration function
+ * @param[in] privacy_id                       The privacy ID
+ * @param[in] count                                    The privacy count
+ * @param[in] user_data                                The user data passed from the callback registration function
  *
- * @returns: true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
  *
  * @see        privacy_guard_client_foreach_log_count_by_privacy_id()
  */
@@ -89,69 +89,160 @@ typedef bool (*privacy_guard_client_privacy_count_cb) (const char *privacy_id, c
  * @brief      Called when the reply of the privacy count request of package is delivered.
  * @since      tizen 3.0
  *
- * @param[in] privacy_id       The privacy ID
- * @param[in] count            The privacy count of a package
- * @param[in] user_data        The user data passed from the callback registration function
+ * @param[in] privacy_id                       The privacy ID
+ * @param[in] count                                    The privacy count of a package
+ * @param[in] user_data                                The user data passed from the callback registration function
  *
- * @returns: true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
  *
  * @see        privacy_guard_client_foreach_log_count_by_package_id()
  */
 typedef bool (*privacy_guard_client_privacy_count_of_package_cb) (const char *package_id, const int count, void *user_data);
 
 /**
+ * @brief      Called when the reply of the leak logs request is delivered.
+ * @since      tizen 3.0
+ *
+ * @param[in] id                                       Leak log ID
+ * @param[in] time_stamp                       Leak time (Unix time)
+ * @param[in] action                           Action taken
+ * @param[in] app_name                         Application name
+ * @param[in] app_icon                         Application icon
+ * @param[in] destination                      Host destination of the leak
+ * @param[in] user_data                                The user data passed from the callback registration function
+ *
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ */
+typedef bool (*privacy_guard_client_leak_logs_cb) (int id, time_t time_stamp, PgDlpAction action, const char *app_name, const char *app_icon, const char *destination, void *user_data);
+
+/**
+ * @brief      Called when the reply of the leak logs application count is delivered.
+ * @since      tizen 3.0
+ *
+ * @param[in] app_name                         Application name
+ * @param[in] first_time_stamp         First leak time (Unix time)
+ * @param[in] last_time_stamp          Last leak time (Unix time)
+ * @param[in] app_icon                         Application icon
+ * @param[in] leak_count                       Number of leaks made by the application
+ * @param[in] user_data                                The user data passed from the callback registration function
+ *
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ */
+typedef bool (*privacy_guard_client_app_leak_count_cb) (const char *app_name, time_t first_time_stamp, time_t last_time_stamp, const char *app_icon, int leak_count, void *user_data);
+
+/**
+ * @brief      Called when the reply of the leak logs category count is delivered.
+ * @since      tizen 3.0
+ *
+ * @param[in] category                         Pattern category
+ * @param[in] first_time_stamp         First leak time (Unix time)
+ * @param[in] last_time_stamp          Last leak time (Unix time)
+ * @param[in] leak_count                       Number of leaks made by the application
+ * @param[in] user_data                                The user data passed from the callback registration function
+ *
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ */
+typedef bool (*privacy_guard_client_category_leak_count_cb) (const char *category, time_t first_time_stamp, time_t last_time_stamp, int leak_count, void *user_data);
+
+/**
+ * @brief      Called when the reply of the dlp rule request is delivered.
+ * @since      tizen 3.0
+ *
+ * @param[in] id                                       The rule ID
+ * @param[in] action                           Action to be taken with this rule
+ * @param[in] pattern_id                       Rule pattern ID
+ * @param[in] name                                     Rule name
+ * @param[in] description                      Rule description
+ * @param[in] application_id           Application ID for over rule
+ * @param[in] leaks_count                      Number of leaks the pattern has matched
+ * @param[in] user_data                                The user data passed from the callback registration function
+ *
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ */
+typedef bool (*privacy_guard_client_dlp_rule_cb) (int id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id, int leaks_count, void *user_data);
+
+/**
+ * @brief      Called when the reply of the pattern request is delivered.
+ * @since      tizen 3.0
+ *
+ * @param[in] id                                       The pattern ID
+ * @param[in] pattern                          The pattern to be matched (string or regex)
+ * @param[in] name                                     Pattern name
+ * @param[in] description                      Pattern description
+ * @param[in] type                                     The pattern type (string or regex)
+ * @param[in] category                         The pattern category
+ * @param[in] undeletable                      True if the pattern cannot be deleted (may still be edited, creating a second rule).
+ * @param[in] leaks_count                      Number of leaks the pattern has matched
+ * @param[in] user_data                                The user data passed from the callback registration function
+ *
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ */
+typedef bool (*privacy_guard_client_dlp_pattern_cb) (int id, const char *pattern, const char *name, const char *description, PgDlpPatternType type, const char *category, bool undeletable, int leaks_count, void *user_data);
+
+/**
+ * @brief      Called when the reply of the category request is delivered.
+ * @since      tizen 4.0
+ *
+ * @param[in] category                         The category name
+ * @param[in] user_data                                The user data passed from the callback registration function
+ *
+ * @return true to continue with the next iteration of the loop, otherwise return false to break out of the loop
+ */
+typedef bool (*privacy_guard_client_dlp_category_cb) (const char *category, void *user_data);
+
+/**
  * @fn int privacy_guard_client_foreach_total_privacy_count_of_package(const int user_id, const int start_date, const int end_date, privacy_guard_client_privacy_count_of_package_cb callback, void *user_data)
  * @brief get total privacy access count for each packcage
- * @param[in] user_id          user ID
- * @param[in] start_date       start date to be monitored (Unix time)
- * @param[in] end_date         end date to be monitored (Unix time)
- * @param[in] callback                 The callback function to invoke
- * @param[in] user_data        The user data to be passed to the callback function
+ * @param[in] user_id                          User ID
+ * @param[in] start_date                       Start date to be monitored (Unix time)
+ * @param[in] end_date                         End date to be monitored (Unix time)
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
  */
 EXTERN_API int privacy_guard_client_foreach_total_privacy_count_of_package(const int user_id, const time_t start_date, const time_t end_date, privacy_guard_client_privacy_count_of_package_cb callback, void *user_data);
 
 /**
  * @fn int privacy_guard_client_foreach_total_privacy_count_of_privacy(const int user_id, const int start_date, const int end_date, privacy_guard_client_privacy_count_cb callback, void *user_data)
  * @brief get total privacy access count for each privacy
- * @param[in] user_id          user ID
- * @param[in] start_date       start date to be monitored (Unix time)
- * @param[in] end_date         end date to be monitored (Unix time)
- * @param[in] callback                 The callback function to invoke
- * @param[in] user_data        The user data to be passed to the callback function
+ * @param[in] user_id                          User ID
+ * @param[in] start_date                       Start date to be monitored (Unix time)
+ * @param[in] end_date                         End date to be monitored (Unix time)
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
  */
 EXTERN_API int privacy_guard_client_foreach_total_privacy_count_of_privacy(const int user_id, const time_t start_date, const time_t end_date, privacy_guard_client_privacy_count_cb callback, void *user_data);
 
 /**
  * @fn int privacy_guard_client_foreach_privacy_count_by_privacy_id(const int user_id, const int start_date, const int end_date, const char* privacy_id, privacy_guard_client_privacy_count_of_package_cb callback, void *user_data)
  * @brief get privacy access count by specified privacy
- * @param[in] user_id          user ID
- * @param[in] start_date       start date to be monitored (Unix time)
- * @param[in] end_date         end date to be monitored (Unix time)
- * @param[in] privacy_id       privacy ID
- * @param[in] callback                 The callback function to invoke
- * @param[in] user_data        The user data to be passed to the callback function
+ * @param[in] user_id                          User ID
+ * @param[in] start_date                       Start date to be monitored (Unix time)
+ * @param[in] end_date                         End date to be monitored (Unix time)
+ * @param[in] privacy_id                       Privacy ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
  */
 EXTERN_API int privacy_guard_client_foreach_privacy_count_by_privacy_id(const int user_id, const time_t start_date, const time_t end_date, const char *privacy_id, privacy_guard_client_privacy_count_of_package_cb callback, void *user_data);
 
 /**
  * @fn int privacy_guard_client_foreach_privacy_count_by_package_id(const int user_id, const int start_date, const int end_date, const char *package_id, privacy_guard_client_privacy_count_cb callback, void *user_data)
  * @brief get privacy access count by specified package
- * @param[in] user_id          user ID
- * @param[in] start_date       start date to be monitored (Unix time)
- * @param[in] end_date end date to be monitored (Unix time)
- * @param[in] package_id       package ID
- * @param[in] callback                 The callback function to invoke
- * @param[in] user_data        The user data to be passed to the callback function
+ * @param[in] user_id                          User ID
+ * @param[in] start_date                       Start date to be monitored (Unix time)
+ * @param[in] end_date                         End date to be monitored (Unix time)
+ * @param[in] package_id                       Package ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
  */
 EXTERN_API int privacy_guard_client_foreach_privacy_count_by_package_id(const int user_id, const time_t start_date, const time_t end_date, const char *package_id, privacy_guard_client_privacy_count_cb callback, void *user_data);
 
 /**
  * @fn int privacy_guard_client_update_monitor_policy(const int user_id, const char *package_id, const char *privacy_id, int monitor_policy)
  * @brief update monitor policy
- * @param[in] user_id                  The user ID
- * @param[in] package_id               The package ID
- * @param[in] privacy_id               The privacy ID
- * @param[in] monitor_policy   monitor policy (0 or 1) to be set
+ * @param[in] user_id                          The user ID
+ * @param[in] package_id                       The package ID
+ * @param[in] privacy_id                       The privacy ID
+ * @param[in] monitor_policy           Monitor policy (0 or 1) to be set
  */
 EXTERN_API int privacy_guard_client_update_monitor_policy(const int user_id, const char *package_id, const char *privacy_id, const int monitor_policy);
 
@@ -159,18 +250,19 @@ EXTERN_API int privacy_guard_client_update_monitor_policy(const int user_id, con
  * @fn int privacy_guard_client_foreach_monitor_policy_by_package_id(const int user_id, const char *package_id,
                privacy_guard_client_monitor_policy_cb callback, void *user_data)
  * @brief get monitor policy by package
- * @param[in] user_id          The user ID
- * @param[in] package_id       The package ID
- * @param[in] callback The     callback function to invoke
+ * @param[in] user_id                          The user ID
+ * @param[in] package_id                       The package ID
+ * @param[in] callback                         The callback function to invoke
  */
 EXTERN_API int privacy_guard_client_foreach_monitor_policy_by_package_id(const int user_id, const char *package_id, privacy_guard_client_monitor_policy_cb callback, void *user_data);
 
 /**
  * @fn int privacy_guard_client_check_privacy_package(const int user_id, const char *package_id, bool *is_privacy_package)
  * @brief check whether the package use a privacy or not
- * @param[in] user_id                          The user ID
- * @param[in] package_id                       The package ID
- * @param[out] is_privacy_package      The result of privacy package or not
+ * @param[in] user_id                          The user ID
+ * @param[in] package_id                       The package ID
+ * @param[out] is_privacy_package      The result of privacy package or not
+ *
  * @return the result of operation (ERRORCODE : success, ....)
  */
 EXTERN_API int privacy_guard_client_check_privacy_package(const int user_id, const char *package_id, bool *is_privacy_package);
@@ -178,22 +270,236 @@ EXTERN_API int privacy_guard_client_check_privacy_package(const int user_id, con
 /**
  * @fn int privacy_guard_client_foreach_privacy_package_id(const int user_id, privacy_guard_client_package_id_cb callback, void *user_data)
  * @brief get package using one or more privacy
- * @param[in] user_id          The user ID
- * @param[in] callback                 The callback function to invoke
- * @param[in] user_data        The user data to be passed to the callback function
+ * @param[in] user_id                          The user ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
  */
 EXTERN_API int privacy_guard_client_foreach_package_id_using_privacy(const int user_id, privacy_guard_client_package_id_cb callback, void *user_data);
 
 /**
  * @fn int privacy_guard_client_foreach_package_info_by_privacy_id(const int user_id, const char *privacy_id, privacy_guard_client_package_id_cb callback, void *user_data)
  * @brief get package info (package_id, count, monitor_enable) using specified privacy
- * @param[in] user_id          The user ID
- * @param[in] privacy_id       The privacy ID
- * @param[in] callback                 The callback function to invoke
- * @param[in] user_data The user data to be passed to the callback function
+ * @param[in] user_id                          The user ID
+ * @param[in] privacy_id                       The privacy ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
  */
 EXTERN_API int privacy_guard_client_foreach_package_info_by_privacy_id(const int user_id, const char *privacy_id, privacy_guard_client_package_info_cb callback, void *user_data);
 
+/**
+ * @fn int privacy_guard_client_foreach_leak_logs(const int user_id, privacy_guard_client_leak_logs_cb callback, void *user_data)
+ * @brief get all logs from leaked packet
+ * @param[in] user_id                          The user ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_leak_logs(const int user_id, privacy_guard_client_leak_logs_cb callback, void *user_data);
+
+/**
+ * @fn int privacy_guard_client_foreach_leak_logs_by_app_name(const int user_id, const char *application_name, privacy_guard_client_leak_logs_cb callback, void *user_data)
+ * @brief get all logs from leaked packet made by given application
+ * @param[in] user_id                          The user ID
+ * @param[in] application_name         The application name
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_leak_logs_by_app_name(const int user_id, const char *application_name, privacy_guard_client_leak_logs_cb callback, void *user_data);
+
+/**
+ * @fn int privacy_guard_client_foreach_leak_logs_by_category(const int user_id, const char *category, privacy_guard_client_leak_logs_cb callback, void *user_data)
+ * @brief get all logs from leaked packet made by given application
+ * @param[in] user_id                          The user ID
+ * @param[in] category                         The category of the rule
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_leak_logs_by_category(const int user_id, const char *category, privacy_guard_client_leak_logs_cb callback, void *user_data);
+
+/**
+ * @fn int privacy_guard_client_foreach_app_leak_count(const int user_id, privacy_guard_client_app_leak_count_cb callback, void *user_data)
+ * @brief get the total leak count of each application detected by DLP
+ * @param[in] user_id                          The user ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_app_leak_count(const int user_id, privacy_guard_client_app_leak_count_cb callback, void *user_data);
+
+/**
+ * @fn int privacy_guard_client_foreach_category_leak_count(const int user_id, privacy_guard_client_category_leak_count_cb callback, void *user_data)
+ * @brief get the total leak count of each pattern categories detected by DLP
+ * @param[in] user_id                          The user ID
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_category_leak_count(const int user_id, privacy_guard_client_category_leak_count_cb callback, void *user_data);
+
+/**
+ * @fn int privacy_guard_client_get_leak_logs(const int user_id, time_t start, time_t end, privacy_guard_client_leak_logs_cb callback, void *user_data)
+ * @brief get logs from leaked packet by timestamp range
+ * @param[in] user_id                          The user ID
+ * @param[in] start                                    Start of timestamp range.
+ * @param[in] end                                      End of timestamp range. Must be greater than or equal to start.
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_get_leak_logs(const int user_id, const time_t start, const time_t end, privacy_guard_client_leak_logs_cb callback, void *user_data);
+
+/**
+ * @fn int privacy_guard_client_get_leak_log_detail(int user_id, int log_id, leak_log_get_detail_data_s *log_detail)
+ * @brief get all logs from leaked packet
+ * @param[in] user_id                          The user ID
+ * @param[in] log_id                           The log ID
+ * @param[in] log_detail                       Structure with all leak log details
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_get_leak_log_detail(int user_id, int log_id, leak_log_get_detail_data_s *log_detail);
+
+/**
+ * @fn int privacy_guard_client_purge_leak_logs(const int user_id)
+ * @brief purge all logs from leaked database
+ * @param[in] user_id                          The user ID
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_purge_leak_logs(const int user_id);
+
+/**
+ * @fn int privacy_guard_client_purge_leak_logs_by_logid(const int user_id, const int[] log_id, const size_t log_id_size)
+ * @brief purge all logs from leaked database by logid
+ * @param[in] user_id                          The user ID
+ * @param[in] log_id                           The log IDs to be purged
+ * @param[in] log_id_size                      Number of elements in the log_id array
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_purge_leak_logs_by_logid(const int log_id[], const size_t log_id_size);
+
+/**
+ * @fn int privacy_guard_client_set_dlp_profile(const int user_id, const dlp_profile_s *profile)
+ * @brief set user DLP profile
+ * @param[in] user_id                          The user ID
+ * @param[in] profile                          Profile structure
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_set_dlp_profile(const int user_id, const dlp_profile_s *profile);
+
+/**
+ * @fn int privacy_guard_client_get_dlp_profile(const int user_id, dlp_profile_s *profile)
+ * @brief get user DLP profile
+ * @param[in] user_id                          The user ID
+ * @param[out] profile                         Profile structure
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_get_dlp_profile(const int user_id, dlp_profile_s *profile);
+
+/**
+ * @fn int privacy_guard_client_add_dlp_custom_rule(int user_id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id);
+ * @brief add a custom DLP rule for user user_id
+ * @param[in] user_id                          The user ID
+ * @param[in] action                           Action to be take with this rule
+ * @param[in] pattern_id                       Rule pattern ID
+ * @param[in] name                                     Rule name
+ * @param[in] description                      Rule description
+ * @param[in] application_id           Application ID for over rule
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ * @callgraph
+ */
+EXTERN_API int privacy_guard_client_add_dlp_custom_rule(int user_id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id);
+
+/**
+ * @fn int privacy_guard_client_delete_dlp_custom_rule(int rule_id)
+ * @brief delete a custom DLP rule
+ * @param[in] rule_id                          The rule ID to be deleted
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_delete_dlp_custom_rule(int rule_id);
+
+/**
+ * @brief update custom rule rule_id with new values
+ * @param[in] rule_id                          The existing rule ID
+ * @param[in] action                           The new action to be taken (allow, deny, sanitize)
+ * @param[in] pattern_id                       The new pattern ID
+ * @param[in] name                             The new rule name
+ * @param[in] description                      The new rule description
+ * @param[in] application_id                   The new app id
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_update_dlp_custom_rule(int rule_id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id);
+
+/**
+ * @brief get all dlp rules from user user_id, profile profile
+ * @param[in] user_id                          The user ID
+ * @param[in] profile                          The profile
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_dlp_rules(int user_id, PgDlpProfile profile, privacy_guard_client_dlp_rule_cb callback, void *user_data);
+
+/**
+ * @brief add a new DLP pattern
+ * @param[in] name             Pattern name
+ * @param[in] description      Pattern description
+ * @param[in] category         Pattern category
+ * @param[in] pattern          The pattern to match
+ * @param[in] type             Pattern type (STRING, REGEX)
+ * @return the result of operation (ERRORCODE : success, ....)
+ * @callgraph
+ */
+EXTERN_API int privacy_guard_client_add_dlp_pattern(const char *name, const char *description, const char *category, const char *pattern, PgDlpPatternType type);
+
+/**
+ * @brief delete the specified pattern from the user's view (marked as DELETED, later purged)
+ * @param[in] pattern_id                       The pattern to be removed
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_delete_dlp_pattern(int pattern_id);
+
+/**
+ * @fn int privacy_guard_client_foreach_dlp_patterns(privacy_guard_client_dlp_pattern_cb callback, void *user_data)
+ * @brief get all patterns
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_dlp_patterns(privacy_guard_client_dlp_pattern_cb callback, void *user_data);
+
+/**
+ * @brief get all categories
+ * @param[in] callback                         The callback function to invoke
+ * @param[in] user_data                                The user data to be passed to the callback function
+ *
+ * @return the result of operation (ERRORCODE : success, ....)
+ */
+EXTERN_API int privacy_guard_client_foreach_dlp_categories(privacy_guard_client_dlp_category_cb callback, void *user_data);
+
+/**
+ * @brief check if a pattern is valid or not
+ * @param[in] pattern_type the pattern's type (string match or regular expression)
+ * @param[in] pattern the pattern to validate
+ *
+ * @return if the pattern is valid, return PRIV_GUARD_ERROR_SUCCESS; an error code otherwise
+ */
+EXTERN_API int privacy_guard_client_validate_pattern(PgDlpPatternType pattern_type, const char* pattern);
+
 #ifdef __cplusplus
 }
 #endif
old mode 100755 (executable)
new mode 100644 (file)
index 0a95ce7..faab28c
  * limitations under the License.
  */
 
+/**
+ * @file       privacy_guard_client_types.h
+ */
+
 #ifndef _PRIVACY_GUARD_CLIENT_TYPES_H_
 #define _PRIVACY_GUARD_CLIENT_TYPES_H_
 
 #include <time.h>
 #include <stdbool.h>
 
+#define LEN_APPLICATION_ID 128
+#define LEN_APPLICATION_NAME 128
+#define LEN_APPLICATION_VERSION 32
+#define LEN_APPLICATION_ICON 128
+#define LEN_PACKAGE_ID 128
+#define LEN_DESTINATION 128
+#define LEN_DESCRIPTION 128
+#define MAX_CATEGORIES 16
+#define LEN_CATEGORY 32
+#define LEN_NAME 128
+#define LEN_PATTERN 256
+#define MIN_PATTERN_LEN 5
+
+#define PRE_MATCH_BYTES 32    ///< number of bytes of packet to show before the match
+#define POST_MATCH_BYTES 32   ///< number of bytes of packet to show after the match
+
+#define LEN_RAW_PACKET (PRE_MATCH_BYTES + LEN_PATTERN + POST_MATCH_BYTES) ///< max length of packet fragment we can send to UI
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -47,6 +69,105 @@ enum {
        PRIV_GUARD_ERROR_UNKNOWN = -(0x99),
 };
 
+typedef enum {
+       PRIV_GUARD_DLP_PROFILE_BASIC,
+       PRIV_GUARD_DLP_PROFILE_ADVANCED,
+       PRIV_GUARD_DLP_PROFILE_CUSTOM
+} PgDlpProfile;
+
+typedef enum {
+       PRIV_GUARD_DLP_ACTION_ALLOW,
+       PRIV_GUARD_DLP_ACTION_DENY,
+       PRIV_GUARD_DLP_ACTION_SANITIZE
+} PgDlpAction;
+
+typedef enum {
+       PRIV_GUARD_DLP_RESULT_ALLOW,
+       PRIV_GUARD_DLP_RESULT_DENY
+} PgDlpResult;
+
+typedef enum {
+       PRIV_GUARD_DLP_PATTERN_STRING,
+       PRIV_GUARD_DLP_PATTERN_REGEX
+} PgDlpPatternType;
+
+typedef struct _dlp_profile_s {
+       int enabled;
+       PgDlpProfile profile;
+       int keep_log_days;
+} dlp_profile_s;
+
+typedef struct _leak_log_get_app_count_s {
+       char application_name[LEN_APPLICATION_NAME];
+       time_t first_time_stamp;
+       time_t last_time_stamp;
+       char application_icon[LEN_APPLICATION_ICON];
+       int leak_count;
+} leak_log_get_app_count_s;
+
+/*
+  @brief use a union here. When fetching from the server only the id is used.
+        The client will then fill in the text from its cached version of categories.
+        This saves some table lookups on the server end.
+*/
+typedef union {
+       int id;
+       char text[LEN_CATEGORY];
+} category_u;
+
+typedef struct _leak_log_get_category_count_s {
+       category_u category;
+       time_t first_time_stamp;
+       time_t last_time_stamp;
+       int leak_count;
+} leak_log_get_category_count_s;
+
+typedef struct _leak_log_get_detail_data_s {
+       PgDlpAction action;
+       char application_id[LEN_APPLICATION_ID];
+       char application_name[LEN_APPLICATION_NAME];
+       char application_version[LEN_APPLICATION_VERSION];
+       char application_icon[LEN_APPLICATION_ICON];
+       char package_id[LEN_PACKAGE_ID];
+       char destination[LEN_DESTINATION];
+       char pattern_name[LEN_NAME];
+       category_u category;
+       int pkt_len;
+       char raw_packet[LEN_RAW_PACKET];
+       int leak_offset;
+       int leak_len;
+} leak_log_get_detail_data_s;
+
+typedef struct _get_custom_rule_s {
+       int id;
+       PgDlpAction action;
+       int pattern_id;
+       char pattern[LEN_PATTERN];
+       char name[LEN_NAME];
+       char description[LEN_DESCRIPTION];
+       char application_id[LEN_APPLICATION_ID];
+       int leaks_count;
+} get_custom_rule_s;
+
+typedef struct _get_pattern_s {
+       int id;
+       char pattern[LEN_PATTERN];
+       char name[LEN_NAME];
+       char description[LEN_DESCRIPTION];
+       PgDlpPatternType type;
+       category_u category;
+       bool undeletable;
+       int leaks_count;
+} get_pattern_s;
+
+typedef struct _pattern_s {
+       char pattern[LEN_PATTERN];
+       char name[LEN_NAME];
+       char description[LEN_DESCRIPTION];
+       PgDlpPatternType type;
+       category_u category;
+} pattern_s;
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/privacy_guard_dlp.h b/include/privacy_guard_dlp.h
new file mode 100644 (file)
index 0000000..8c6785c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file       privacy_guard_dlp.h
+ * @brief      APIs for privacy-guard-dlp
+ */
+
+#ifndef _PRIVACY_GUARD_DLP_H_
+#define _PRIVACY_GUARD_DLP_H_
+
+#include "privacy_guard_client_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @fn void privacy_guard_dlp_init(void)
+ * @brief Initialize the DLP creating the Load Rules and Logging threads
+ * @callgraph
+ */
+EXTERN_API void privacy_guard_dlp_init(void);
+
+/**
+ * @fn PgDlpResult privacy_guard_dlp_check_leak(const char *hostname, char * const mem, size_t len)
+ * @brief Checks for information leak on a given request string
+ *
+ * @param[in] hostname                                 The hostname of the server to which the request will be sent
+ * @param[in] mem                                              Text that we are going to validate for info leak
+ * @param[in] len                                              Size of len in bytes
+ *
+ * @return  either PRIV_GUARD_DLP_RESULT_ALLOW or PRIV_GUARD_DLP_RESULT_DENY
+ * @callgraph
+ */
+EXTERN_API PgDlpResult privacy_guard_dlp_check_leak(const char *hostname, char * const mem, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_PRIVACY_GUARD_DLP_H_
index a24996a..a00d254 100755 (executable)
@@ -29,6 +29,13 @@ BuildRequires:       pkgconfig(cynara-monitor)
 BuildRequires:  pkgconfig(pkgmgr-installer)
 BuildRequires:  pkgconfig(security-manager)
 BuildRequires:  pkgconfig(aul)
+BuildRequires:  pkgconfig(libpcre)
+BuildRequires:  pkgconfig(capi-telephony)
+BuildRequires:  pkgconfig(capi-network-connection)
+BuildRequires:  pkgconfig(capi-network-wifi)
+BuildRequires:  pkgconfig(capi-location-manager)
+BuildRequires:  pkgconfig(contacts-service2)
+
 
 Requires(post):   /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
@@ -119,7 +126,9 @@ chsmack -a System %{TZ_SYS_DB}/.privacy_guard.db-journal
 %license  LICENSE.APLv2
 %manifest privacy-guard-server.manifest
 #%{TZ_SYS_DB}/.privacy_guard_privacylist.db
-%{_bindir}/*
+%{_bindir}/privacy-guard-server
+%{_bindir}/privacy_guard_create_clean_db.sh
+%{_bindir}/privacy_guard_db.sql
 %{_libdir}/systemd/system/*
 
 
@@ -140,4 +149,5 @@ chsmack -a System %{TZ_SYS_DB}/.privacy_guard.db-journal
 %{_libdir}/pkgconfig/privacy-guard-client.pc
 
 %files -n tc-privacy-guard
-%{_bindir}/tc-privacy-guard
\ No newline at end of file
+%{_bindir}/tc-privacy-guard
+%{_bindir}/tc-dlp
old mode 100755 (executable)
new mode 100644 (file)
index 961afaa..c22a68b
@@ -21,6 +21,111 @@ CREATE TABLE MainMonitorPolicy(
        PRIMARY KEY(USER_ID)
 CHECK(1) );
 
+CREATE TABLE DlpPatterns(
+       ID INTEGER PRIMARY KEY,
+       PATTERN TEXT not null,
+       NAME TEXT not null,
+       DESCRIPTION TEXT not null,
+       TYPE INTEGER not null,
+       CATEGORY_ID INTEGER not null,
+       STATE INTEGER default 1,
+       UNIQUE(PATTERN, TYPE)
+CHECK(1) );
+
+CREATE TABLE DlpRules(
+       ID INTEGER PRIMARY KEY AUTOINCREMENT,
+       USER_ID INTEGER,
+       PROFILE INTEGER not null,
+       ACTION INTEGER not null,
+       PATTERN_ID INTEGER,
+       NAME TEXT,
+       DESCRIPTION TEXT,
+       APP_ID TEXT default "",
+       UNIQUE(USER_ID, PROFILE, PATTERN_ID, APP_ID)
+CHECK(1) );
+
+CREATE TABLE DlpRequestLog(
+       ID INTEGER PRIMARY KEY AUTOINCREMENT,
+       USER_ID INTEGER not null,
+       TIME_STAMP INTEGER not null,
+       APP_NAME TEXT not null,
+       APP_ICON TEXT not null,
+       APP_ID TEXT not null,
+       APP_VERSION TEXT not null,
+       PKG_ID TEXT not null,
+       DESTINATION TEXT,
+       RAW_PACKET BLOB,
+CHECK(1) );
+
+CREATE TABLE DlpLeakLog(
+       ID INTEGER PRIMARY KEY AUTOINCREMENT,
+       REQUEST_ID INTEGER not null,
+       ACTION INTEGER not null,
+       PATTERN_ID INTEGER not null,
+       LEAK_OFFSET INTEGER not null,
+       LEAK_LEN INTEGER not null
+CHECK(1) );
+
+CREATE TABLE DlpProfile(
+       USER_ID INTEGER not null,
+       ENABLED INTEGER not null,
+       PROFILE INTEGER not null,
+       KEEP_LOG_DAYS INTEGER not null,
+       PRIMARY KEY(USER_ID)
+CHECK(1) );
+
+CREATE TABLE DlpCategories(
+       ID INTEGER PRIMARY KEY,
+       CATEGORY TEXT not null,
+       UNIQUE(CATEGORY)
+CHECK(1) );
+
+INSERT INTO DlpCategories(CATEGORY) VALUES("IMEI");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Full Name");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Birthday");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Home Address");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Phone Number");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Email");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Network Address");
+INSERT INTO DlpCategories(CATEGORY) VALUES("MAC");
+INSERT INTO DlpCategories(CATEGORY) VALUES("GPS");
+INSERT INTO DlpCategories(CATEGORY) VALUES("Other");
+
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##IMEI##", "Device IMEI", "Verify for the device IMEI", 0, 1, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##OWNER-FULL-NAME##", "Full Name", "Verify for full name", 0, 2, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##OWNER-BIRTHDAY##", "My Birthday", "Verify for birthday", 0, 3, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##OWNER-HOME-ADDRESS##", "Home Address", "Verify for home address", 0, 4, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##OWNER-PHONE-NUMBER##", "SIM/Me Phone Number", "Verify for the SIM/Me phone number", 0, 5, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##EMAIL##", "User Email", "Verify for the user email", 0, 6, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##IPV4##", "IP v4", "Verify for the device IP v4", 0, 7, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##MAC##", "MAC Address", "Verify for the device MAC address", 0, 8, 0);
+INSERT INTO DlpPatterns(PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE)
+       VALUES("##LOCATION##", "User Location", "Verify for the user GPS location", 1, 9, 0);
+
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(0, 0, 2);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(0, 0, 3);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(0, 0, 4);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(0, 0, 5);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(0, 0, 6);
+
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 1);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 2);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 3);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 4);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 5);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 6);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 7);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 8);
+INSERT INTO DlpRules(PROFILE, ACTION, PATTERN_ID) VALUES(1, 0, 9);
+
 COMMIT;
 BEGIN TRANSACTION; 
 CREATE TABLE DB_VERSION_0_1 (version INT); COMMIT;
index 149a828..1c88c2e 100755 (executable)
@@ -1,13 +1,18 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 PROJECT(privacy-guard)
 
+FIND_PACKAGE(Threads REQUIRED)
+
 SET(CMAKE_INSTALL_PREFIX /usr)
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(EXEC_PREFIX "\${prefix}")
 SET(INCLUDEDIR "\${prefix}/include")
 
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED dlog sqlite3 dbus-1 dbus-glib-1 db-util pkgmgr-info capi-system-info libtzplatform-config security-privilege-manager cynara-monitor security-manager aul)
+pkg_check_modules(pkgs REQUIRED dlog sqlite3 dbus-1 dbus-glib-1 db-util pkgmgr-info capi-system-info
+       libtzplatform-config security-privilege-manager cynara-monitor security-manager aul
+       capi-telephony capi-network-connection capi-network-wifi capi-location-manager
+       contacts-service2)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
@@ -49,12 +54,15 @@ SET(PRIVACY_GUARD_SERVER_SOURCES
        ${common_src_dir}/SocketConnection.cpp
        ${common_src_dir}/SocketStream.cpp
        ${common_src_dir}/PrivacyIdInfo.cpp
+       ${common_src_dir}/pg_strlcpy.c
        ${server_src_dir}/PrivacyGuardDb.cpp
        ${server_src_dir}/main.cpp
        ${server_src_dir}/SocketService.cpp
        ${server_src_dir}/CynaraService.cpp
        ${server_src_dir}/PrivacyGuardDaemon.cpp
+       ${server_src_dir}/DlpRuleChangeNotification.cpp
        ${server_src_dir}/service/PrivacyInfoService.cpp
+       ${server_src_dir}/service/DlpPrivacyInfoData.cpp
        )
 SET(PRIVACY_GUARD_SERVER_LDFLAGS " -module -avoid-version ")
 SET(PRIVACY_GUARD_SERVER_CFLAGS  " ${CFLAGS} -fPIE ")
index f9c6a6b..90345b8 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       CynaraService.h
+ */
+
 #ifndef _CYNARA_SERVICE_H_
 #define _CYNARA_SERVICE_H_
 
@@ -32,7 +36,7 @@ private:
        pthread_t m_cynaraThread;
 
 private:
-       static void* getEntriesThread(void* );
+       static void* getEntriesThread(void*);
 //     static void* flushThread(void* );
 public:
        CynaraService(void);
@@ -41,7 +45,7 @@ public:
        int start(void);
        int stop(void);
        int shutdown(void);
-       static int updateDb(cynara_monitor_entry** monitor_entries);
+       static int updateDb(cynara_monitor_entry **monitor_entries);
 };
 
-#endif //_CYNARA_SERVICE_H_
\ No newline at end of file
+#endif //_CYNARA_SERVICE_H_
diff --git a/server/inc/DlpPrivacyInfoData.h b/server/inc/DlpPrivacyInfoData.h
new file mode 100644 (file)
index 0000000..2f6eb48
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpPrivacyInfoData.h
+ */
+
+#ifndef _DLP_PRIVACYINFODATA_H_
+#define _DLP_PRIVACYINFODATA_H_
+
+#include <locale.h>
+#include <vconf.h>
+#include <arpa/inet.h>
+#include <list>
+#include <set>
+#include <string>
+#include <map>
+#include <mutex>
+#include <telephony.h>
+#include <net_connection.h>
+#include <locations.h>
+#include "PrivacyGuardTypes.h"
+
+#define LEN_MAC_ADDRESS   18
+#define IMEI_TEMPLATE     "##IMEI##"
+#define IPV4_TEMPLATE     "##IPV4##"
+#define EMAIL_TEMPLATE    "##EMAIL##"
+#define MAC_TEMPLATE      "##MAC##"
+#define LOCATION_TEMPLATE "##LOCATION##"
+#define OWNER_FULLNAME_TEMPLATE "##OWNER-FULL-NAME##"
+#define OWNER_PHONENO_TEMPLATE "##OWNER-PHONE-NUMBER##"
+#define OWNER_HOME_ADDRESS_TEMPLATE "##OWNER-HOME-ADDRESS##"
+#define OWNER_BIRTHDAY_TEMPLATE "##OWNER-BIRTHDAY##"
+
+class DlpPrivacyInfoData
+{
+public:
+       DlpPrivacyInfoData();
+
+       void replaceRuleTemplates(const int userId, std::list<current_rules_s> *rulesIn, std::list<current_rules_s> *rulesOut);
+       static DlpPrivacyInfoData *getInstance();
+       bool start(void);
+       void stop(void);
+
+private:
+       static void networkAddressChanged(const char *ipv4, const char *ipv6, void *user_data);
+       static void telephonySIMStatusChanged(telephony_h handle, telephony_noti_e noti_id, void *data, void *user_data);
+       static void myProfileChanged(const char *view_uri, void *user_data);
+       static void positionUpdated(double latitude, double longitude, double altitude, time_t timestamp, void *user_data);
+       static void contactChanged(const char *view_uri, void *user_data);
+       static void localeChanged(keynode_t *key, void *user_data);
+       void loadMyProfile(void);
+       void loadInfo(const int userId);
+       static void *startLocation(void *_this);
+
+       connection_h m_connection;
+       std::list<char *> m_imei_list;
+       std::set<std::string> m_sim_phoneno_list;
+       std::set<std::string> m_owner_phoneno_list;
+       std::list<std::string> m_location_list;
+       std::set<std::string> m_email_list;
+       std::set<std::string> m_owner_email_list;
+       double m_last_latitude;
+       double m_last_longitude;
+       char m_mac[LEN_MAC_ADDRESS] = { 0 };
+       std::string m_ipv4;
+       std::string m_owner_name;
+       int m_owner_ibirthday;
+       std::string m_owner_birthday;
+       std::set<std::string> m_owner_address_list;
+       telephony_handle_list_s m_handle_list = { 0 };
+       location_manager_h m_locmgr;
+       bool m_myprofile_watch;
+       std::mutex m_infoMutex;
+
+       static std::mutex m_singletonMutex;
+       static DlpPrivacyInfoData *m_pInstance;
+};
+
+#endif // _DLP_PRIVACYINFODATA_H_
diff --git a/server/inc/DlpRuleChangeNotification.h b/server/inc/DlpRuleChangeNotification.h
new file mode 100644 (file)
index 0000000..0e284d0
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpRuleChangeNotification.h
+ */
+
+#ifndef _DLP_RULECHANGENOTIFICATION_H_
+#define _DLP_RULECHANGENOTIFICATION_H_
+
+#include <list>
+#include <mutex>
+#include "privacy_guard_client_types.h"
+#include "PrivacyGuardTypes.h"
+
+class DlpRuleChangeNotification
+{
+private:
+       static std::mutex m_singletonMutex;
+       static DlpRuleChangeNotification* m_pInstance;
+       std::list<privacy_semaphore_s> m_semaphore_list;
+       std::mutex m_semaphore_mutex;
+
+public:
+       static DlpRuleChangeNotification *getInstance(void);
+       int addDlpClient(int pId);
+       int notifyDlpClients(void);
+};
+
+#endif // _DLP_RULECHANGENOTIFICATION_H_
index 33c16d5..15c2d52 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       ICommonDb.h
+ */
+
 #ifndef _ICOMMONDB_H_
 #define _ICOMMONDB_H_
 
@@ -37,7 +41,6 @@ public:
        virtual ~ICommonDb() {}
 
        virtual void openSqliteDB(void) = 0;
-
 };
 
 #endif // _ICOMMONDB_H_
index be0d1ce..b33dec8 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyGuardDaemon.h
+ */
+
 #ifndef _PRIVACYGUARDDAEMON_H_
 #define _PRIVACYGUARDDAEMON_H_
 
index 977b731..045630c 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyGuardDb.h
+ */
+
 #ifndef _PRIVACY_GUARD_DB_H_
 #define _PRIVACY_GUARD_DB_H_
 
 #include <string>
 #include <memory>
 #include <list>
+#include <set>
 #include <mutex>
 #include <glib.h>
 #include "ICommonDb.h"
 #include "privacy_guard_client_types.h"
 #include "PrivacyGuardTypes.h"
 
-class PrivacyGuardDb : public ICommonDb
+typedef enum {
+       PRIV_GUARD_DLP_PATTERN_STATE_UNDELETABLE = 0, ///< for built-in patterns
+       PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE, ///< default for newly created patterns (can go to state in_use or state deleted)
+       PRIV_GUARD_DLP_PATTERN_STATE_IN_USE, ///< pattern is attached to one or more rules, user cannot delete it (system will move to deleted when no longer used)
+       PRIV_GUARD_DLP_PATTERN_STATE_DELETED ///< pattern was deleted (can go to IN_USE if user re-creates it), will be deleted when no leaks point to it
+} PgDlpPatternState;
+
+class PrivacyGuardDb:public ICommonDb
 {
 private:
        static std::mutex m_singletonMutex;
@@ -39,6 +51,8 @@ private:
        PrivacyGuardDb(void);
        void initialize(void);
        int prepareGlobalPackagePolicy(const int userId);
+       int markUnusedPatterns(int ruleId, int newPatternId, sqlite3_stmt* update_stmt);
+       int purgeUnusedDeletedPatterns(void);
        ~PrivacyGuardDb(void);
 
 public:
@@ -48,7 +62,7 @@ public:
 
        int PgAddPrivacyAccessLog(const int userId, const std::string packageId, const std::string privacyId, const time_t timestamp);
 
-       int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::list < std::string > privacyList, bool monitorPolicy);
+       int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::list<std::string> privacyList, bool monitorPolicy);
 
        int PgAddMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, bool monitorPolicy);
 
@@ -62,23 +76,23 @@ public:
 
        int PgDeleteMonitorPolicyByPackageId(const std::string packageId);
 
-       int PgForeachTotalPrivacyCountOfPackage(const int userId, const int startDate, const int endDate, std::list < std::pair < std::string, int > >& packageInfoList);
+       int PgForeachTotalPrivacyCountOfPackage(const int userId, const int startDate, const int endDate, std::list< std::pair <std::string, int> > &packageInfoList);
 
-       int PgForeachTotalPrivacyCountOfPrivacy(const int userId, const int startDate, const int endDate, std::list < std::pair < std::string, int > >& privacyInfoList);
+       int PgForeachTotalPrivacyCountOfPrivacy(const int userId, const int startDate, const int endDate, std::list< std::pair <std::string, int> > &privacyInfoList);
 
-       int PgForeachPrivacyCountByPrivacyId(const int userId, const int startDate, const int endDate, const std::string privacyId, std::list < std::pair < std::string, int > >& packageInfoList);
+       int PgForeachPrivacyCountByPrivacyId(const int userId, const int startDate, const int endDate, const std::string privacyId, std::list<std::pair<std::string, int>> &packageInfoList);
 
-       int PgForeachPrivacyCountByPackageId(const int userId, const int startDate, const int endDate, const std::string packageId, std::list < std::pair < std::string, int > >& privacyInfoList);
+       int PgForeachPrivacyCountByPackageId(const int userId, const int startDate, const int endDate, const std::string packageId, std::list<std::pair<std::string, int>> &privacyInfoList);
 
        int PgGetMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, int &monitorPolicy);
 
-       int PgGetAllMonitorPolicy(std::list < std::pair < std::string, int > >& monitorPolicyList);
+       int PgGetAllMonitorPolicy(std::list<std::pair<std::string, int>> &monitorPolicyList);
 
-       int PgForeachMonitorPolicyByPackageId(const int userId, const std::string packageId, std::list <privacy_data_s>privacyInfoList);
+       int PgForeachMonitorPolicyByPackageId(const int userId, const std::string packageId, std::list <privacy_data_s> &privacyInfoList);
 
-       int PgForeachPackageIdUsingPrivacy(const int userId, std::list < std::string > & packageList);
+       int PgForeachPackageIdUsingPrivacy(const int userId, std::list<std::string> &packageList);
 
-       int PgForeachPackageInfoByPrivacyId(const int userId, const std::string privacyId, std::list < package_data_s > &packageList);
+       int PgForeachPackageInfoByPrivacyId(const int userId, const std::string privacyId, std::list<package_data_s> &packageList);
 
        int PgUpdateMonitorPolicy(const int userId, const std::string packageId, const std::string privacyId, const int monitorPolicy);
 
@@ -89,7 +103,52 @@ public:
        int PgGetMainMonitorPolicy(const int userId, int &mainMonitorPolicy);
 
        int PgDeleteMainMonitorPolicyByUserId(const int userId);
+
+       // DLP features
+       int PgAddLeakLog(leak_log_insert_common_data_s &data, const std::list<leak_log_insert_data_s> &logList);
+
+       int PgForeachLeakLogs(const int userId, const char *appName, int category_id, std::list<leak_log_get_data_s> &logList);
+
+       int PgForeachAppLeakCount(const int userId, std::list<leak_log_get_app_count_s> &logList);
+
+       int PgForeachCategoryLeakCount(const int userId, std::list<leak_log_get_category_count_s> &logList);
+
+       int PgForeachLeakLogsByTimestamp(const int userId, const time_t start, const time_t end, std::list<leak_log_get_data_s> &logList);
+
+       int PgGetLeakLogDetails(int userId, int logId, leak_log_get_detail_data_s &logDetail);
+
+       int PgPurgeLeakLogs(const int userId);
+
+       int PgPurgeLeakLogsByDays(const int userId, int days);
+
+       int PgPurgeLeakLogsByLogId(const std::list<int> &logId);
+
+       int PgSetDlpProfile(const int userId, const dlp_profile_s &profile);
+
+       int PgGetDlpProfile(const int userId, dlp_profile_s &profile);
+
+       int PgGetDlpCurrentRules(const int userId, const char *AppId, const int pId, std::list<current_rules_s> &rules);
+
+       int PgGetAccountEmails(const int userId, std::set<std::string> &emails);
+
+       int PgAddDlpCustomRule(int userId, const custom_rule_s &rule);
+
+       int PgUpdateDlpCustomRule(const custom_rule_s &rule);
+
+       int PgDeleteDlpCustomRule(int ruleId);
+
+       int PgForeachDlpCustomRules(int userId, std::list<get_custom_rule_s> &rules);
+
+       int PgForeachDlpRules(int userId, int profile, std::list<get_custom_rule_s> &rules);
+
+       int PgAddDlpPattern(const pattern_s &pattern);
+
+       int PgDeleteDlpPattern(int pattern_id);
+
+       int PgForeachDlpPatterns(std::list<get_pattern_s> &patterns);
+
+       int PgGetDlpCategories(std::list<std::string> &categories);
 };
 
 
-#endif // _PRIVACY_GUARD_DB_H_
\ No newline at end of file
+#endif // _PRIVACY_GUARD_DB_H_
index e80d3ab..55f36a1 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyInfoService.h
+ */
+
 #ifndef _PRIVACYINFOSERVICE_H_
 #define _PRIVACYINFOSERVICE_H_
 
@@ -28,45 +32,88 @@ private:
        }
 
 public:
-       static void registerCallbacks(SocketService* pSocketService)
-       {
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddPrivacyAccessLog"), PgAddPrivacyAccessLog);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddMonitorPolicy"), PgAddMonitorPolicy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteLogsByPackageId"), PgDeleteLogsByPackageId);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteMonitorPolicyByPackageId"), PgDeleteMonitorPolicyByPackageId);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachTotalPrivacyCountOfPackage"), PgForeachTotalPrivacyCountOfPackage);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachTotalPrivacyCountOfPrivacy"), PgForeachTotalPrivacyCountOfPrivacy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPrivacyCountByPrivacyId"), PgForeachPrivacyCountByPrivacyId);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPrivacyCountByPackageId"), PgForeachPrivacyCountByPackageId);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPackageIdUsingPrivacy"), PgForeachPackageIdUsingPrivacy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPackageInfoByPrivacyId"), PgForeachPackageInfoByPrivacyId);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachMonitorPolicyByPackageId"), PgForeachMonitorPolicyByPackageId);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetMonitorPolicy"), PgGetMonitorPolicy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetAllMonitorPolicy"), PgGetAllMonitorPolicy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgCheckPrivacyPackage"), PgCheckPrivacyPackage);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgUpdateMonitorPolicy"), PgUpdateMonitorPolicy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetMainMonitorPolicy"), PgGetMainMonitorPolicy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgUpdateMainMonitorPolicy"), PgUpdateMainMonitorPolicy);
-               pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteAllLogs"), PgDeleteAllLogs);
-       }
+static void registerCallbacks(SocketService* pSocketService) {
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddPrivacyAccessLog"), PgAddPrivacyAccessLog);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddMonitorPolicy"), PgAddMonitorPolicy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteLogsByPackageId"), PgDeleteLogsByPackageId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteMonitorPolicyByPackageId"), PgDeleteMonitorPolicyByPackageId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachTotalPrivacyCountOfPackage"), PgForeachTotalPrivacyCountOfPackage);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachTotalPrivacyCountOfPrivacy"), PgForeachTotalPrivacyCountOfPrivacy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPrivacyCountByPrivacyId"), PgForeachPrivacyCountByPrivacyId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPrivacyCountByPackageId"), PgForeachPrivacyCountByPackageId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPackageIdUsingPrivacy"), PgForeachPackageIdUsingPrivacy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachPackageInfoByPrivacyId"), PgForeachPackageInfoByPrivacyId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachMonitorPolicyByPackageId"), PgForeachMonitorPolicyByPackageId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetMonitorPolicy"), PgGetMonitorPolicy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetAllMonitorPolicy"), PgGetAllMonitorPolicy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgCheckPrivacyPackage"), PgCheckPrivacyPackage);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgUpdateMonitorPolicy"), PgUpdateMonitorPolicy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetMainMonitorPolicy"), PgGetMainMonitorPolicy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgUpdateMainMonitorPolicy"), PgUpdateMainMonitorPolicy);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteAllLogs"), PgDeleteAllLogs);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddLeakLog"), PgAddLeakLog);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachLeakLogs"), PgForeachLeakLogs);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachLeakLogsByAppName"), PgForeachLeakLogsByAppName);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachLeakLogsByCategory"), PgForeachLeakLogsByCategory);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachAppLeakCount"), PgForeachAppLeakCount);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachCategoryLeakCount"), PgForeachCategoryLeakCount);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachLeakLogsByTimestamp"), PgForeachLeakLogsByTimestamp);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetLeakLogDetails"), PgGetLeakLogDetails);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgPurgeLeakLogs"), PgPurgeLeakLogs);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgPurgeLeakLogsByLogId"), PgPurgeLeakLogsByLogId);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetDlpProfile"), PgGetDlpProfile);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgSetDlpProfile"), PgSetDlpProfile);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetDlpCurrentRules"), PgGetDlpCurrentRules);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddDlpCustomRule"), PgAddDlpCustomRule);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgUpdateDlpCustomRule"), PgUpdateDlpCustomRule);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteDlpCustomRule"), PgDeleteDlpCustomRule);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachDlpCustomRules"), PgForeachDlpCustomRules);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachDlpRules"), PgForeachDlpRules);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgAddDlpPattern"), PgAddDlpPattern);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgDeleteDlpPattern"), PgDeleteDlpPattern);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgForeachDlpPatterns"), PgForeachDlpPatterns);
+       pSocketService->registerServiceCallback(getInterfaceName(), std::string("PgGetDlpCategories"), PgGetDlpCategories);
+}
 
-       static void PgAddPrivacyAccessLog(SocketConnection* pConnector);
-       static void PgAddMonitorPolicy(SocketConnection* pConnector);
-       static void PgDeleteLogsByPackageId(SocketConnection* pConnector);
-       static void PgDeleteMonitorPolicyByPackageId(SocketConnection* pConnector);
-       static void PgForeachTotalPrivacyCountOfPackage(SocketConnection* pConnector);
-       static void PgForeachTotalPrivacyCountOfPrivacy(SocketConnection* pConnector);
-       static void PgForeachPrivacyCountByPrivacyId(SocketConnection* pConnector);
-       static void PgForeachPrivacyCountByPackageId(SocketConnection* pConnector);
-       static void PgForeachPackageIdUsingPrivacy(SocketConnection* pConnector);
-       static void PgForeachPackageInfoByPrivacyId(SocketConnection* pConnector);
-       static void PgForeachMonitorPolicyByPackageId(SocketConnection* pConnector);
-       static void PgGetMonitorPolicy(SocketConnection* pConnector);
-       static void PgGetAllMonitorPolicy(SocketConnection* pConnector);
-       static void PgCheckPrivacyPackage(SocketConnection* pConnector);
-       static void PgUpdateMonitorPolicy(SocketConnection* pConnector);
-       static void PgGetMainMonitorPolicy(SocketConnection* pConnector);
-       static void PgUpdateMainMonitorPolicy(SocketConnection* pConnector);
-       static void PgDeleteAllLogs(SocketConnection* pConnector);
+static void PgAddPrivacyAccessLog(SocketConnection *pConnector);
+static void PgAddMonitorPolicy(SocketConnection *pConnector);
+static void PgDeleteLogsByPackageId(SocketConnection *pConnector);
+static void PgDeleteMonitorPolicyByPackageId(SocketConnection *pConnector);
+static void PgForeachTotalPrivacyCountOfPackage(SocketConnection *pConnector);
+static void PgForeachTotalPrivacyCountOfPrivacy(SocketConnection *pConnector);
+static void PgForeachPrivacyCountByPrivacyId(SocketConnection *pConnector);
+static void PgForeachPrivacyCountByPackageId(SocketConnection *pConnector);
+static void PgForeachPackageIdUsingPrivacy(SocketConnection *pConnector);
+static void PgForeachPackageInfoByPrivacyId(SocketConnection *pConnector);
+static void PgForeachMonitorPolicyByPackageId(SocketConnection *pConnector);
+static void PgGetMonitorPolicy(SocketConnection *pConnector);
+static void PgGetAllMonitorPolicy(SocketConnection *pConnector);
+static void PgCheckPrivacyPackage(SocketConnection *pConnector);
+static void PgUpdateMonitorPolicy(SocketConnection *pConnector);
+static void PgGetMainMonitorPolicy(SocketConnection *pConnector);
+static void PgUpdateMainMonitorPolicy(SocketConnection *pConnector);
+static void PgDeleteAllLogs(SocketConnection *pConnector);
+static void PgAddLeakLog(SocketConnection *pConnector);
+static void PgForeachLeakLogsByAppName(SocketConnection *pConnector);
+static void PgForeachLeakLogsByCategory(SocketConnection *pConnector);
+static void PgForeachLeakLogs(SocketConnection *pConnector);
+static void PgForeachAppLeakCount(SocketConnection *pConnector);
+static void PgForeachCategoryLeakCount(SocketConnection *pConnector);
+static void PgForeachLeakLogsByTimestamp(SocketConnection *pConnector);
+static void PgGetLeakLogDetails(SocketConnection *pConnector);
+static void PgPurgeLeakLogs(SocketConnection *pConnector);
+static void PgPurgeLeakLogsByLogId(SocketConnection *pConnector);
+static void PgGetDlpProfile(SocketConnection *pConnector);
+static void PgSetDlpProfile(SocketConnection *pConnector);
+static void PgGetDlpCurrentRules(SocketConnection *pConnector);
+static void PgAddDlpCustomRule(SocketConnection *pConnector);
+static void PgUpdateDlpCustomRule(SocketConnection *pConnector);
+static void PgDeleteDlpCustomRule(SocketConnection *pConnector);
+static void PgForeachDlpCustomRules(SocketConnection *pConnector);
+static void PgForeachDlpRules(SocketConnection *pConnector);
+static void PgAddDlpPattern(SocketConnection* pConnector);
+static void PgDeleteDlpPattern(SocketConnection* pConnector);
+static void PgForeachDlpPatterns(SocketConnection *pConnector);
+static void PgGetDlpCategories(SocketConnection *pConnector);
 };
-#endif // _PRIVACYINFOSERVICE_H_
\ No newline at end of file
+#endif // _PRIVACYINFOSERVICE_H_
index 2f18d68..6261943 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketService.h
+ */
+
 #ifndef _SOCKETSERVICE_H_
 #define _SOCKETSERVICE_H_
 
 
 typedef void(*socketServiceCallback)(SocketConnection* pConnector);
 
-class SocketService
-{
-       struct ConnectionInfo{
-               ConnectionInfo(int fd, void* pData) : connFd(fd), pData(pData) {}
-               int connFd;
-               void* pData;
-       };
-       class ServiceCallback
-       {
-       public:
-               ServiceCallback(socketServiceCallback callback)
-                       : serviceCallback(callback)
-               {}
-               socketServiceCallback serviceCallback;
-       };
-       
+class SocketService {
+class ServiceCallback {
+public:
+       ServiceCallback(socketServiceCallback callback) : serviceCallback(callback) { }
+       socketServiceCallback serviceCallback;
+};
+
+struct ConnectionInfo {
+       ConnectionInfo(int fd, void* pData) : connFd(fd), pData(pData) {}
+       int connFd;
+       void* pData;
+};
+
 private:
        static const int MAX_LISTEN;
        static const int TIMEOUT_SEC;
@@ -55,13 +56,13 @@ private:
        //Map for callback methods, key is a method name and value is a callback to method
        typedef std::map<std::string, ServiceCallbackPtr> ServiceMethodCallbackMap;
        //Map for interface methods, key is an interface name and value is a map of available methods with callbacks
-       std::map <std::string, ServiceMethodCallbackMap > m_callbackMap;
+       std::map<std::string, ServiceMethodCallbackMap> m_callbackMap;
 
        std::list < int > m_clientSocketList;
        std::mutex m_clientSocketListMutex;
 
 private:
-       static void* serverThread(void* );
+       static void* serverThread(void*);
        static void* connectionThread(void* pData);
        int connectionService(int fd);
        int mainloop(void);
@@ -81,4 +82,4 @@ public:
        int shutdown(void);
 };
 
-#endif //_SOCKETSERVICE_H_
\ No newline at end of file
+#endif //_SOCKETSERVICE_H_
index db04b25..8dedd1a 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       privacy_guard_daemon.h
+ */
+
 #ifndef _PRIVACY_GUARD_DAEMON_H_
 #define _PRIVACY_GUARD_DAEMON_H_
 
index e2d4a35..dbd19d3 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       CynaraService.cpp
+ */
+
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/server/src/DlpRuleChangeNotification.cpp b/server/src/DlpRuleChangeNotification.cpp
new file mode 100644 (file)
index 0000000..99c16cc
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpRuleChangeNotification.cpp
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include "DlpRuleChangeNotification.h"
+#include "Utils.h"
+
+#define BUF_SIZE 256
+
+std::mutex DlpRuleChangeNotification::m_singletonMutex;
+DlpRuleChangeNotification *DlpRuleChangeNotification::m_pInstance = NULL;
+
+DlpRuleChangeNotification*
+DlpRuleChangeNotification::getInstance(void)
+{
+       std::lock_guard<std::mutex> guard(m_singletonMutex);
+       if (m_pInstance == NULL) {
+               m_pInstance = new(std::nothrow) DlpRuleChangeNotification();
+       }
+       return m_pInstance;
+}
+
+int
+DlpRuleChangeNotification::addDlpClient(int pId)
+{
+       int res = PRIV_GUARD_ERROR_SUCCESS;
+       bool first_request_by_pid = true;
+       char sem_name[sizeof(PRIVACY_SEM_INITVAL)+5];
+       char buf[BUF_SIZE];
+
+       std::lock_guard<std::mutex> guard(m_singletonMutex);
+       for (auto it = m_semaphore_list.begin(); it != m_semaphore_list.end();) {
+               if (it->pid == pId) {
+                       // Process found, no need to add it to sem list
+                       first_request_by_pid = false;
+               } else {
+                       // Just checking if the process still exists, no signal is sent
+                       if (kill(it->pid, 0) == -1 && errno == ESRCH) {
+                               // process does not exists, remove from sem list
+                               sem_close(it->sem);
+                               it = m_semaphore_list.erase(it);
+                               continue;
+                       }
+               }
+               it++;
+       }
+
+       if (first_request_by_pid) {
+               // First request from process, to add it to sem list
+               snprintf(sem_name, sizeof(PRIVACY_SEM_INITVAL)+5, PRIVACY_SEM_INITVAL, pId);
+               privacy_semaphore_s ps;
+               ps.sem = sem_open(sem_name, 0);
+               if (ps.sem == SEM_FAILED) {
+                       PG_LOGE("errro opening sem: %s  - %s", sem_name, strerror_r(errno, buf, sizeof(buf)));
+                       res = errno;
+               } else {
+                       ps.pid = pId;
+                       m_semaphore_list.push_back(ps);
+               }
+       }
+
+       return res;
+}
+
+int
+DlpRuleChangeNotification::notifyDlpClients()
+{
+       char buf[BUF_SIZE];
+       int res = PRIV_GUARD_ERROR_SUCCESS;
+
+       std::lock_guard<std::mutex> guard(m_singletonMutex);
+       for (auto it = m_semaphore_list.begin(); it != m_semaphore_list.end();) {
+               // Just checking if the process still exists, no signal is sent
+               if (kill(it->pid, 0) == -1 && errno == ESRCH) {
+                       // process does not exists, remove from sem list
+                       sem_close(it->sem);
+                       it = m_semaphore_list.erase(it);
+               } else {
+                       // process does exists, post sem
+                       PG_LOGD("posting sem: 0x%x, pid: %d", it->sem, it->pid);
+                       if (sem_post(it->sem) < 0) {
+                               res = errno;
+                               PG_LOGE("errro posting sem: 0x%x, pid: %d - %s", it->sem, it->pid, strerror_r(errno, buf, sizeof(buf)));
+                       }
+                       it++;
+               }
+       }
+
+       return res;
+}
index 922f25b..d5ed496 100755 (executable)
@@ -1,4 +1,4 @@
-/*
+/*zz
  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    limitations under the License.
  */
 
-#include <string>
+/**
+ * @file       PrivacyGuardDaemon.cpp
+ */
+
 #include "PrivacyGuardDaemon.h"
 #include "PrivacyInfoService.h"
+#include "DlpPrivacyInfoData.h"
 #include "SocketService.h"
 #include <CynaraService.h>
 
@@ -86,6 +90,11 @@ PrivacyGuardDaemon::start(void)
                PG_LOGE("FAIL");
        }
 
+       PG_LOGI("Starting DLP");
+       res = DlpPrivacyInfoData::getInstance()->start();
+       if (res != true)
+               PG_LOGE("Can not start DLP");
+
        return res;
 }
 
@@ -98,6 +107,8 @@ PrivacyGuardDaemon::stop(void)
        PG_LOGD("calling pCynaraService->stop()");
        pCynaraService->stop();
 
+       DlpPrivacyInfoData::getInstance()->stop();
+
        return 0;
 }
 
old mode 100755 (executable)
new mode 100644 (file)
index f27c792..782a493
@@ -13,6 +13,9 @@
  *    See the License for the specific language governing permissions and
  *    limitations under the License.
  */
+/**
+ * @file       PrivacyGuardDb.cpp
+ */
 
 #include <sstream>
 #include <fstream>
@@ -22,6 +25,7 @@
 #include "Utils.h"
 #include "PrivacyGuardDb.h"
 #include "PrivacyIdInfo.h"
+#include "DlpRuleChangeNotification.h"
 
 #define PRIVACY_GUARD_DAYS 7
 #define UNIX_TIME_ONE_DAY (24 * 60 * 60) // 86400 secs
@@ -80,8 +84,7 @@ PrivacyGuardDb::openSqliteDB(void)
                PG_LOGI("monitor db is opened successfully");
                //sqlite3_wal_autocheckpoint(m_sqlHandler, 1);
                m_bDBOpen = true;
-       }
-       else {
+       } else {
                PG_LOGE("fail : monitor db open(%d)", res);
        }
 }
@@ -282,7 +285,7 @@ PrivacyGuardDb::PgCheckPrivacyPackage(const int userId, const std::string packag
 
        // prepare
        res = sqlite3_prepare_v2(m_sqlHandler, query.c_str(), -1, &m_stmt, NULL);
-       TryCatchResLogReturn( res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
 
        // bind
        res = sqlite3_bind_int(m_stmt, 1, userId);
@@ -304,8 +307,7 @@ PrivacyGuardDb::PgCheckPrivacyPackage(const int userId, const std::string packag
 
        if (count > 0) {
                isPrivacyPackage = true;
-       }
-       else {
+       } else {
                isPrivacyPackage = false;
        }
 
@@ -933,8 +935,7 @@ PrivacyGuardDb::PgGetAllMonitorPolicy(std::list < std::pair < std::string, int >
        PG_LOGD("monitorPolicyList.size() is [%d]", monitorPolicyList.size());
        if(monitorPolicyList.size() > 0) {
                res = PRIV_GUARD_ERROR_SUCCESS;
-       }
-       else {
+       } else {
                res = PRIV_GUARD_ERROR_NO_DATA;
        }
 
@@ -989,9 +990,8 @@ PrivacyGuardDb::PgForeachMonitorPolicyByPackageId(const int userId, const std::s
                }
                privacy_data_s p_data;
                memset(p_data.privacy_id, 0x0, LEN_PRIVACY_ID);
-               strncpy(p_data.privacy_id, tmp_data, strlen(tmp_data));
-               p_data.privacy_id[strlen(tmp_data)] = '\0';
-               p_data.monitor_policy= sqlite3_column_int(m_stmt, 1);
+               pg_strlcpy(p_data.privacy_id, tmp_data, strlen(tmp_data));
+               p_data.monitor_policy = sqlite3_column_int(m_stmt, 1);
 
                privacyInfoList.push_back(p_data);
        }
@@ -1141,19 +1141,17 @@ PrivacyGuardDb::prepareGlobalPackagePolicy(const int userId)
 
        // step
        while ((res = sqlite3_step(m_stmt)) == SQLITE_ROW) {
-               char *temp1 = (char*)sqlite3_column_text(m_stmt, 0);    // package_id
-               char *temp2 = (char*)sqlite3_column_text(m_stmt, 1);    // privacy_id
-               if(temp1 == NULL || temp2 == NULL) {
+               char *package_id = (char*)sqlite3_column_text(m_stmt, 0);
+               char *privacy_id = (char*)sqlite3_column_text(m_stmt, 1);
+               if(package_id == NULL || privacy_id == NULL) {
                        //PG_LOGD("PackageID: [%s], PrivacyID: [%s]", temp1, temp2);
                        continue;
                }
                package_privacy_data_s p_data;
                memset(p_data.package_id, 0x0, LEN_PACKAGE_ID);
                memset(p_data.privacy_id, 0x0, LEN_PRIVACY_ID);
-               strncpy(p_data.package_id, temp1, strlen(temp1));
-               strncpy(p_data.privacy_id, temp2, strlen(temp2));
-               p_data.package_id[strlen(temp1)] = '\0';
-               p_data.privacy_id[strlen(temp2)] = '\0';
+               pg_strlcpy(p_data.package_id, package_id, strlen(package_id));
+               pg_strlcpy(p_data.privacy_id, privacy_id, strlen(privacy_id));
                dataList.push_back(p_data);
        }
 
@@ -1255,8 +1253,7 @@ PrivacyGuardDb::PgForeachPackageInfoByPrivacyId(const int userId, const std::str
                }
                package_data_s p_data;
                memset(p_data.package_id, 0x0, LEN_PACKAGE_ID);
-               strncpy(p_data.package_id, tmp_data, strlen(tmp_data));
-               p_data.package_id[strlen(tmp_data)] = '\0';
+               pg_strlcpy(p_data.package_id, tmp_data, strlen(tmp_data));
                p_data.monitor_policy = sqlite3_column_int(m_stmt, 1);
                PG_LOGD("## package_id[%s]", p_data.package_id);
                PG_LOGD("## monitor_policy[%d]", p_data.monitor_policy);
@@ -1510,8 +1507,7 @@ PrivacyGuardDb::PgGetMainMonitorPolicy(const int userId, int &mainMonitorPolicy)
 
                sqlite3_finalize(m_stmt);
                m_dbMutex.unlock();
-       }
-       else {
+       } else {
                sqlite3_finalize(m_stmt);
                m_dbMutex.unlock();
                res = PgAddMainMonitorPolicy(userId);
@@ -1567,6 +1563,1533 @@ PrivacyGuardDb::PgDeleteMainMonitorPolicyByUserId(const int userId)
        return PRIV_GUARD_ERROR_SUCCESS;
 }
 
+int
+PrivacyGuardDb::PgAddLeakLog(leak_log_insert_common_data_s &data, const std::list<leak_log_insert_data_s> &logList)
+{
+       int res = -1;
+       int requestId;
+
+       const char *insertr = "INSERT INTO DlpRequestLog(USER_ID, TIME_STAMP, APP_NAME, APP_ICON, APP_ID, APP_VERSION, "
+                             "PKG_ID, DESTINATION, RAW_PACKET) "
+                             "VALUES(?, ?, ?, ?, ?, ?, ?, ?, CAST(? AS BLOB))";
+
+       const char *selectid = "SELECT ID FROM DlpRequestLog ORDER BY ID DESC LIMIT 1";
+
+       const char *insertl = "INSERT INTO DlpLeakLog(REQUEST_ID, PATTERN_ID, ACTION, LEAK_OFFSET, LEAK_LEN) "
+                             "VALUES(?, ?, ?, ?, ?)";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // insert in DlpRequestLog
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, insertr, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, data.user_id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, time(NULL));
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 3, data.application_name, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 4, data.application_icon, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 5, data.application_id, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 6, data.application_version, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 7, data.package_id, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 8, data.destination, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_blob(m_stmt, 9, data.pkt_data.buffer, data.pkt_data.len, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_blob : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       // get ID of last row
+       res = sqlite3_prepare_v2(m_sqlHandler, selectid, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       if (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               requestId = sqlite3_column_int(m_stmt, 0);
+       } else {
+               m_dbMutex.unlock();
+               return PRIV_GUARD_ERROR_DB_ERROR;
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       // must free the pkt_data.buffer to prevent memory leak
+       delete[] (uint8_t *)data.pkt_data.buffer;
+       data.pkt_data.buffer = NULL;
+       data.pkt_data.len = 0;
+
+       // now append to DlpLeakLog
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, insertl, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       for (const auto &it : logList) {
+               // bind
+               res = sqlite3_bind_int(m_stmt, 1, requestId);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 2, it.pattern_id);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 3, it.action);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 4, it.leak_offset);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 5, it.leak_len);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               // step
+               res = sqlite3_step(m_stmt);
+               TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+               sqlite3_reset(m_stmt);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgForeachLeakLogs(const int userId, const char *appName, int category_id, std::list<leak_log_get_data_s> &logList)
+{
+       int res;
+       dlp_profile_s profile;
+       const char *query;
+
+       if (category_id > 0)
+         query = "SELECT L.ID, RE.TIME_STAMP, L.ACTION, RE.APP_NAME, RE.APP_ICON, RE.DESTINATION "
+                                               "FROM DlpLeakLog AS L, DlpRequestLog AS RE, DlpPatterns AS P WHERE RE.USER_ID=? AND "
+                                               "L.REQUEST_ID=RE.ID AND L.PATTERN_ID=P.ID AND RE.APP_NAME LIKE ? AND P.CATEGORY_ID=?";
+       else
+         query = "SELECT L.ID, RE.TIME_STAMP, L.ACTION, RE.APP_NAME, RE.APP_ICON, RE.DESTINATION "
+                                               "FROM DlpLeakLog AS L, DlpRequestLog AS RE, DlpPatterns AS P WHERE RE.USER_ID=? AND "
+                                               "L.REQUEST_ID=RE.ID AND L.PATTERN_ID=P.ID AND RE.APP_NAME LIKE ?";
+       // clear old logs
+       res = PgGetDlpProfile(userId, profile);
+       if (res == PRIV_GUARD_ERROR_SUCCESS)
+               PgPurgeLeakLogsByDays(userId, profile.keep_log_days);
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 2, appName ? appName : "%", -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       if (category_id > 0) {
+         res = sqlite3_bind_int(m_stmt, 3, category_id);
+         TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+       }
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               leak_log_get_data_s log;
+               log.id = sqlite3_column_int(m_stmt, 0);
+               log.time_stamp = sqlite3_column_int(m_stmt, 1);
+               log.action = (PgDlpAction)sqlite3_column_int(m_stmt, 2);
+               pg_strlcpy(log.application_name, (const char *)sqlite3_column_text(m_stmt, 3), LEN_APPLICATION_NAME);
+               pg_strlcpy(log.application_icon, (const char *)sqlite3_column_text(m_stmt, 4), LEN_APPLICATION_ICON);
+               pg_strlcpy(log.destination, (const char *)sqlite3_column_text(m_stmt, 5), LEN_DESTINATION);
+               logList.push_back(log);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgForeachAppLeakCount(const int userId, std::list<leak_log_get_app_count_s> &logList)
+{
+       int res;
+       dlp_profile_s profile;
+       const char *query = "SELECT R.APP_NAME, MIN(R.TIME_STAMP), MAX(R.TIME_STAMP), R.APP_ICON, COUNT(L.ID) AS LEAK_COUNT "
+                                               "FROM DlpRequestLog AS R, DlpLeakLog AS L WHERE R.USER_ID=? AND R.ID = L.REQUEST_ID "
+                                               "GROUP BY R.APP_NAME ORDER BY LEAK_COUNT DESC";
+
+       // clear old logs
+       res = PgGetDlpProfile(userId, profile);
+       if (res == PRIV_GUARD_ERROR_SUCCESS)
+               PgPurgeLeakLogsByDays(userId, profile.keep_log_days);
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               leak_log_get_app_count_s log;
+               pg_strlcpy(log.application_name, (const char *)sqlite3_column_text(m_stmt, 0), LEN_APPLICATION_NAME);
+               log.first_time_stamp = sqlite3_column_int(m_stmt, 1);
+               log.last_time_stamp = sqlite3_column_int(m_stmt, 2);
+               pg_strlcpy(log.application_icon, (const char *)sqlite3_column_text(m_stmt, 3), LEN_APPLICATION_ICON);
+               log.leak_count = sqlite3_column_int(m_stmt, 4);
+               logList.push_back(log);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgForeachCategoryLeakCount(const int userId, std::list<leak_log_get_category_count_s> &logList)
+{
+       int res;
+       dlp_profile_s profile;
+       const char *query = "SELECT P.CATEGORY_ID, MIN(R.TIME_STAMP), MAX(R.TIME_STAMP), COUNT(L.ID) AS LEAK_COUNT "
+                                               "FROM DlpRequestLog AS R, DlpLeakLog AS L, DlpPatterns AS P WHERE R.USER_ID=? AND "
+                                               "R.ID = L.REQUEST_ID AND P.ID = L.PATTERN_ID GROUP BY P.CATEGORY_ID ORDER BY LEAK_COUNT DESC";
+
+       // clear old logs
+       res = PgGetDlpProfile(userId, profile);
+       if (res == PRIV_GUARD_ERROR_SUCCESS)
+               PgPurgeLeakLogsByDays(userId, profile.keep_log_days);
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               leak_log_get_category_count_s log;
+               log.category.id = sqlite3_column_int(m_stmt, 0);
+               log.first_time_stamp = sqlite3_column_int(m_stmt, 1);
+               log.last_time_stamp = sqlite3_column_int(m_stmt, 2);
+               log.leak_count = sqlite3_column_int(m_stmt, 3);
+               logList.push_back(log);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgForeachLeakLogsByTimestamp(const int userId, const time_t start, const time_t end, std::list<leak_log_get_data_s> &logList)
+{
+       int res;
+       dlp_profile_s profile;
+       const char *query = "SELECT L.ID, RE.TIME_STAMP, L.ACTION, RE.APP_NAME, RE.APP_ICON, RE.DESTINATION "
+                                               "FROM DlpLeakLog AS L, DlpRequestLog AS RE "
+                                               "WHERE RE.USER_ID=? AND RE.TIME_STAMP >= ? AND RE.TIME_STAMP <= ? AND L.REQUEST_ID=RE.ID";
+
+       // clear old logs
+       res = PgGetDlpProfile(userId, profile);
+       if (res == PRIV_GUARD_ERROR_SUCCESS)
+               PgPurgeLeakLogsByDays(userId, profile.keep_log_days);
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, start);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, end);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               leak_log_get_data_s log;
+               log.id = sqlite3_column_int(m_stmt, 0);
+               log.time_stamp = sqlite3_column_int(m_stmt, 1);
+               log.action = (PgDlpAction)sqlite3_column_int(m_stmt, 2);
+               pg_strlcpy(log.application_name, (const char *)sqlite3_column_text(m_stmt, 3), LEN_APPLICATION_NAME);
+               pg_strlcpy(log.application_icon, (const char *)sqlite3_column_text(m_stmt, 4), LEN_APPLICATION_ICON);
+               pg_strlcpy(log.destination, (const char *)sqlite3_column_text(m_stmt, 5), LEN_DESTINATION);
+               logList.push_back(log);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgGetLeakLogDetails(int userId, int logId, leak_log_get_detail_data_s &logDetail)
+{
+       int res = -1;
+       int fragment_offset;
+       const char *query = "SELECT L.ACTION, RE.APP_ID, RE.APP_NAME, RE.APP_VERSION, RE.APP_ICON, RE.PKG_ID, " \
+                                               "RE.DESTINATION, P.NAME, P.CATEGORY_ID, LENGTH(CAST(RE.RAW_PACKET AS BLOB)), "                          \
+                                               " CAST(RE.RAW_PACKET AS BLOB), L.LEAK_OFFSET, "                                                                                 \
+                                               "L.LEAK_LEN FROM DlpLeakLog AS L, DlpRequestLog AS RE, DlpPatterns AS P "                               \
+                                               " WHERE RE.USER_ID=? AND L.ID=? AND L.REQUEST_ID=RE.ID AND L.PATTERN_ID=P.ID";
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false)
+               initialize();
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if (m_bDBOpen == false)
+               openSqliteDB();
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, logId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       if (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               logDetail.action = (PgDlpAction)sqlite3_column_int(m_stmt, 0);
+               pg_strlcpy(logDetail.application_id, (const char *)sqlite3_column_text(m_stmt, 1), LEN_APPLICATION_ID);
+               pg_strlcpy(logDetail.application_name, (const char *)sqlite3_column_text(m_stmt, 2), LEN_APPLICATION_NAME);
+               pg_strlcpy(logDetail.application_version, (const char *)sqlite3_column_text(m_stmt, 3), LEN_APPLICATION_VERSION);
+               pg_strlcpy(logDetail.application_icon, (const char *)sqlite3_column_text(m_stmt, 4), LEN_APPLICATION_ICON);
+               pg_strlcpy(logDetail.package_id, (const char *)sqlite3_column_text(m_stmt, 5), LEN_PACKAGE_ID);
+               pg_strlcpy(logDetail.destination, (const char *)sqlite3_column_text(m_stmt, 6), LEN_DESTINATION);
+               pg_strlcpy(logDetail.pattern_name, (const char *)sqlite3_column_text(m_stmt, 7), LEN_NAME);
+               logDetail.category.id = sqlite3_column_int(m_stmt, 8);
+               logDetail.pkt_len = sqlite3_column_int(m_stmt, 9);
+               logDetail.leak_offset = sqlite3_column_int(m_stmt, 11);
+               logDetail.leak_len = sqlite3_column_int(m_stmt, 12);
+
+               // trim the packet to the just show the part around the leak
+               fragment_offset = logDetail.leak_offset > PRE_MATCH_BYTES ? logDetail.leak_offset - PRE_MATCH_BYTES : 0;
+               logDetail.leak_offset -= fragment_offset;
+               logDetail.pkt_len = fragment_offset +  logDetail.leak_offset + logDetail.leak_len + POST_MATCH_BYTES > logDetail.pkt_len ?
+                                   logDetail.pkt_len - fragment_offset :
+                                   logDetail.leak_offset + logDetail.leak_len + POST_MATCH_BYTES;
+               memcpy(logDetail.raw_packet, ((const char *)sqlite3_column_blob(m_stmt, 10)) + fragment_offset, logDetail.pkt_len);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int PrivacyGuardDb::purgeUnusedDeletedPatterns()
+{
+       int patternId;
+       const char *query1 = "SELECT ID FROM DlpPatterns WHERE STATE=?";
+       const char *query2 = "SELECT ID FROM DlpLeakLog WHERE PATTERN_ID=?";
+       const char *query3 = "DELETE FROM DlpPatterns WHERE ID=?";
+
+       sqlite3_stmt* m_stmt2;
+
+       // prepare
+       int res = sqlite3_prepare_v2(m_sqlHandler, query1, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, PRIV_GUARD_DLP_PATTERN_STATE_DELETED);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               // step through all patterns marked as STATE=PRIV_GUARD_DLP_PATTERN_STATE_DELETED
+               patternId = sqlite3_column_int(m_stmt, 0);
+
+               // query leak logs to see if any has a reference to the pattern. Otherwise we delete the pattern
+               // prepare
+               res = sqlite3_prepare_v2(m_sqlHandler, query2, -1, &m_stmt2, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt2, 1, patternId);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               if (sqlite3_step(m_stmt2) == SQLITE_ROW) {
+                       // leak log still has a ref to this
+                       sqlite3_finalize(m_stmt2);
+                       continue;
+               }
+
+               // no refs so we can delete the pattern
+               // prepare
+               res = sqlite3_prepare_v2(m_sqlHandler, query3, -1, &m_stmt2, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt2, 1, patternId);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               // step
+               res = sqlite3_step(m_stmt2);
+               TryCatchResLogReturn(res == SQLITE_DONE, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+               sqlite3_finalize(m_stmt2);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgPurgeLeakLogs(const int userId)
+{
+       int res = -1;
+
+       const char *query1 = "DELETE FROM DlpRequestLog WHERE USER_ID=?";
+       const char *query2 = "DELETE FROM DlpLeakLog WHERE REQUEST_ID NOT IN (SELECT DISTINCT ID FROM DlpRequestLog)";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query1, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query2, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       purgeUnusedDeletedPatterns();
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgPurgeLeakLogsByDays(const int userId, int days)
+{
+       int res = -1;
+       time_t timeStamp;
+       struct tm localTime;
+       const char *query1 = "DELETE FROM DlpRequestLog WHERE USER_ID=? AND TIME_STAMP<?";
+       const char *query2 = "DELETE FROM DlpLeakLog WHERE REQUEST_ID NOT IN (SELECT DISTINCT ID FROM DlpRequestLog)";
+
+       if (days < 1)
+               return PRIV_GUARD_ERROR_INVALID_PARAMETER;
+
+       // calculate days to keep logs
+       timeStamp = time(NULL);
+       localtime_r(&timeStamp, &localTime);
+       localTime.tm_hour = localTime.tm_min = localTime.tm_sec = 0;
+       timeStamp = mktime(&localTime) - UNIX_TIME_ONE_DAY * (days - 1);
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query1, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, timeStamp);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query2, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       purgeUnusedDeletedPatterns();
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+namespace {
+       std::string getQueryToPurgeLogsByLogId(const size_t numberOfLogIds) {
+               std::string query{ "DELETE FROM DlpLeakLog WHERE ID IN (?" };
+               for (size_t i = 1; i < numberOfLogIds; ++i) {
+                       query += ",?";
+               }
+               query += ")";
+               return query;
+       }
+}
+
+int
+PrivacyGuardDb::PgPurgeLeakLogsByLogId(const std::list<int> &logId)
+{
+       int res = -1;
+
+       const std::string query{ getQueryToPurgeLogsByLogId(logId.size()) };
+       const char *query2 = "DELETE FROM DlpRequestLog WHERE ID NOT IN (SELECT DISTINCT REQUEST_ID FROM DlpLeakLog)";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query.c_str(), -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       auto idIndex = 0;
+       for (const auto id : logId) {
+               res = sqlite3_bind_int(m_stmt, ++idIndex, id);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+       }
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query2, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       purgeUnusedDeletedPatterns();
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgSetDlpProfile(const int userId, const dlp_profile_s &profile)
+{
+       int res = -1;
+       const char *query = "UPDATE DlpProfile SET ENABLED=?, PROFILE=?, KEEP_LOG_DAYS=? WHERE USER_ID=?";
+       const char *insert = "INSERT INTO DlpProfile(USER_ID, ENABLED, PROFILE, KEEP_LOG_DAYS) VALUES(?, ?, ?, ?)";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, profile.enabled);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, profile.profile);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, profile.keep_log_days);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 4, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       // insert profile if not found
+       if (sqlite3_changes(m_sqlHandler) == 0) {
+               sqlite3_finalize(m_stmt);
+
+               // prepare
+               res = sqlite3_prepare_v2(m_sqlHandler, insert, -1, &m_stmt, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt, 1, userId);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 2, profile.enabled);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 3, profile.profile);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 4, profile.keep_log_days);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               // step
+               res = sqlite3_step(m_stmt);
+               TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+       m_dbMutex.unlock();
+
+       return PgPurgeLeakLogsByDays(userId, profile.keep_log_days);
+}
+
+int
+PrivacyGuardDb::PgGetDlpProfile(const int userId, dlp_profile_s &profile)
+{
+       int res = -1;
+       const char *query = "SELECT ENABLED, PROFILE, KEEP_LOG_DAYS FROM DlpProfile WHERE USER_ID=?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       if (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               profile.enabled = sqlite3_column_int(m_stmt, 0);
+               profile.profile = (PgDlpProfile)sqlite3_column_int(m_stmt, 1);
+               profile.keep_log_days = sqlite3_column_int(m_stmt, 2);
+       } else {
+               profile.enabled = false;
+               profile.profile = PRIV_GUARD_DLP_PROFILE_BASIC;
+               profile.keep_log_days = KEEP_LOG_DAYS_WEEKLY;
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgGetDlpCurrentRules(const int userId, const char *appId, const int pId, std::list<current_rules_s> &rules)
+{
+       int res = -1;
+       char query[256];
+       dlp_profile_s profile;
+
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->addDlpClient(pId);
+
+       // get current profile
+       PgGetDlpProfile(userId, profile);
+       if (!profile.enabled)
+               return PRIV_GUARD_ERROR_SUCCESS;
+
+       m_dbMutex.lock();
+
+       //////////////////////////////
+       // get regular rules
+       //////////////////////////////
+
+       // prepare
+       snprintf(query, sizeof(query), "SELECT R.ID, R.PATTERN_ID, R.ACTION, P.PATTERN, P.TYPE FROM DlpRules AS R, DlpPatterns AS P WHERE R.PROFILE=? "
+                "AND R.PATTERN_ID=P.ID AND R.APP_ID=\"\"%s", profile.profile == PRIV_GUARD_DLP_PROFILE_CUSTOM ? " AND R.USER_ID=?" : "");
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, profile.profile);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       if (profile.profile == PRIV_GUARD_DLP_PROFILE_CUSTOM) {
+               res = sqlite3_bind_int(m_stmt, 2, userId);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+       }
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               current_rules_s rule;
+               rule.id = sqlite3_column_int(m_stmt, 0);
+               rule.pattern_id = sqlite3_column_int(m_stmt, 1);
+               rule.action = (PgDlpAction)sqlite3_column_int(m_stmt, 2);
+               pg_strlcpy(rule.pattern, (const char *)sqlite3_column_text(m_stmt, 3), LEN_PATTERN);
+               rule.type = (PgDlpPatternType)sqlite3_column_int(m_stmt, 4);
+               rules.push_back(rule);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       if (appId[0] != '\0') {
+               //////////////////////////////
+               // get app specific rules
+               //////////////////////////////
+
+               // prepare
+               snprintf(query, sizeof(query), "SELECT R.ID, R.PATTERN_ID, R.ACTION, P.PATTERN, P.TYPE FROM DlpRules AS R, DlpPatterns AS P WHERE "
+                       "R.PROFILE=? AND R.PATTERN_ID=P.ID AND R.APP_ID=?%s", profile.profile == PRIV_GUARD_DLP_PROFILE_CUSTOM ?
+                       " AND R.USER_ID=?" : "");
+               res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt, 1, profile.profile);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_text(m_stmt, 2, appId, -1, SQLITE_TRANSIENT);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+               if (profile.profile == PRIV_GUARD_DLP_PROFILE_CUSTOM) {
+                       res = sqlite3_bind_int(m_stmt, 3, userId);
+                       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+               }
+
+               // step
+               while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+                       std::list<current_rules_s>::iterator it;
+                       const int pattern_id = sqlite3_column_int(m_stmt, 1);
+                       const PgDlpPatternType type = (PgDlpPatternType)sqlite3_column_int(m_stmt, 4);
+
+                       // rule found, replace it
+                       for (it = rules.begin(); it != rules.end(); it++) {
+                               if (it->pattern_id == pattern_id && it->type == type) {
+                                       // replaces a general rule with an app specific one
+                                       it->id = sqlite3_column_int(m_stmt, 0);
+                                       it->action = (PgDlpAction)sqlite3_column_int(m_stmt, 2);
+                                       pg_strlcpy(it->pattern, (const char *)sqlite3_column_text(m_stmt, 3), LEN_PATTERN);
+                                       break;
+                               }
+                       }
+
+                       // rule not found, insert it
+                       if (it == rules.end()) {
+                               current_rules_s rule;
+                               rule.id = sqlite3_column_int(m_stmt, 0);
+                               rule.pattern_id = sqlite3_column_int(m_stmt, 1);
+                               rule.action = (PgDlpAction)sqlite3_column_int(m_stmt, 2);
+                               pg_strlcpy(rule.pattern, (const char *)sqlite3_column_text(m_stmt, 3), LEN_PATTERN);
+                               rule.type = (PgDlpPatternType)sqlite3_column_int(m_stmt, 4);
+                               rules.push_back(rule);
+                       }
+               }
+
+               sqlite3_finalize(m_stmt);
+       }
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgGetAccountEmails(const int userId, std::set<std::string> &emails)
+{
+       sqlite3 *sqlHandler = NULL;
+       int res = -1;
+       sqlite3_stmt *stmt;
+       const char *email_query = "SELECT DISTINCT email_address FROM account";
+       char account_uid_db_path[sizeof("%d/.account.db") + 8];
+
+       //////////////////////////////
+       // get account emails
+       //////////////////////////////
+
+       snprintf(account_uid_db_path, sizeof("%d/.account.db") + 8, "%d/.account.db", userId);
+       res = sqlite3_open_v2(tzplatform_mkpath(TZ_SYS_DB, account_uid_db_path), &sqlHandler, SQLITE_OPEN_READONLY, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, ;, PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_open_v2 : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(sqlHandler, email_query, -1, &stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_close_v2(sqlHandler), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // step
+       while (sqlite3_step(stmt) == SQLITE_ROW) {
+               std::string email((const char *)sqlite3_column_text(stmt, 0));
+               emails.insert(email);
+       }
+
+       sqlite3_finalize(stmt);
+
+       sqlite3_close_v2(sqlHandler);
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgAddDlpCustomRule(int userId, const custom_rule_s &rule)
+{
+       int res = -1;
+
+       const char *insertr = "INSERT INTO DlpRules (USER_ID, PROFILE, ACTION, PATTERN_ID, NAME, DESCRIPTION) VALUES (?, ?, ?, ?, ?, ?)";
+       const char *insertFullr = "INSERT INTO DlpRules (USER_ID, PROFILE, ACTION, PATTERN_ID, NAME, DESCRIPTION, APP_ID) "
+         "VALUES (?, ?, ?, ?, ?, ?, ?)";
+       const char *update = "UPDATE DlpPatterns SET STATE = ? WHERE ID = ? AND STATE = ?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // insert the rule
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, rule.application_id[0] != '\0' ? insertFullr : insertr, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, userId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, PRIV_GUARD_DLP_PROFILE_CUSTOM);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, rule.action);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 4, rule.pattern_id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 5, rule.name, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 6, rule.description, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       // extra information for over rule
+       if (rule.application_id[0] != '\0') {
+               res = sqlite3_bind_text(m_stmt, 7, rule.application_id, -1, SQLITE_TRANSIENT);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+       }
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       // update pattern state
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, update, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, (int)PRIV_GUARD_DLP_PATTERN_STATE_IN_USE);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, rule.pattern_id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, (int)PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int PrivacyGuardDb::markUnusedPatterns(int ruleId, int newPatternId, sqlite3_stmt* update_stmt)
+{
+       int res = -1;
+       int patternId, patternCount;
+
+       const char *query1 = "SELECT PATTERN_ID FROM DlpRules WHERE ID=?";
+       const char *query2 = "SELECT COUNT(*) FROM DlpRules WHERE PATTERN_ID=?";
+       const char *query3 = "UPDATE DlpPatterns SET STATE=? WHERE ID=? AND STATE=?";
+
+       // get old PATTERN_ID
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query1, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, ruleId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_ROW, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       patternId = sqlite3_column_int(m_stmt, 0);
+       sqlite3_finalize(m_stmt);
+
+       // execute the delete or update statement - we need to be sure this succeeds before marking the pattern
+       while ((res = sqlite3_step(update_stmt)) == SQLITE_ROW);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+       sqlite3_finalize(update_stmt);
+
+       if (newPatternId != patternId) {
+               // rule was deleted or updated
+               // get count of PATTERN_ID now
+
+               // prepare
+               res = sqlite3_prepare_v2(m_sqlHandler, query2, -1, &m_stmt, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt, 1, patternId);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               // step
+               res = sqlite3_step(m_stmt);
+               TryCatchResLogReturn(res == SQLITE_ROW, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+               patternCount = sqlite3_column_int(m_stmt, 0);
+               sqlite3_finalize(m_stmt);
+
+               if (patternCount == 0) {
+                       // we can delete the pattern as we were the only one using it
+                       // for now we just mark it as STATE=PRIV_GUARD_DLP_PATTERN_STATE_DELETED. This is because some log details may refer to it.
+                       // We will delete these patterns from the database during leak log cleanup.
+
+                       // prepare
+                       res = sqlite3_prepare_v2(m_sqlHandler, query3, -1, &m_stmt, NULL);
+                       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+                       // bind
+                       // (If automatic deletion is no longer required, the state could change to PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE instead.)
+                       res = sqlite3_bind_int(m_stmt, 1, PRIV_GUARD_DLP_PATTERN_STATE_DELETED);
+                       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+                       // bind
+                       res = sqlite3_bind_int(m_stmt, 2, patternId);
+                       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+                       // bind
+                       res = sqlite3_bind_int(m_stmt, 3, PRIV_GUARD_DLP_PATTERN_STATE_IN_USE);
+                       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+                       // step
+                       res = sqlite3_step(m_stmt);
+                       TryCatchResLogReturn(res == SQLITE_DONE || res == SQLITE_ROW, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+                       sqlite3_finalize(m_stmt);
+               }
+       }
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgUpdateDlpCustomRule(const custom_rule_s &rule)
+{
+       int res = -1;
+
+       sqlite3_stmt *update_stmt;
+
+       const char *update = "UPDATE DlpRules SET PROFILE = ?, ACTION = ?, PATTERN_ID = ?, NAME = ?, DESCRIPTION = ?, APP_ID = ? "
+                            "WHERE ID = ?";
+       const char *updatepattern = "UPDATE DlpPatterns SET STATE = ? WHERE ID = ? AND STATE = ?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false)
+               initialize();
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if (m_bDBOpen == false)
+               openSqliteDB();
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, update, -1, &update_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(update_stmt, 1, PRIV_GUARD_DLP_PROFILE_CUSTOM);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(update_stmt, 2, (int)rule.action);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(update_stmt, 3, rule.pattern_id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(update_stmt, 4, rule.name, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(update_stmt, 5, rule.description, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(update_stmt, 6, rule.application_id, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_int(update_stmt, 7, rule.id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       // mark the pattern as deleted if no longer used
+       res = markUnusedPatterns(rule.id, rule.pattern_id, update_stmt);
+       TryCatchResLogReturn(res == PRIV_GUARD_ERROR_SUCCESS, m_dbMutex.unlock(), res, "markUnusedPatterns : %d", res);
+
+       // update pattern state
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, updatepattern, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, (int)PRIV_GUARD_DLP_PATTERN_STATE_IN_USE);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, rule.pattern_id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, (int)PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE || res == SQLITE_ROW, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgDeleteDlpCustomRule(int ruleId)
+{
+       int res = -1;
+
+       sqlite3_stmt *update_stmt;
+
+       const char *query = "DELETE FROM DlpRules WHERE ID=?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false)
+               initialize();
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if (m_bDBOpen == false)
+               openSqliteDB();
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // query to delete the Rule
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &update_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(update_stmt, 1, ruleId);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(update_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // mark the pattern as deleted if no longer used
+       res = markUnusedPatterns(ruleId, 0, update_stmt);
+       TryCatchResLogReturn(res == PRIV_GUARD_ERROR_SUCCESS, m_dbMutex.unlock(), res, "markUnusedPatterns : %d", res);
+
+       // notify clients of the rule change
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgForeachDlpCustomRules(int userId, std::list<get_custom_rule_s> &rules)
+{
+  return PgForeachDlpRules(userId, (int)PRIV_GUARD_DLP_PROFILE_CUSTOM, rules);
+}
+
+int
+PrivacyGuardDb::PgForeachDlpRules(int userId, int profile, std::list<get_custom_rule_s> &rules)
+{
+       int res = -1;
+       const char *queryc = "SELECT R.ID, R.ACTION, R.PATTERN_ID, R.NAME, R.DESCRIPTION, P.NAME, P.DESCRIPTION, R.APP_ID, "
+         "(SELECT COUNT(LL.ID) FROM DlpLeakLog AS LL WHERE LL.PATTERN_ID == R.PATTERN_ID) FROM DlpRules AS R, "
+         "DlpPatterns AS P WHERE R.PATTERN_ID=P.ID AND R.USER_ID=? AND PROFILE=?";
+
+       const char *query = "SELECT R.ID, R.ACTION, R.PATTERN_ID, R.NAME, R.DESCRIPTION, P.NAME, P.DESCRIPTION, R.APP_ID, "
+         "(SELECT COUNT(LL.ID) FROM DlpLeakLog AS LL WHERE LL.PATTERN_ID == R.PATTERN_ID) FROM DlpRules AS R, "
+         "DlpPatterns AS P WHERE R.PATTERN_ID=P.ID AND PROFILE=?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       if (profile == PRIV_GUARD_DLP_PROFILE_CUSTOM) {
+               res = sqlite3_prepare_v2(m_sqlHandler, queryc, -1, &m_stmt, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt, 1, userId);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+               res = sqlite3_bind_int(m_stmt, 2, profile);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+       } else {
+               res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+               TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+               // bind
+               res = sqlite3_bind_int(m_stmt, 1, profile);
+               TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+       }
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               get_custom_rule_s rule;
+               rule.id = sqlite3_column_int(m_stmt, 0);
+               rule.action = (PgDlpAction)sqlite3_column_int(m_stmt, 1);
+               rule.pattern_id = sqlite3_column_int(m_stmt, 2);
+               pg_strlcpy(rule.name, (const char *)sqlite3_column_text(m_stmt, 3), LEN_NAME);
+               if (!strlen(rule.name)) // if rule.name is empty or NULL we use the pattern.name
+                 pg_strlcpy(rule.name, (const char *)sqlite3_column_text(m_stmt, 5), LEN_NAME);
+               pg_strlcpy(rule.description, (const char *)sqlite3_column_text(m_stmt, 4), LEN_DESCRIPTION);
+               if (!strlen(rule.description)) // if rule.description is empty or NULL we use the pattern.description
+                 pg_strlcpy(rule.description, (const char *)sqlite3_column_text(m_stmt, 6), LEN_DESCRIPTION);
+               pg_strlcpy(rule.application_id, (const char *)sqlite3_column_text(m_stmt, 7), LEN_APPLICATION_ID);
+               rule.leaks_count = sqlite3_column_int(m_stmt, 9);
+               rules.push_back(rule);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgAddDlpPattern(const pattern_s &pattern)
+{
+       int res = -1;
+
+       const char *check = "SELECT ID FROM DlpPatterns WHERE PATTERN=? AND TYPE=? AND STATE!=?";
+
+       const char *insert = "INSERT OR REPLACE INTO DlpPatterns (PATTERN, NAME, DESCRIPTION, TYPE, CATEGORY_ID, STATE) "
+               "VALUES (?, ?, ?, ?, ?, ?)";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // check if we have an existing pattern / type and state != deleted
+       // if state is deleted we allow to continue, since REPLACE will replace it
+       // if no existing copy then INSERT will insert it
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, check, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_text(m_stmt, 1, pattern.pattern, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, (int)pattern.type);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, PRIV_GUARD_DLP_PATTERN_STATE_DELETED);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       if ((res = sqlite3_step(m_stmt)) == SQLITE_ROW) {
+         // rule already exists with pattern / type and state != DELETED
+         sqlite3_finalize(m_stmt);
+         m_dbMutex.unlock();
+         return PRIV_GUARD_ERROR_DB_ERROR;
+       }
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       // do the insert or replace
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, insert, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_text(m_stmt, 1, pattern.pattern, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 2, pattern.name, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_text(m_stmt, 3, pattern.description, -1, SQLITE_TRANSIENT);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_text : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 4, pattern.type);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 5, pattern.category.id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 6, PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgDeleteDlpPattern(int pattern_id)
+{
+       int res = -1;
+
+       const char *update = "UPDATE DlpPatterns SET STATE = ? WHERE ID = ? AND STATE = ?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, update, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, (int)PRIV_GUARD_DLP_PATTERN_STATE_DELETED);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 2, pattern_id);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       res = sqlite3_bind_int(m_stmt, 3, (int)PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE);
+       TryCatchResLogReturn(res == SQLITE_OK, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       res = sqlite3_step(m_stmt);
+       TryCatchResLogReturn(res == SQLITE_DONE, sqlite3_finalize(m_stmt); m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_step : %d", res);
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgForeachDlpPatterns(std::list<get_pattern_s> &patterns)
+{
+       int res = -1;
+
+       const char *query = "SELECT P.ID, P.PATTERN, P.NAME, P.DESCRIPTION, P.TYPE, P.CATEGORY_ID, P.STATE, "
+         "(SELECT COUNT(LL.ID) FROM DlpLeakLog AS LL WHERE LL.PATTERN_ID == P.ID) "
+         "FROM DlpPatterns P WHERE P.STATE !=?";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // bind
+       res = sqlite3_bind_int(m_stmt, 1, PRIV_GUARD_DLP_PATTERN_STATE_DELETED);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_bind_int : %d", res);
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+               get_pattern_s pattern;
+               pattern.id = sqlite3_column_int(m_stmt, 0);
+               pg_strlcpy(pattern.pattern, (const char *)sqlite3_column_text(m_stmt, 1), LEN_PATTERN);
+               pg_strlcpy(pattern.name, (const char *)sqlite3_column_text(m_stmt, 2), LEN_NAME);
+               pg_strlcpy(pattern.description, (const char *)sqlite3_column_text(m_stmt, 3), LEN_DESCRIPTION);
+               pattern.type = (PgDlpPatternType)sqlite3_column_int(m_stmt, 4);
+               pattern.category.id = sqlite3_column_int(m_stmt, 5);
+               if (sqlite3_column_int(m_stmt, 6) != PRIV_GUARD_DLP_PATTERN_STATE_DELETABLE) pattern.undeletable = true;
+               else pattern.undeletable = false;
+               pattern.leaks_count = sqlite3_column_int(m_stmt, 7);
+               patterns.push_back(pattern);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
+int
+PrivacyGuardDb::PgGetDlpCategories(std::list<std::string> &categories)
+{
+       int res = -1;
+       const char *query = "SELECT * FROM DlpCategories";
+
+       m_dbMutex.lock();
+
+       // initialize
+       if (m_bInitialized == false) {
+               initialize();
+       }
+       TryCatchResLogReturn(m_bInitialized == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_NOT_INITIALIZED, "Failed to initialize", res);
+
+       // open db
+       if(m_bDBOpen == false) {
+               openSqliteDB();
+       }
+       TryCatchResLogReturn(m_bDBOpen == true, m_dbMutex.unlock(), PRIV_GUARD_ERROR_IO_ERROR, "openSqliteDB : %d", res);
+
+       // prepare
+       res = sqlite3_prepare_v2(m_sqlHandler, query, -1, &m_stmt, NULL);
+       TryCatchResLogReturn(res == SQLITE_OK, m_dbMutex.unlock(), PRIV_GUARD_ERROR_DB_ERROR, "sqlite3_prepare_v2 : %d", res);
+
+       // step
+       while (sqlite3_step(m_stmt) == SQLITE_ROW) {
+         std::string str((const char *)sqlite3_column_text(m_stmt, 1), LEN_CATEGORY);
+         categories.push_back(str);
+       }
+
+       sqlite3_finalize(m_stmt);
+
+       m_dbMutex.unlock();
+
+       return PRIV_GUARD_ERROR_SUCCESS;
+}
+
 PrivacyGuardDb::PrivacyGuardDb(void)
        : m_bInitialized(false)
 {
@@ -1608,7 +3131,7 @@ PrivacyGuardDb::getInstance(void)
        std::lock_guard < std::mutex > guard(m_singletonMutex);
 
        if (m_pInstance == NULL) {
-               m_pInstance = new PrivacyGuardDb();
+               m_pInstance = new(std::nothrow) PrivacyGuardDb();
        }
 
        return m_pInstance;
index e3cfd90..d0ded11 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       SocketService.cpp
+ */
+
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -97,7 +101,7 @@ SocketService::start(void)
        res = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
        TryReturn( res >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, , "pthread_sigmask : %s", strerror_r(errno, buf, sizeof(buf)));
 
-       pthread_t mainThread;
+       pthread_t mainThread = 0;
        res = pthread_create(&mainThread, NULL, &serverThread, this);
        TryReturn( res >= 0, PRIV_GUARD_ERROR_SYSTEM_ERROR, errno = res, "pthread_create : %s", strerror_r(res, buf, sizeof(buf)));
 
@@ -179,14 +183,11 @@ SocketService::mainloop(void)
                        TryReturn( res > 0, PRIV_GUARD_ERROR_IPC_ERROR, closeConnections();, "read : %s", strerror_r(errno, buf, sizeof(buf)));
                        TryReturn( (size_t)res == sizeof(siginfo), PRIV_GUARD_ERROR_IPC_ERROR, closeConnections();, "couldn't read whole siginfo");
 
-                       if((int)siginfo.ssi_signo == m_signalToClose)
-                       {
+                       if((int)siginfo.ssi_signo == m_signalToClose) {
                                PG_LOGI("Server thread got signal to close");
                                closeConnections();
                                return PRIV_GUARD_ERROR_SUCCESS;
-                       }
-                       else
-                       {
+                       } else {
                                PG_LOGI("Got not handled signal");
                        }
                }
@@ -217,17 +218,17 @@ void*
 SocketService::connectionThread(void* pData)
 {
        pthread_detach(pthread_self());
-       std::unique_ptr<ConnectionInfo> connectionInfo (static_cast<ConnectionInfo *>(pData));
+       std::unique_ptr<ConnectionInfo> connectionInfo(static_cast<ConnectionInfo *>(pData));
        SocketService &t = *static_cast<SocketService *>(connectionInfo->pData);
 
        int ret = t.connectionService(connectionInfo->connFd);
-       if (ret < 0)
-       {
+       if (ret < 0) {
                PG_LOGE("Connection thread error");
                t.removeClientSocket(connectionInfo->connFd);
                close(connectionInfo->connFd);
                return (void*)1;
        }
+
        return (void*)0;
 }
 
index 528355b..e5cfdbc 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       main.cpp
+ */
+
 #include <glib.h>
 #include "PrivacyGuardDaemon.h"
 
@@ -34,4 +38,4 @@ main(int argc, char* argv[])
        pDaemon->shutdown();
 
        return 0;
-}
\ No newline at end of file
+}
index efd2ca2..88d37ca 100755 (executable)
  * limitations under the License. 
  */
 
+/**
+ * @file       privacy_guard_daemon.cpp
+ */
+
 #include "privacy_guard_daemon.h"
 #include "PrivacyGuardDaemon.h"
 
diff --git a/server/src/service/DlpPrivacyInfoData.cpp b/server/src/service/DlpPrivacyInfoData.cpp
new file mode 100644 (file)
index 0000000..27e6e1c
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ * @file       DlpPrivacyInfoData.cpp
+ */
+
+#include <string.h>
+
+#include <contacts.h>
+#include <wifi.h>
+
+#include "Utils.h"
+#include "DlpPrivacyInfoData.h"
+#include "PrivacyGuardDb.h"
+#include "DlpRuleChangeNotification.h"
+
+#define LEN_LOCATION     24
+
+#define CONTACTS_LIST_FOREACH(list, record)                                                                                                    \
+       bool success = (contacts_list_get_current_record_p(list, &record) == CONTACTS_ERROR_NONE);      \
+       for ( ; success;                                                                                                                                                        \
+               success = ((contacts_list_next(list) == CONTACTS_ERROR_NONE)                                                    \
+               && (contacts_list_get_current_record_p(list, &record) == CONTACTS_ERROR_NONE))                  \
+    )
+
+std::mutex DlpPrivacyInfoData::m_singletonMutex;
+DlpPrivacyInfoData *DlpPrivacyInfoData::m_pInstance = NULL;
+
+DlpPrivacyInfoData::DlpPrivacyInfoData() : m_connection(NULL), m_locmgr(NULL), m_myprofile_watch(false)
+{
+       m_last_latitude = 0;
+       m_last_longitude = 0;
+       m_owner_ibirthday = 0;
+}
+
+static inline void float2regex(double pos, char *buffer, ssize_t len)
+{
+       int i;
+
+       /*
+        * Converting float coordinate (latitude or longitude) to regexp.
+        * The following expression considers precision of 2 digits. For
+        * each coordinate reported additional values are inserted to
+        * consider approximation (terminal may be in movement).
+        *
+        * Conversion example:
+        * input  = -0.12345
+        * output = "0\.12\d{2}"
+        */
+       snprintf(buffer, len, "%+.2f\\d{2}", pos);
+
+       // At this point: -0.12\d{2}
+       // Swift integer part: ignore signal and add '\' before '.'
+       for (i = 0; i < len; i++) {
+               if (buffer[i + 1] == '.') {
+                       buffer[i] = '\\';
+                       break;
+               }
+               buffer[i] = buffer[i + 1];
+       }
+}
+
+static bool birthday2string(int date, char *buffer, ssize_t len)
+{
+       struct tm tm;
+
+       // Converting to tm structure
+       memset(&tm, 0, sizeof(tm));
+       tm.tm_year = (date / 10000) - 1900;
+       tm.tm_mon = ((date % 10000) / 100) - 1;
+       tm.tm_mday = date % 100;
+
+       // Preferred date representation for the current locale without the time
+       if (strftime(buffer, len, "%x", &tm) == 0)
+               return false;
+
+       return true;
+}
+
+void
+DlpPrivacyInfoData::networkAddressChanged(const char *ipv4, const char *ipv6, void *user_data)
+{
+       DlpPrivacyInfoData *pid = (DlpPrivacyInfoData*)user_data;
+
+       if (pid != NULL) {
+               pid->m_infoMutex.lock();
+
+               pid->m_ipv4 = ipv4;
+
+               if(DlpRuleChangeNotification::getInstance() != NULL)
+                       DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+
+               pid->m_infoMutex.unlock();
+       }
+}
+
+void
+DlpPrivacyInfoData::telephonySIMStatusChanged(telephony_h handle, telephony_noti_e noti_id, void *data, void *user_data)
+{
+       char *phoneno;
+       DlpPrivacyInfoData *pid = (DlpPrivacyInfoData*)user_data;
+       telephony_sim_state_e *state = (telephony_sim_state_e *)data;
+
+       if (pid != NULL && *state == TELEPHONY_SIM_STATE_AVAILABLE) {
+               pid->m_infoMutex.lock();
+
+               pid->m_sim_phoneno_list.clear();
+
+               for (unsigned int i = 0; i < pid->m_handle_list.count; i++) {
+                       int ret = telephony_sim_get_subscriber_number(pid->m_handle_list.handle[i], &phoneno);
+                       if (ret == TELEPHONY_ERROR_NONE && phoneno && strlen(phoneno))
+                               pid->m_sim_phoneno_list.insert(phoneno);
+               }
+
+               if(DlpRuleChangeNotification::getInstance() != NULL)
+                       DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+
+               pid->m_infoMutex.unlock();
+       }
+}
+
+void
+DlpPrivacyInfoData::myProfileChanged(const char *view_uri, void *user_data)
+{
+       DlpPrivacyInfoData *pid = (DlpPrivacyInfoData*) user_data;
+
+       pid->m_infoMutex.lock();
+
+       pid->loadMyProfile();
+
+       pid->m_infoMutex.unlock();
+
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+}
+
+void
+DlpPrivacyInfoData::positionUpdated(double latitude, double longitude, double altitude,
+                                   time_t timestamp, void *user_data)
+
+{
+       DlpPrivacyInfoData *pid = (DlpPrivacyInfoData*) user_data;
+       char location[LEN_LOCATION];
+       double lat_round;
+       double long_round;
+
+       // Last position tracking: consider 2 decimal digits only
+       lat_round = ((int)(latitude * 100.0)) / 100.0;
+       long_round = ((int)(longitude * 100.0)) / 100.0;
+
+       // Ignore/Return if position has not changed
+       if (pid->m_last_latitude == lat_round &&
+                       pid->m_last_longitude == long_round)
+               return;
+
+       pid->m_infoMutex.lock();
+
+       pid->m_last_latitude = lat_round;
+       pid->m_last_longitude = long_round;
+
+       pid->m_location_list.clear();
+
+       // For each position add two additional entries for approximation
+
+       float2regex(latitude, location, sizeof(location));
+       pid->m_location_list.push_back(location);
+
+       float2regex(longitude, location, sizeof(location));
+       pid->m_location_list.push_back(location);
+
+       // First approximation: plus 0.01
+       float2regex(latitude + 0.01, location, sizeof(location));
+       pid->m_location_list.push_back(location);
+
+       float2regex(longitude + 0.01, location, sizeof(location));
+       pid->m_location_list.push_back(location);
+
+       // Second approximation: minus 0.01
+       float2regex(latitude - 0.01, location, sizeof(location));
+       pid->m_location_list.push_back(location);
+
+       float2regex(longitude - 0.01, location, sizeof(location));
+       pid->m_location_list.push_back(location);
+
+       if(DlpRuleChangeNotification::getInstance() != NULL)
+               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+
+       pid->m_infoMutex.unlock();
+}
+
+void
+DlpPrivacyInfoData::loadMyProfile(void)
+{
+       contacts_list_h contact_list = NULL;
+       contacts_record_h record, child_record;
+       char buffer[18];
+       char *value;
+       int ret, i, count = 0, type, date;
+
+       // Remove previous entries
+       m_owner_name.clear();
+       m_owner_birthday.clear();
+       m_owner_ibirthday = 0;
+       m_owner_address_list.clear();
+       m_owner_phoneno_list.clear();
+       m_owner_email_list.clear();
+       /* Load My Profile: Owner's phone number */
+       ret = contacts_db_get_all_records(_contacts_my_profile._uri,
+                                                       0, 0, &contact_list);
+       if (ret != CONTACTS_ERROR_NONE)
+               return;
+
+       CONTACTS_LIST_FOREACH(contact_list, record) {
+               // Owner: read name
+               ret = contacts_record_get_str_p(record,
+                                               _contacts_my_profile.display_name,
+                                               &value);
+               if (ret == CONTACTS_ERROR_NONE)
+                       m_owner_name = value;
+
+               // Owner: read all phone numbers
+               ret = contacts_record_get_child_record_count(record,
+                                    _contacts_my_profile.number, &count);
+
+               if (ret != CONTACTS_ERROR_NONE)
+                       continue;
+
+               for (i = 0; i < count; i++) {
+                       ret = contacts_record_get_child_record_at_p(record,
+                                                   _contacts_my_profile.number,
+                                                   i, &child_record);
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       ret = contacts_record_get_str_p(child_record,
+                                               _contacts_person_number.number,
+                                               &value);
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       m_owner_phoneno_list.insert(value);
+               }
+
+               // Owner: birthday
+               ret = contacts_record_get_child_record_count(record,
+                                    _contacts_my_profile.event, &count);
+
+               if (ret != CONTACTS_ERROR_NONE)
+                       continue;
+
+               for (i = 0; i < count; i++) {
+                       ret = contacts_record_get_child_record_at_p(record,
+                                                   _contacts_my_profile.event,
+                                                   i, &child_record);
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       ret = contacts_record_get_int(child_record,
+                                               _contacts_event.type,
+                                               &type);
+
+                       if (ret != CONTACTS_ERROR_NONE || type != CONTACTS_EVENT_TYPE_BIRTH)
+                               continue;
+
+                       ret = contacts_record_get_int(child_record,
+                                               _contacts_event.date,
+                                               &date);
+
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       if (birthday2string(date, buffer, sizeof(buffer))) {
+                               m_owner_birthday = buffer;
+                               m_owner_ibirthday = date;
+                       }
+               }
+
+               /* Owner: read all email addresses */
+               ret = contacts_record_get_child_record_count(record,
+                                      _contacts_my_profile.email, &count);
+
+               if (ret != CONTACTS_ERROR_NONE)
+                       continue;
+
+               for (i = 0; i < count; i++) {
+                       ret = contacts_record_get_child_record_at_p(record,
+                                                   _contacts_my_profile.email,
+                                                   i, &child_record);
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       ret = contacts_record_get_str_p(child_record,
+                                               _contacts_person_email.email,
+                                               &value);
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       m_owner_email_list.insert(value);
+               }
+
+               // Owner: read all address
+               ret = contacts_record_get_child_record_count(record,
+                                    _contacts_my_profile.address, &count);
+
+               if (ret != CONTACTS_ERROR_NONE)
+                       continue;
+
+               for (i = 0; i < count; i++) {
+                       ret = contacts_record_get_child_record_at_p(record,
+                                                 _contacts_my_profile.address,
+                                               i, &child_record);
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       ret = contacts_record_get_int(child_record,
+                                             _contacts_address.type, &type);
+
+                       // Limited to HOME address
+                       if (type != CONTACTS_ADDRESS_TYPE_HOME)
+                               continue;
+
+                       ret = contacts_record_get_str_p(child_record,
+                                       _contacts_address.street, &value);
+
+                       if (ret != CONTACTS_ERROR_NONE)
+                               continue;
+
+                       if (value)
+                               m_owner_address_list.insert(value);
+               }
+       }
+
+       contacts_list_destroy(contact_list, true);
+}
+
+void
+DlpPrivacyInfoData::loadInfo(const int userId)
+{
+       char *ipv4 = NULL, *imei = NULL, *phoneno = NULL, *mac;
+       int ret;
+
+       if (m_connection && m_ipv4.empty()) {
+               ret = connection_get_ip_address(m_connection, CONNECTION_ADDRESS_FAMILY_IPV4, &ipv4);
+               if (ret == CONNECTION_ERROR_NONE) {
+                       m_ipv4 = ipv4;
+                       free(ipv4);
+               }
+       }
+
+       // Loading IMEIs, phone numbers
+       if (m_handle_list.handle == NULL && telephony_init(&m_handle_list) == TELEPHONY_ERROR_NONE) {
+               for (unsigned int i = 0; i < m_handle_list.count; i++) {
+                       ret = telephony_modem_get_imei(m_handle_list.handle[i], &imei);
+                       if (ret == TELEPHONY_ERROR_NONE && imei && strlen(imei))
+                               m_imei_list.push_back(imei);
+
+                       ret = telephony_sim_get_subscriber_number(m_handle_list.handle[i], &phoneno);
+                       if (ret == TELEPHONY_ERROR_NONE && phoneno && strlen(phoneno))
+                               m_sim_phoneno_list.insert(phoneno);
+
+                       // Tracking SIM status: Phone number may not be available after power up
+                       telephony_set_noti_cb(m_handle_list.handle[i], TELEPHONY_NOTI_SIM_STATUS,
+                                                                       telephonySIMStatusChanged, this);
+               }
+       }
+
+       // Loading Wi-Fi MAC
+       if (!strcmp(m_mac, "") && wifi_get_mac_address(&mac) == WIFI_ERROR_NONE) {
+               pg_strlcpy(m_mac, mac, LEN_MAC_ADDRESS);
+               free(mac);
+       }
+
+       // Loading emails from user ID
+       m_email_list.clear();
+       PrivacyGuardDb::getInstance()->PgGetAccountEmails(userId, m_email_list);
+
+       // Loading my profile infos
+       if (m_myprofile_watch == false) {
+               ret = contacts_connect();
+               if (ret == CONTACTS_ERROR_NONE) {
+                       loadMyProfile();
+                       m_myprofile_watch = true;
+                       contacts_db_add_changed_cb(_contacts_my_profile._uri,
+                                                       myProfileChanged, this);
+               }
+       }
+}
+
+void
+DlpPrivacyInfoData::replaceRuleTemplates(const int userId, std::list<current_rules_s> *rulesIn, std::list<current_rules_s> *rulesOut)
+{
+       std::set<std::string> ruleSet;
+
+       m_infoMutex.lock();
+
+       loadInfo(userId);
+
+       for (auto &it : *rulesIn) {
+               // replace IMEI
+               if (!strcmp(it.pattern, IMEI_TEMPLATE)) {
+                       for (const auto &it2 : m_imei_list) {
+                               pg_strlcpy(it.pattern, it2, LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+                       continue;
+               }
+
+               // My Profile: Owner name
+               if (!strcmp(it.pattern, OWNER_FULLNAME_TEMPLATE)) {
+                       if (!m_owner_name.empty()) {
+                               pg_strlcpy(it.pattern, m_owner_name.c_str(), LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+                       continue;
+               }
+
+               // My Profile: Owner birthday
+               if (!strcmp(it.pattern, OWNER_BIRTHDAY_TEMPLATE)) {
+                       if (!m_owner_birthday.empty()) {
+                               pg_strlcpy(it.pattern, m_owner_birthday.c_str(), LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+                       continue;
+               }
+
+               // My Profile: Owner address
+               if (!strcmp(it.pattern, OWNER_HOME_ADDRESS_TEMPLATE)) {
+                       for (const auto &it2 : m_owner_address_list) {
+                               pg_strlcpy(it.pattern, it2.c_str(), LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+                       continue;
+               }
+
+               // replace SIM number & My Profile number
+               if (!strcmp(it.pattern, OWNER_PHONENO_TEMPLATE)) {
+                       // Merging SIM & My profile numbers
+                       ruleSet = m_owner_phoneno_list;
+                       ruleSet.insert(m_sim_phoneno_list.begin(), m_sim_phoneno_list.end());
+
+                       for (const auto &it2 : ruleSet) {
+                               pg_strlcpy(it.pattern, it2.c_str(), LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+
+                       continue;
+               }
+
+               // replace EMAIL
+               if (!strcmp(it.pattern, EMAIL_TEMPLATE)) {
+                       // Merging Account & My profile e-mails
+                       ruleSet.clear();
+                       ruleSet = m_owner_email_list;
+                       ruleSet.insert(m_email_list.begin(), m_email_list.end());
+
+                       for (const auto &it2 : ruleSet) {
+                               pg_strlcpy(it.pattern, it2.c_str(), LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+                       continue;
+               }
+
+               // replace LOCATION
+               if (!strcmp(it.pattern, LOCATION_TEMPLATE)) {
+                       for (const auto &it2 : m_location_list) {
+                               pg_strlcpy(it.pattern, it2.c_str(), LEN_PATTERN);
+                               rulesOut->push_back(it);
+                       }
+                       continue;
+               }
+
+               // replace IP v4
+               if (!strcmp(it.pattern, IPV4_TEMPLATE))
+                       pg_strlcpy(it.pattern, m_ipv4.c_str(), LEN_PATTERN);
+
+               // replace MAC
+               else if (!strcmp(it.pattern, MAC_TEMPLATE))
+                       pg_strlcpy(it.pattern, m_mac, LEN_PATTERN);
+
+               // insert if not blank pattern
+               if (strcmp(it.pattern, ""))
+                       rulesOut->push_back(it);
+       }
+
+       m_infoMutex.unlock();
+}
+
+DlpPrivacyInfoData *
+DlpPrivacyInfoData::getInstance()
+{
+       std::lock_guard<std::mutex> guard(m_singletonMutex);
+
+       if (m_pInstance == NULL)
+               m_pInstance = new(std::nothrow) DlpPrivacyInfoData();
+
+       return m_pInstance;
+}
+
+void *
+DlpPrivacyInfoData::startLocation(void *_this)
+{
+       DlpPrivacyInfoData *dlp = (DlpPrivacyInfoData *) _this;
+
+       /*
+        * Passive location tracking: get updates when other apps use location.
+        * location_manager_start() may block for while if GPS service is not
+        * available: this procedure should be handled by a thread.
+        */
+
+       if (location_manager_create(LOCATIONS_METHOD_PASSIVE,
+                                   &(dlp->m_locmgr)) != LOCATIONS_ERROR_NONE)
+               return NULL;
+
+       location_manager_start(dlp->m_locmgr);
+       location_manager_set_position_updated_cb(dlp->m_locmgr,
+                                        dlp->positionUpdated, 10, dlp);
+
+       return NULL;
+}
+
+void
+DlpPrivacyInfoData::localeChanged(keynode_t *key, void *user_data)
+{
+       DlpPrivacyInfoData *pid = (DlpPrivacyInfoData *) user_data;
+       const char *locale;
+       char buffer[18];
+
+       // Setting program's locale based on system settings
+       locale = vconf_get_str(VCONFKEY_LANGSET);
+       if (locale)
+               setlocale(LC_ALL, locale);
+
+       if (pid->m_owner_ibirthday == 0)
+               return;
+
+       pid->m_infoMutex.lock();
+       if (birthday2string(pid->m_owner_ibirthday, buffer, sizeof(buffer))) {
+               // Same format?
+               if (strcmp(buffer, pid->m_owner_birthday.c_str()) != 0) {
+                       pid->m_owner_birthday = buffer;
+                       if(DlpRuleChangeNotification::getInstance() != NULL)
+                               DlpRuleChangeNotification::getInstance()->notifyDlpClients();
+               }
+       }
+
+       pid->m_infoMutex.unlock();
+}
+
+bool
+DlpPrivacyInfoData::start(void)
+{
+       pthread_t locmgr_thread;
+       int ret;
+       const char *locale;
+
+       // Setting program's locale based on system settings
+       locale = vconf_get_str(VCONFKEY_LANGSET);
+       if (locale)
+               setlocale(LC_ALL, locale);
+
+       vconf_notify_key_changed(VCONFKEY_LANGSET, localeChanged, this);
+
+       /*
+        * Register callback to track network address changes. Thread integrity
+        * is broken if registering on demand in the first connection.
+        */
+       ret  = connection_create(&m_connection);
+       if (ret == CONNECTION_ERROR_NONE) {
+               ret = connection_set_ip_address_changed_cb(m_connection,
+                                                  networkAddressChanged, this);
+               if (ret != CONNECTION_ERROR_NONE)
+                       PG_LOGE("Can not register network address changed callback!");
+       } else {
+               PG_LOGE("Can not track network address changes!");
+       }
+
+       // Starting location without blocking: start may block if GPS is broken
+       if (pthread_create(&locmgr_thread, NULL, startLocation, this) != 0)
+               return false;
+
+       return true;
+}
+
+void
+DlpPrivacyInfoData::stop(void)
+{
+        location_manager_stop(m_locmgr);
+}
index 280c48d..8f089c8 100755 (executable)
  *    limitations under the License.
  */
 
+/**
+ * @file       PrivacyInfoService.cpp
+ */
+
 #include "PrivacyInfoService.h"
+#include "DlpPrivacyInfoData.h"
 #include "PrivacyGuardDb.h"
 #include "Utils.h"
 
@@ -281,3 +286,331 @@ PrivacyInfoService::PgGetMainMonitorPolicy(SocketConnection* pConnector)
        pConnector->write(result);
        pConnector->write(mainMonitorPolicy);
 }
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgAddLeakLog(SocketConnection* pConnector)
+{
+       leak_log_insert_common_data_s data;
+       std::list<leak_log_insert_data_s> logList;
+
+       pConnector->read(data);
+       pConnector->read(logList);
+
+       int result = PrivacyGuardDb::getInstance()->PgAddLeakLog(data, logList);
+
+       pConnector->write(result);
+}
+
+void
+/**
+ * @callgraph
+ */
+PrivacyInfoService::PgForeachLeakLogs(SocketConnection* pConnector)
+{
+       int userId = 0;
+       std::list<leak_log_get_data_s> logList;
+
+       pConnector->read(&userId);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachLeakLogs(userId, NULL, 0, logList);
+
+       pConnector->write(result, logList);
+}
+
+void
+/**
+ * @callgraph
+ */
+PrivacyInfoService::PgForeachLeakLogsByAppName(SocketConnection* pConnector)
+{
+       int userId = 0;
+       char appName[LEN_APPLICATION_NAME];
+       std::list<leak_log_get_data_s> logList;
+
+       pConnector->read(&userId);
+       pConnector->read(appName, LEN_APPLICATION_NAME);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachLeakLogs(userId, appName, 0, logList);
+
+       pConnector->write(result, logList);
+}
+
+void
+/**
+ * @callgraph
+ */
+PrivacyInfoService::PgForeachLeakLogsByCategory(SocketConnection* pConnector)
+{
+       int userId = 0;
+       int category_id = 0;
+       std::list<leak_log_get_data_s> logList;
+
+       pConnector->read(&userId);
+       pConnector->read(&category_id);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachLeakLogs(userId, NULL, category_id, logList);
+
+       pConnector->write(result, logList);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgForeachAppLeakCount(SocketConnection* pConnector)
+{
+       int userId = 0;
+       std::list<leak_log_get_app_count_s> logList;
+
+       pConnector->read(&userId);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachAppLeakCount(userId, logList);
+
+       pConnector->write(result, logList);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgForeachCategoryLeakCount(SocketConnection* pConnector)
+{
+       int userId = 0;
+       std::list<leak_log_get_category_count_s> logList;
+
+       pConnector->read(&userId);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachCategoryLeakCount(userId, logList);
+
+       pConnector->write(result, logList);
+}
+
+/**
+ * @callgraph
+ */
+void PrivacyInfoService::PgForeachLeakLogsByTimestamp(SocketConnection* pConnector)
+{
+       int userId = 0;
+       time_t start = 0;
+       time_t end = 0;
+       pConnector->read(&userId, &start, &end);
+
+       std::list<leak_log_get_data_s> logList;
+       int result = PrivacyGuardDb::getInstance()->PgForeachLeakLogsByTimestamp(userId, start, end, logList);
+
+       pConnector->write(result, logList);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgGetLeakLogDetails(SocketConnection* pConnector)
+{
+       int userId = 0, logId = 0;
+       leak_log_get_detail_data_s logDetail;
+
+       pConnector->read(&userId, &logId);
+
+       int result = PrivacyGuardDb::getInstance()->PgGetLeakLogDetails(userId, logId, logDetail);
+
+       pConnector->write(result, (const leak_log_get_detail_data_s *)&logDetail);
+}
+
+void
+PrivacyInfoService::PgPurgeLeakLogs(SocketConnection* pConnector)
+{
+       int userId = 0;
+
+       pConnector->read(&userId);
+
+       int result = PrivacyGuardDb::getInstance()->PgPurgeLeakLogs(userId);
+
+       pConnector->write(result);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgPurgeLeakLogsByLogId(SocketConnection* pConnector)
+{
+       std::list<int> logId;
+       pConnector->read(&logId);
+
+       const int result = PrivacyGuardDb::getInstance()->PgPurgeLeakLogsByLogId(logId);
+
+       pConnector->write(result);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgGetDlpProfile(SocketConnection* pConnector)
+{
+       int userId = 0;
+       dlp_profile_s profile;
+
+       pConnector->read(&userId);
+
+       int result = PrivacyGuardDb::getInstance()->PgGetDlpProfile(userId, profile);
+
+       pConnector->write(result, (const dlp_profile_s *)&profile);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgSetDlpProfile(SocketConnection* pConnector)
+{
+       int userId = 0;
+       dlp_profile_s profile;
+
+       pConnector->read(&userId, &profile);
+
+       int result = PrivacyGuardDb::getInstance()->PgSetDlpProfile(userId, profile);
+
+       pConnector->write(result);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgGetDlpCurrentRules(SocketConnection* pConnector)
+{
+       int userId = 0;
+       char appId[LEN_PACKAGE_ID];
+       int pId = 0;
+       std::list<current_rules_s> templateRules;
+       std::list<current_rules_s> rules;
+
+       pConnector->read(&userId);
+       pConnector->read(appId, LEN_PACKAGE_ID);
+       pConnector->read(&pId);
+
+       int result = PrivacyGuardDb::getInstance()->PgGetDlpCurrentRules(userId, appId, pId, templateRules);
+
+       // replace all rule templates
+       if (result == PRIV_GUARD_ERROR_SUCCESS)
+               DlpPrivacyInfoData::getInstance()->replaceRuleTemplates(userId, &templateRules, &rules);
+
+       pConnector->write(result, rules);
+}
+
+/**
+ * @callgraph
+ */
+void
+PrivacyInfoService::PgAddDlpCustomRule(SocketConnection* pConnector)
+{
+       int userId = 0;
+       custom_rule_s rule;
+
+       pConnector->read(&userId);
+       pConnector->read(rule);
+
+       int result = PrivacyGuardDb::getInstance()->PgAddDlpCustomRule(userId, rule);
+
+       pConnector->write(result);
+}
+
+void
+PrivacyInfoService::PgUpdateDlpCustomRule(SocketConnection* pConnector)
+{
+       custom_rule_s rule;
+
+       pConnector->read(rule);
+
+       int result = PrivacyGuardDb::getInstance()->PgUpdateDlpCustomRule(rule);
+
+       pConnector->write(result);
+}
+
+void
+PrivacyInfoService::PgDeleteDlpCustomRule(SocketConnection* pConnector)
+{
+       int ruleId = 0;
+
+       pConnector->read(&ruleId);
+
+       int result = PrivacyGuardDb::getInstance()->PgDeleteDlpCustomRule(ruleId);
+
+       pConnector->write(result);
+}
+
+void
+PrivacyInfoService::PgForeachDlpCustomRules(SocketConnection* pConnector)
+{
+       int userId = 0;
+       std::list<get_custom_rule_s> rules;
+
+       pConnector->read(&userId);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachDlpCustomRules(userId, rules);
+
+       pConnector->write(result, rules);
+}
+
+void
+PrivacyInfoService::PgForeachDlpRules(SocketConnection* pConnector)
+{
+       int userId = 0, profile = 0;
+       std::list<get_custom_rule_s> rules;
+
+       pConnector->read(&userId);
+       pConnector->read(&profile);
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachDlpRules(userId, profile, rules);
+
+       pConnector->write(result, rules);
+}
+
+void
+PrivacyInfoService::PgAddDlpPattern(SocketConnection* pConnector)
+{
+       pattern_s pattern;
+
+       pConnector->read(pattern);
+
+       int result = PrivacyGuardDb::getInstance()->PgAddDlpPattern(pattern);
+
+       pConnector->write(result);
+}
+
+void
+PrivacyInfoService::PgDeleteDlpPattern(SocketConnection* pConnector)
+{
+       int pattern_id = 0;
+
+       pConnector->read(pattern_id);
+
+       int result = PrivacyGuardDb::getInstance()->PgDeleteDlpPattern(pattern_id);
+
+       pConnector->write(result);
+}
+
+void
+PrivacyInfoService::PgForeachDlpPatterns(SocketConnection* pConnector)
+{
+       std::list<get_pattern_s> patterns;
+
+       int result = PrivacyGuardDb::getInstance()->PgForeachDlpPatterns(patterns);
+
+       pConnector->write(result, patterns);
+}
+
+void
+PrivacyInfoService::PgGetDlpCategories(SocketConnection* pConnector)
+{
+       std::list<std::string> categories;
+
+       int result = PrivacyGuardDb::getInstance()->PgGetDlpCategories(categories);
+
+       pConnector->write(result, categories);
+}
old mode 100755 (executable)
new mode 100644 (file)
index f4d115d..59feed7
@@ -3,12 +3,16 @@ SET(PACKAGE_NAME tc-privacy-guard)
 PROJECT(${PACKAGE_NAME})
 
 SET(TC1_NAME tc-privacy-guard)
+SET(TC2_NAME tc-dlp)
+SET(TC3_NAME tc-dlp-performance)
 
-SET(TC1_SRCS ${TC1_NAME}.c)
+SET(TC1_SRCS ${TC1_NAME}.c ${CMAKE_SOURCE_DIR}/common/src/pg_strlcpy.c)
+SET(TC2_SRCS ${TC2_NAME}.c ${CMAKE_SOURCE_DIR}/ahocorasick/ahocorasick.c ${CMAKE_SOURCE_DIR}/ahocorasick/node.c ${CMAKE_SOURCE_DIR}/common/src/pg_strlcpy.c)
+SET(TC3_SRCS ${TC3_NAME}.c ${CMAKE_SOURCE_DIR}/common/src/pg_strlcpy.c)
 
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/client/inc)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/client/inc ${CMAKE_SOURCE_DIR}/common/inc ${CMAKE_SOURCE_DIR}/common/src)
 
-SET(requires glib-2.0 dlog)
+SET(requires glib-2.0 dlog libpcre)
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${PACKAGE_NAME} REQUIRED ${requires})
 FOREACH(flag ${${PACKAGE_NAME}_CFLAGS})
@@ -22,9 +26,16 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIC -Wall -fvisibility=hidden -D_WITH_SYSTEMD_")
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${PACKAGE_NAME_CFLAGS} -fPIE")
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+SET(PC_LDFLAGS -lpcre)
 
 ADD_EXECUTABLE(${TC1_NAME} ${TC1_SRCS})
+ADD_EXECUTABLE(${TC2_NAME} ${TC2_SRCS})
+ADD_EXECUTABLE(${TC3_NAME} ${TC3_SRCS})
 
 TARGET_LINK_LIBRARIES(${TC1_NAME} "privacy-guard-client")
+TARGET_LINK_LIBRARIES(${TC2_NAME} "privacy-guard-client")
+TARGET_LINK_LIBRARIES(${TC3_NAME} "privacy-guard-client" "rt")
 
 INSTALL(TARGETS ${TC1_NAME} DESTINATION /usr/bin)
+INSTALL(TARGETS ${TC2_NAME} DESTINATION /usr/bin)
+#INSTALL(TARGETS ${TC3_NAME} DESTINATION /usr/bin)
diff --git a/test/tc-dlp-performance.c b/test/tc-dlp-performance.c
new file mode 100644 (file)
index 0000000..3c1e614
--- /dev/null
@@ -0,0 +1,482 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <glib.h>
+#include <privacy_guard_client.h>
+#include <privacy_guard_client_internal.h>
+#include <time.h>
+#include "privacy_guard_dlp.h"
+#include <complex.h>
+
+extern void pg_strlcpy(char *dst, const char *src, size_t dstsize);
+
+#define BRIGHTNESS             0
+#define RED                    31
+#define GREEN                  32
+#define YELLOW                 33
+#define BG_BLACK               40
+
+static int fail_cnt = 0;
+static int success_cnt = 0;
+static long interval[5000];
+
+typedef struct rec {
+               char char_vec[32000];
+} RECORD;
+
+// Packet to match 6 rules: Personal Document, Birth Date, Email, Address, Full Name and PhoneNumber
+char packet_match_6rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.445544552AUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%d02/02/1972%2emailtest@test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2John Doe%220 Sunny Street%3vo"
+                                                         "1237123461234567890"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec6";
+
+// Packet to match 5 rules: Personal Document, Email, Address, Full Name and PhoneNumber
+char packet_match_5rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.445544552AUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%dfdjghskjdf%2emailtest@test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2John Doe%220 Sunny Street%3vo"
+                                                         "1237123461234567890"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec5";
+
+// Packet to match 4 rules: Email, Address, Full Name and PhoneNumber
+char packet_match_4rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.sdfvcbytuAUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%dfdjghskjdf%2emailtest@test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2John Doe%220 Sunny Street%3vo"
+                                                         "123712346"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec4";
+
+// Packet to match 3 rules: Email, Full Name and PhoneNumber
+char packet_match_3rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.sdfvcbytuAUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%dfdjghskjdf%2emailtest@test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2John Doe%25858655sf234546%3vo"
+                                                         "123712346"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec3";
+
+// Packet to match 2 rules: Email and PhoneNumber
+char packet_match_2rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.sdfvcbytuAUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%dfdjghskjdf%2emailtest@test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2dfr32r35%25858655sf234546%3vo"
+                                                         "123712346"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec2";
+
+// Packet to match 1 rules: PhoneNumber
+char packet_match_1rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.sdfvcbytuAUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%dfdjghskjdf%2emailtest-test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2dfr32r35%25858655sf234546%3vo"
+                                                         "123712346"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec1";
+
+// Packet to match 0 rules
+char packet_match_0rules[] = "GET /sync/pubmatic/csrc/7/44D1C4FE-60A-4 HTTP/1.1" \
+                                                         "Host: pr-bh.ybp.yahoo.com" \
+                                                         "Connection: keep-alive"
+                                                         "Accept: image/webp,image/*,*/*;q=0.8"
+                                                         "User-Agent: Mozilla/5.0 (Linux; Tizen 3.0;SAMSUNG"
+                                                         "TM1) AppleWebKit/537.36 (KHTML, like Gecko) Samsu"
+                                                         "ngBrowser/1.0 Chrome/47.0.2526.6 Mobile safari/53"
+                                                         "Referer: https://br.news.search.yahoo.com/search;"
+                                                         "ylt=A2KLj.sdfvcbytuAUAj16Qt.?p=353418070114639&fr"
+                                                         "=p%dfdjghskjdf%2emailtest-test.orgasdasdCm%3Apivo"
+                                                         "Chjsad%3As%2Cv%3Ai%2dfr32r35%25858655sf234546%3vo"
+                                                         "123715346"
+                                                         "Accept-Encoding: gzip, deflate"
+                                                         "Accept-Language: en-US"
+                                                         "Cookie: B=b74b8llci8lhm&b=3&s=nn; ypcdb=00d340ec0";
+
+///////////////////////////////////////////////////////////////////////////////
+// test utilities
+///////////////////////////////////////////////////////////////////////////////
+static void __change_color_to_red(void)
+{
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, RED);
+}
+
+static void __change_color_to_green(void)
+{
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, GREEN);
+}
+
+static void __change_color_to_yellow(void)
+{
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, YELLOW);
+}
+
+static void __change_color_to_origin(void)
+{
+       printf("%c[%dm", 0x1B, 0);
+}
+
+static void __start_test_executions(const char *function_name, int num_of_executions)
+{
+       __change_color_to_yellow();
+       printf("================================================================================\n");
+       printf("\t%s executed %dx \n", function_name, num_of_executions);
+       printf("================================================================================\n");
+       __change_color_to_origin();
+}
+
+static void __finish_test(void)
+{
+       __change_color_to_yellow();
+       printf("\n\n");
+       __change_color_to_origin();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Testcases
+static void __add_dlp_profile(int enabled)
+{
+       dlp_profile_s config;
+       config.enabled = enabled;
+       config.keep_log_days = 7;
+       config.profile = PRIV_GUARD_DLP_PROFILE_CUSTOM;
+
+       int res = privacy_guard_client_set_dlp_profile(getuid(), &config);
+
+       if (res != PRIV_GUARD_ERROR_SUCCESS)
+               printf("Failed to set profile: %d", res);
+
+}
+
+static bool __dlp_delete_pattern(int id, const char *pattern, const char *name, const char *description, PgDlpPatternType type, const char *category, bool undeletable, int leaks_count, void *user_data)
+{
+       privacy_guard_client_delete_dlp_pattern(id);
+       return true;
+}
+
+static void __add_dlp_rules()
+{
+       privacy_guard_client_foreach_dlp_patterns(__dlp_delete_pattern, NULL);
+
+       privacy_guard_client_add_dlp_pattern("p1",                                                      // Name
+                                                                                "desc",                                                // Description
+                                                                                "Others",                                              // Category
+                                                                                "123712346",                                   // PhoneNumber
+                                                                                PRIV_GUARD_DLP_PATTERN_STRING);// Type
+
+       privacy_guard_client_add_dlp_pattern("p2",                                                      // Name
+                                                                                "desc",                                                // Description
+                                                                                "Others",                                              // Category
+                                                                                "John Doe",                                    // Full Name
+                                                                                PRIV_GUARD_DLP_PATTERN_STRING);// Type
+
+       privacy_guard_client_add_dlp_pattern("p3",                                                      // Name
+                                                                                "desc",                                                // Description
+                                                                                "Others",                                              // Category
+                                                                                "20 Sunny Street",                             // Address
+                                                                                PRIV_GUARD_DLP_PATTERN_STRING);// Type
+
+       privacy_guard_client_add_dlp_pattern("p4",                                                      // Name
+                                                                                "desc",                                                // Description
+                                                                                "Others",                                              // Category
+                                                                                "emailtest@test.org",                  // email
+                                                                                PRIV_GUARD_DLP_PATTERN_STRING);// Type
+
+       privacy_guard_client_add_dlp_pattern("p5",                                                      // Name
+                                                                                "desc",                                                // Description
+                                                                                "Others",                                              // Category
+                                                                                "02/02/1972",                                  // birth
+                                                                                PRIV_GUARD_DLP_PATTERN_STRING);// Type
+
+       privacy_guard_client_add_dlp_pattern("p6",                                                      // Name
+                                                                                "desc",                                                // Description
+                                                                                "Others",                                              // Category
+                                                                                "1234567890",                                  // data
+                                                                                PRIV_GUARD_DLP_PATTERN_STRING);// Type
+
+       privacy_guard_client_add_dlp_custom_rule(getuid(),                                              // int user_id
+                                                                                    PRIV_GUARD_DLP_ACTION_ALLOW,       // PgDlpAction action
+                                                                                    10,                                                        // int pattern_id
+                                                                                    "phone number",                            // const char *ruleName
+                                                                                    "Test add custom rule 001",        // const char *ruleDescription
+                                                                                    "");                                                       // const char *application_id
+
+       privacy_guard_client_add_dlp_custom_rule(getuid(),                                              // int user_id
+                                                                                    PRIV_GUARD_DLP_ACTION_ALLOW,       // PgDlpAction action
+                                                                                    11,                                                        // int pattern_id
+                                                                                    "name",                                            // const char *ruleName
+                                                                                    "Test add custom rule 002",        // const char *ruleDescription
+                                                                                    "");                                                       // const char *application_id
+
+       privacy_guard_client_add_dlp_custom_rule(getuid(),                                              // int user_id
+                                                                                    PRIV_GUARD_DLP_ACTION_ALLOW,       // PgDlpAction action
+                                                                                    12,                                                        // int pattern_id
+                                                                                    "address",                                         // const char *ruleName
+                                                                                    "Test add custom rule 003",        // const char *ruleDescription
+                                                                                    "");
+
+       privacy_guard_client_add_dlp_custom_rule(getuid(),                                              // int user_id
+                                                                                        PRIV_GUARD_DLP_ACTION_ALLOW,   // PgDLPAction action
+                                                                                        13,                                                    // int pattern_id
+                                                                                        "email",                                               // const char *ruleName
+                                                                                        "Test add custom rule 004",    // const char *ruleDescription
+                                                                                        "");
+
+       privacy_guard_client_add_dlp_custom_rule(getuid(),                                              // int user_id
+                                                                                    PRIV_GUARD_DLP_ACTION_ALLOW,       // PgDlpAction action
+                                                                                    14,                                                        // int pattern_id
+                                                                                    "bith",                                            // const char *ruleName
+                                                                                    "Test add custom rule 005",        // const char *ruleDescription
+                                                                                    "");
+
+       privacy_guard_client_add_dlp_custom_rule(getuid(),                                              // int user_id
+                                                                                    PRIV_GUARD_DLP_ACTION_ALLOW,       // PgDlpAction action
+                                                                                    15,                                                        // int pattern_id
+                                                                                    "data",                                            // const char *ruleName
+                                                                                    "Test add custom rule 006",        // const char *ruleDescription
+                                                                                    "");
+}
+
+static void __test_privacy_guard_client_dlp_string_match(int number_of_executions, bool show_clock, int n_rules, int payload_multiply)
+{
+       int count = 0;
+       char *packet = NULL;
+       char *packet_to_send = NULL;
+
+       struct timespec tp_before, tp_after;
+
+       __start_test_executions(__FUNCTION__, number_of_executions);
+
+    switch (n_rules) {
+       case 0:
+               packet = packet_match_0rules;
+               break;
+               case 1:
+                       packet = packet_match_1rules;
+                       break;
+               case 2:
+                       packet = packet_match_2rules;
+                       break;
+               case 3:
+                       packet = packet_match_3rules;
+                       break;
+               case 4:
+                       packet = packet_match_4rules;
+                       break;
+               case 5:
+                       packet = packet_match_5rules;
+                       break;
+               case 6:
+                       packet = packet_match_6rules;
+                       break;
+               default:
+                       packet = packet_match_1rules;
+                       break;
+    }
+
+    packet_to_send = strdup(packet);
+       // If needs to increase payload size...
+    for (count = 1; count < payload_multiply; count++) {
+       // ...just duplicate the payload content
+       char* new_packet_to_send = malloc(strlen(packet_to_send)+strlen(packet_to_send)+1);
+
+       if (new_packet_to_send != NULL) {
+               pg_strlcpy(new_packet_to_send, packet_to_send, strlen(packet_to_send));
+               strncat(new_packet_to_send, packet_to_send, sizeof(new_packet_to_send) - strlen(new_packet_to_send) - 1);
+                       packet_to_send = strdup(new_packet_to_send);
+                       free(new_packet_to_send);
+       }
+    }
+
+    printf("Sending %d bytes\n", strlen(packet_to_send));
+
+       for (count = 0; count < number_of_executions; count++) {
+               if(show_clock) clock_gettime(CLOCK_REALTIME, &tp_before);
+               privacy_guard_dlp_check_leak("fakehost.net", packet_to_send, strlen(packet_to_send));
+               if(show_clock) clock_gettime(CLOCK_REALTIME, &tp_after);
+               if(show_clock) interval[count] = (tp_after.tv_sec - tp_before.tv_sec) * 1000000000 + tp_after.tv_nsec - tp_before.tv_nsec;
+       }
+
+       __finish_test();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Main
+//////////////////////////////////////////////////////////////////////////
+int main(int argc, char *argv[])
+{
+       int idx = 0;
+       long n_iterations = 1;
+       long n_rules = 1;
+       int payload_multiply = 1;
+       int exit = 0;
+       int show_clock = 0;
+
+       // Iterate over all arguments
+       for (idx = 1; idx < (argc); idx++) {
+
+               if (strcmp("-s", argv[idx]) == 0) {
+                       printf("Settings DLP rules\n");
+                       __add_dlp_rules();
+                       exit = 1;
+                       continue;
+               }
+
+               if (strcmp("-d", argv[idx]) == 0) {
+                       printf("Disable DLP\n");
+                       __add_dlp_profile(0);
+                       exit = 1;
+                       continue;
+               }
+
+               if (strcmp("-e", argv[idx]) == 0) {
+                       printf("Enable DLP\n");
+                       __add_dlp_profile(1);
+                       exit = 1;
+                       continue;
+               }
+
+               if (strcmp("-c", argv[idx]) == 0) {
+                       printf("SET to print clock_gettime\n");
+                       show_clock = 1;
+                       continue;
+               }
+
+               if (strcmp("-h", argv[idx]) == 0) {
+                       printf("Use tc-dlp-performance -n [number_of_interations] [-s] [-e]\n");
+                       printf("[-s] Set rules\n");
+                       printf("[-e] Enable DLP\n");
+                       printf("[-d] Disable DLP\n");
+                       printf("[-n] Enter the number of executions (<= 5000)\n");
+                       printf("[-r] Enter the number of match rules (<= 6)\n");
+                       printf("[-m] Increase payload size multiplying \"585 bytes\" by input value\n");
+                       exit = 1;
+                       continue;
+               }
+       }
+
+       if (exit)
+               return 0;
+
+       // Validate -n parameter (number of test executions)
+       for (idx = 1; idx < (argc); idx++) {
+
+               if (strcmp("-n", argv[idx]) == 0) {
+                       char *p;
+                       n_iterations = strtol(argv[idx+1], &p, 10);
+
+                       if(n_iterations > 5000) {
+                               printf("Not allow to execute more than 5000 tests\n");
+                               return -1;
+                       }
+
+                       break;
+               }
+       }
+
+       // Validate -m parameter
+       for (idx = 1; idx < (argc); idx++) {
+
+               if (strcmp("-m", argv[idx]) == 0) {
+                       char *p;
+                       payload_multiply = strtol(argv[idx+1], &p, 10);
+
+                       if(payload_multiply > 10) {
+                               printf("Invalid value for -m parameter\n");
+                               return -1;
+                       }
+
+                       break;
+               }
+       }
+
+       // Validate -r parameter (number of rules)
+       for (idx = 1; idx < (argc); idx++) {
+
+               if (strcmp("-r", argv[idx]) == 0) {
+                       char *p;
+                       n_rules = strtol(argv[idx+1], &p, 10);
+
+                       if(n_rules > 6) {
+                               printf("Not allow to execute more than 6 rules\n");
+                               return -1;
+                       }
+
+                       break;
+               }
+       }
+
+       __change_color_to_green();
+       printf("DLP String Match Test\n");
+       __change_color_to_origin();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Start Tests
+       __test_privacy_guard_client_dlp_string_match(n_iterations, show_clock, n_rules, payload_multiply);
+
+       // Print test results
+       __change_color_to_green();
+       printf("Test Complete\n");
+       printf("success : %d, ", success_cnt);
+       __change_color_to_red();
+       printf("fail : %d\n", fail_cnt);
+       __change_color_to_origin();
+
+       if (show_clock)
+               for (idx=0; idx < n_iterations; idx++)
+                       printf("req %03d:\t%ld\tns\n", idx, interval[idx]);
+
+       return 0;
+}
diff --git a/test/tc-dlp.c b/test/tc-dlp.c
new file mode 100644 (file)
index 0000000..4629bb1
--- /dev/null
@@ -0,0 +1,764 @@
+#include <stdio.h>
+#include <stdlib.h>
+//#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <privacy_guard_client.h>
+#include <privacy_guard_client_internal.h>
+#include <time.h>
+#include "privacy_guard_dlp.h"
+#include "../ahocorasick/ahocorasick.h"
+#include "../ahocorasick/node.h"
+//#include "../common/inc/DlpUtils.h"
+
+#define BRIGHTNESS             0
+#define RED                    31
+#define GREEN                  32
+#define YELLOW                 33
+#define BG_BLACK               40
+
+static int fail_cnt = 0;
+static int success_cnt = 0;
+
+//extern "C" void pg_strlcpy(char *dst, const char *src, size_t dstsize);
+
+///////////////////////////////////////////////////////////////////////////////
+// test utilities
+///////////////////////////////////////////////////////////////////////////////
+static void __change_color_to_red(void)
+{
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, RED);
+}
+
+static void __change_color_to_green(void)
+{
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, GREEN);
+}
+
+static void __change_color_to_yellow(void)
+{
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, YELLOW);
+}
+
+static void __change_color_to_origin(void)
+{
+       printf("%c[%dm", 0x1B, 0);
+}
+
+static void __start_test(const char *function_name)
+{
+       __change_color_to_yellow();
+       printf("================================================================================\n");
+       printf("\t%s\n", function_name);
+       printf("================================================================================\n");
+       __change_color_to_origin();
+}
+
+static void __finish_test(void)
+{
+       __change_color_to_yellow();
+       printf("\n\n");
+       __change_color_to_origin();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// test verfication utility
+///////////////////////////////////////////////////////////////////////////////
+static const char* __get_result_string(int ret)
+{
+       if (ret == PRIV_GUARD_ERROR_SUCCESS) {
+               return "PRIV_GUARD_ERROR_SUCCESS";
+       } else if (ret == PRIV_GUARD_ERROR_NOT_INITIALIZED) {
+               return "PRIV_GUARD_ERROR_NOT_INITIALIZED";
+       } else if (ret == PRIV_GUARD_ERROR_INVALID_PARAMETER) {
+               return "PRIV_GUARD_ERROR_INVALID_PARAMETER";
+       } else if (ret == PRIV_GUARD_ERROR_OUT_OF_MEMORY) {
+               return "PRIV_GUARD_ERROR_OUT_OF_MEMORY";
+       } else if (ret == PRIV_GUARD_ERROR_IO_ERROR) {
+               return "PRIV_GUARD_ERROR_IO_ERROR";
+       } else if (ret == PRIV_GUARD_ERROR_NO_DATA) {
+               return "PRIV_GUARD_ERROR_NO_DATA";
+       } else if (ret == PRIV_GUARD_ERROR_DB_ERROR) {
+               return "PRIV_GUARD_ERROR_DB_ERROR";
+       } else if (ret == PRIV_GUARD_ERROR_IPC_ERROR) {
+               return "PRIV_GUARD_ERROR_IPC_ERROR";
+       } else if (ret == PRIV_GUARD_ERROR_INVALID_STATE) {
+               return "PRIV_GUARD_ERROR_INVALID_STATE";
+       } else if (ret == PRIV_GUARD_ERROR_SYSTEM_ERROR) {
+               return "PRIV_GUARD_ERROR_SYSTEM_ERROR";
+       } else if (ret == PRIV_GUARD_ERROR_USER_NOT_CONSENTED) {
+               return "PRIV_GUARD_ERROR_USER_NOT_CONSENTED";
+       } else if (ret == PRIV_GUARD_ERROR_INTERNAL_ERROR) {
+               return "PRIV_GUARD_ERROR_INTERNAL_ERROR";
+       } else if (ret == PRIV_GUARD_ERROR_NOT_PERMITTED) {
+               return "PRIV_GUARD_ERROR_NOT_PERMITTED";
+       } else {
+               return "PRIV_GUARD_ERROR_UNKNOWN";
+       }
+
+       return "FAIL";
+}
+
+static void __check_result_error_code(int expected, int actual, int line)
+{
+       printf("expected result = %s, actual result = %s\n", __get_result_string(expected), __get_result_string(actual));
+
+       if (expected != actual) {
+               printf("not matched [line %d]\n", line);
+               __change_color_to_red();
+               printf("test fail\n");
+               fail_cnt++;
+       } else {
+               printf("matched [line %d]\n", line);
+               __change_color_to_green();
+               printf("test success\n");
+               success_cnt++;
+       }
+       __change_color_to_origin();
+}
+
+static bool __get_dlp_leak_logs_cb3(int id, time_t time_stamp, PgDlpAction action, const char *app_name, const char *app_icon, const char *destination, void *user_data)
+{
+       int *log_total = (int *)user_data;
+       ++(*log_total);
+       return true;
+}
+
+static bool __get_dlp_leak_logs_cb4(int id, time_t time_stamp, PgDlpAction action, const char *app_name, const char *app_icon, const char *destination, void *user_data)
+{
+       int **log_id_ptr = (int **)user_data;
+       **log_id_ptr = id;
+       ++(*log_id_ptr);
+       return true;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test Profiles
+static void __change_dlp_set_profile(PgDlpProfile profile)
+{
+       __start_test(__FUNCTION__);
+
+       dlp_profile_s config;
+       privacy_guard_client_get_dlp_profile(getuid(), &config);
+       printf("Current profile is: %d\n", config.profile);
+
+       config.profile = profile;
+
+       printf("Update profile to: %d\n", profile);
+
+       // Set new profile
+       privacy_guard_client_set_dlp_profile(getuid(), &config);
+
+       privacy_guard_client_get_dlp_profile(getuid(), &config);
+       if (config.profile == profile)
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_SUCCESS, __LINE__);
+       else
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_UNKNOWN, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test Keep Logs dates
+static int __change_dlp_get_keeplogs()
+{
+       dlp_profile_s config;
+       privacy_guard_client_get_dlp_profile(getuid(), &config);
+
+       printf("New keep days value: %d\n", config.keep_log_days);
+
+       return config.keep_log_days;
+}
+
+static void __change_dlp_set_keeplogs(int days)
+{
+       __start_test(__FUNCTION__);
+       printf("Update keep days value to: %d\n", days);
+
+       dlp_profile_s config;
+       privacy_guard_client_get_dlp_profile(getuid(), &config);
+
+       printf("Current configuration from keep days: %d\n", config.keep_log_days);
+
+       config.keep_log_days = days;
+       privacy_guard_client_set_dlp_profile(getuid(), &config);
+
+       int res = __change_dlp_get_keeplogs();
+
+       if (res == days)
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_SUCCESS, __LINE__);
+       else
+               __check_result_error_code(PRIV_GUARD_ERROR_UNKNOWN, PRIV_GUARD_ERROR_UNKNOWN, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test String Match (ahocorasick)
+static void __test_string_match()
+{
+       __start_test(__FUNCTION__);
+
+       const char *text = "there was a blue balloon dog cow there.";
+       printf("text %s\n", text);
+
+       const char *search_match[] = {"ball", "cat", "dog", "balloon", "ballet", "ballad", "bar"};
+
+       printf("Search match: ");
+       unsigned int i = 0;
+    for (i = 0; i < (sizeof (search_match) / sizeof (const char *)); i++) {
+        printf("%s ", search_match[i]);
+    }
+    printf("\n");
+
+       int res = 0;
+       ac_match *match;
+       ac_instance *ac = ahocorasick_init();
+
+       res = ahocorasick_add_string(ac, search_match[0], (void *)1);
+       if (res != 1) __check_result_error_code(1, res, __LINE__);
+
+       res = ahocorasick_add_string(ac, search_match[1], (void *)2);
+       if (res != 2) __check_result_error_code(2, res, __LINE__);
+
+       res = ahocorasick_add_string(ac, search_match[2], (void *)3);
+       if (res != 3) __check_result_error_code(3, res, __LINE__);
+
+       res = ahocorasick_add_string(ac, search_match[3], (void *)4);
+       if (res != 4) __check_result_error_code(4, res, __LINE__);
+
+       res = ahocorasick_add_string(ac, search_match[4], (void *)5);
+       if (res != 5) __check_result_error_code(5, res, __LINE__);
+
+       res = ahocorasick_add_string(ac, search_match[5], (void *)6);
+       if (res != 6) __check_result_error_code(6, res, __LINE__);
+
+       res = ahocorasick_add_string(ac, search_match[6], (void *)7);
+       if (res != 7) __check_result_error_code(7, res, __LINE__);
+
+       //dump_tree(ac->root);
+
+       ahocorasick_set_text(ac, text, strlen(text), 0);
+
+       res = 0;
+       do {
+               match = ahocorasick_find_next(ac);
+
+               if (match != NULL) {
+                       printf("got match for %p at %d len %d\n", match->user_data, match->position, match->size);
+                       res++;
+               }
+               //else
+               //      printf("no match\n");
+       } while (match != NULL);
+
+       // This test expects that 3 matches are found, if != from 3 then show an error
+       if (res == 3)
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_SUCCESS, __LINE__);
+       else
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, PRIV_GUARD_ERROR_UNKNOWN, __LINE__);
+
+       ahocorasick_free(ac);
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test Search Pattern (regex)
+/*static void __test_search_pattern()
+{
+       __start_test(__FUNCTION__);
+
+       int res = dlp_pattern_validate(PRIV_GUARD_DLP_PATTERN_REGEX, "(((");
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = dlp_pattern_validate(PRIV_GUARD_DLP_PATTERN_REGEX, "\\d{1}");
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       res = dlp_pattern_validate(PRIV_GUARD_DLP_PATTERN_STRING, "");
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = dlp_pattern_validate(PRIV_GUARD_DLP_PATTERN_STRING, "ok");
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}*/
+
+/////////////////////////////////////////////////////////////////////////
+// Test Add Pattern
+static void __test_privacy_guard_client_add_custom_pattern() {
+
+       __start_test(__FUNCTION__);
+
+       int res = privacy_guard_client_add_dlp_pattern("UT pattern",
+                                                                                                       "Dummy pattern used by UTs",
+                                                                                                       "Others",
+                                                                                                       "test",
+                                                                                                       PRIV_GUARD_DLP_PATTERN_STRING);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test for each pattern
+static bool __dlp_foreach_pattern(int id, const char *pattern, const char *name, const char *description, PgDlpPatternType type, const char *category, bool undeletable, int leaks_count, void *user_data) {
+
+       printf("  - Pattern: id=%d, %s %s %s\n", id, name, description, pattern);
+       return true;
+}
+
+static void __test_privacy_guard_client_foreach_dlp_patterns() {
+
+       __start_test(__FUNCTION__);
+
+       printf("  List patterns:\n");
+       int res = privacy_guard_client_foreach_dlp_patterns(__dlp_foreach_pattern, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test Add Rules
+static bool __dlp_get_rules_by_profile_cb(int id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id, int leaks_count, void *user_data)
+{
+       printf("  - Rule: id=%d, action=%d, pattern_id=%d, name=%s, description=%s, application_id=%s, leaks_count=%d\n", id, action, pattern_id, name, description, application_id, leaks_count);
+       return true;
+}
+
+static void __test_privacy_guard_client_get_custom_rules()
+{
+       printf("  Current custom rules:\n");
+       privacy_guard_client_foreach_dlp_rules(getuid(), PRIV_GUARD_DLP_PROFILE_CUSTOM, __dlp_get_rules_by_profile_cb, NULL);
+
+}
+
+static void __test_privacy_guard_client_add_custom_rules()
+{
+       __start_test(__FUNCTION__);
+
+       dlp_profile_s config;
+       privacy_guard_client_get_dlp_profile(getuid(), &config);
+
+       config.profile = PRIV_GUARD_DLP_PROFILE_CUSTOM;
+       privacy_guard_client_set_dlp_profile(getuid(), &config);
+
+       // List current custom rules
+       __test_privacy_guard_client_get_custom_rules();
+
+       printf("Adding a new custom rules...\n");
+
+       int res = privacy_guard_client_add_dlp_custom_rule(getuid(),                                    // int user_id
+                                                                                                          PRIV_GUARD_DLP_ACTION_ALLOW, // PgDlpAction action
+                                                                                                          2,                                                   // int pattern_id
+                                                                                                          "test001",                                   // const char *ruleName
+                                                                                                          "Test add custom rule 001",  // const char *ruleDescription
+                                                                                                          "");                                                 // const char *application_id
+
+       // List current custom rules to check if any new rule was added
+       __test_privacy_guard_client_get_custom_rules();
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Test delete rules
+static bool __delete_custom_rules(int id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id, int leaks_count, void *user_data)
+{
+       printf("  - Deleting rule id=%d, action=%d, pattern_id=%d, name=%s, description=%s, application_id=%s, leaks_count=%d\n", id, action, pattern_id, name, description, application_id, leaks_count);
+
+       privacy_guard_client_delete_dlp_custom_rule(id);
+
+       return true;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Delete rule
+static void __test_privacy_guard_client_delete_custom_rules()
+{
+       __start_test(__FUNCTION__);
+
+       // List current custom rules
+       __test_privacy_guard_client_get_custom_rules();
+
+       int res = privacy_guard_client_foreach_dlp_rules(getuid(), PRIV_GUARD_DLP_PROFILE_CUSTOM, __delete_custom_rules, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       // List current custom rules to check if rules was really removed
+       __test_privacy_guard_client_get_custom_rules();
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Delete Pattern
+static void __list_dlp_patterns()
+{
+       printf("  - List patterns:\n");
+       privacy_guard_client_foreach_dlp_patterns(__dlp_foreach_pattern, NULL);
+}
+
+static bool __dlp_delete_pattern(int id, const char *pattern, const char *name, const char *description, PgDlpPatternType type, const char *category, bool undeletable, int leaks_count, void *user_data)
+{
+       printf("    Deleting: id=%d, %s %s\n", id, name, description);
+       privacy_guard_client_delete_dlp_pattern(id);
+       return true;
+}
+
+static void __test_privacy_guard_client_delete_custom_pattern()
+{
+       __start_test(__FUNCTION__);
+
+       __list_dlp_patterns();
+
+       int res = privacy_guard_client_foreach_dlp_patterns(__dlp_delete_pattern, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __list_dlp_patterns();
+
+       __finish_test();
+}
+
+static void __test_privacy_guard_client_check_leak()
+{
+       __start_test(__FUNCTION__);
+
+       char packet[] = "123456789test123456789";
+
+       PgDlpResult res = privacy_guard_dlp_check_leak("fakehost.net", packet, strlen(packet));
+
+       __check_result_error_code(PRIV_GUARD_DLP_RESULT_ALLOW, res, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Manage Logs
+static bool __get_dlp_leak_logs_cb(int id, time_t time_stamp, PgDlpAction action, const char *app_name, const char *app_icon, const char *destination, void *user_data)
+{
+       printf("    App Name: %s,  Destination: %s\n", app_name, destination);
+
+       return true;
+}
+
+static void __test_privacy_guard_client_dlp_get_leak_logs(void)
+{
+       __start_test(__FUNCTION__);
+
+       printf("  - Logs from leaked packet:\n");
+
+       int res = privacy_guard_client_foreach_leak_logs(getuid(), __get_dlp_leak_logs_cb, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       __finish_test();
+}
+
+static bool __get_dlp_app_leak_count_cb(const char *app_name, time_t first_time_stamp, time_t last_time_stamp, const char *app_icon, int leak_count, void *user_data)
+{
+       printf("    App Name: %s,  Total: %d\n", app_name, leak_count);
+
+       return true;
+}
+
+static void __test_privacy_guard_client_dlp_get_app_leak_count(void)
+{
+       __start_test(__FUNCTION__);
+
+       printf("  - Total leak count of each application:\n");
+
+       int res = privacy_guard_client_foreach_app_leak_count(getuid(), __get_dlp_app_leak_count_cb, NULL);
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}
+
+static void __test_privacy_guard_client_purge_leak_logs_by_id(void)
+{
+       __start_test(__FUNCTION__);
+
+       /* check parameters validation */
+       int res = privacy_guard_client_purge_leak_logs_by_logid(NULL, 0);
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = privacy_guard_client_purge_leak_logs_by_logid(NULL, 0);
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       const size_t MAX_LOG_ID = 5;
+       int log_id_array[MAX_LOG_ID];
+       res = privacy_guard_client_purge_leak_logs_by_logid(log_id_array, 0);
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       /* get total number of leak logs in db */
+       size_t log_total = 0; /* total number of leak logs in db */
+       res = privacy_guard_client_foreach_leak_logs(getuid(), __get_dlp_leak_logs_cb3, &log_total);
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       size_t log_count = 0; /* number of logs to be purged */
+       if (log_total > 0 && res == PRIV_GUARD_ERROR_SUCCESS) {
+               /* select some log ids from database */
+               int* log_id = (int *)malloc(log_total * sizeof(int));
+               int* log_id_ptr = log_id;
+               res = privacy_guard_client_foreach_leak_logs(getuid(), __get_dlp_leak_logs_cb4, &log_id_ptr);
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+               if (res == PRIV_GUARD_ERROR_SUCCESS) {
+                       unsigned int i = 0;
+                       for (i = 0; i < log_total && i < MAX_LOG_ID; ++i)
+                               log_id_array[i] = log_id[i];
+                       log_count = i;
+               }
+
+               free(log_id);
+       } else {
+               /* db has no leak logs, so set some arbitrary log ids */
+               size_t i = 0;
+               for (i = 0; i < MAX_LOG_ID; ++i)
+                       log_id_array[i] = 1000 + i;
+               log_count = MAX_LOG_ID;
+       }
+
+       if (res == PRIV_GUARD_ERROR_SUCCESS) {
+               /* purge selected logs */
+               privacy_guard_client_purge_leak_logs_by_logid(log_id_array, log_count);
+               __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       }
+
+       __finish_test();
+}
+
+static void __test_privacy_guard_client_purge_leak_logs(void)
+{
+       __start_test(__FUNCTION__);
+
+       int res = privacy_guard_client_purge_leak_logs(getuid());
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       __finish_test();
+}
+
+static bool __get_dlp_category_leak_count_cb(const char *category, time_t first_time_stamp, time_t last_time_stamp, int leak_count, void *user_data)
+{
+       printf("    Leak: %s %d\n", category, leak_count);
+
+       return true;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Logs by category count
+static void __test_privacy_guard_client_dlp_get_category_leak_count(void)
+{
+       __start_test(__FUNCTION__);
+
+       printf("  - List logs by category:\n");
+
+       int res = privacy_guard_client_foreach_category_leak_count(getuid(), __get_dlp_category_leak_count_cb, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Validate pattern
+/*static void __test_privacy_guard_client_validate_privacy_guard_client_validate_pattern(void)
+{
+       __start_test(__FUNCTION__);
+
+       int res = privacy_guard_client_validate_pattern(PRIV_GUARD_DLP_PATTERN_STRING, NULL);
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = privacy_guard_client_validate_pattern((PgDlpPatternType)999, "a random string");
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = privacy_guard_client_validate_pattern(PRIV_GUARD_DLP_PATTERN_REGEX, "[0-9a-zA-Z]");
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       res = privacy_guard_client_validate_pattern(PRIV_GUARD_DLP_PATTERN_REGEX, "[0-9a-zA-Z");
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = privacy_guard_client_validate_pattern(PRIV_GUARD_DLP_PATTERN_STRING, "12345");
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       res = privacy_guard_client_validate_pattern(PRIV_GUARD_DLP_PATTERN_STRING, "1234");
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       __finish_test();
+}*/
+
+/////////////////////////////////////////////////////////////////////////
+// Logs by timestamp
+static bool __get_dlp_leak_logs_ts_cb(int id, time_t time_stamp, PgDlpAction action, const char *app_name, const char *app_icon, const char *destination, void *user_data)
+{
+       int *count = (int *)user_data;
+       printf("    %d: id=%d; time_stamp=%u\n", ++(*count), id, (unsigned int) time_stamp);
+
+       return true;
+}
+
+static void __test_privacy_guard_client_dlp_get_leak_logs_by_timestamp(void)
+{
+       __start_test(__FUNCTION__);
+
+       printf("    List log by timestamp:\n");
+
+       const time_t start = 0;
+       const time_t end = time(NULL);
+       int count = 0;
+
+       /* test validation of timestamp parameters */
+       int res = privacy_guard_client_get_leak_logs(getuid(), end, start, __get_dlp_leak_logs_ts_cb, &count);
+       __check_result_error_code(PRIV_GUARD_ERROR_INVALID_PARAMETER, res, __LINE__);
+
+       res = privacy_guard_client_get_leak_logs(getuid(), start, end, __get_dlp_leak_logs_ts_cb, &count);
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Logs details
+static bool __get_dlp_leak_logs_cb2(int id, time_t time_stamp, PgDlpAction action, const char *app_name, const char *app_icon, const char *destination, void *user_data)
+{
+       leak_log_get_detail_data_s details;
+       int res = privacy_guard_client_get_leak_log_detail(getuid(), id, &details);
+
+       printf("    Details: appId: %s, appName: %s, dest: %s\n", details.application_id, details.application_name, details.destination);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       return true;
+}
+
+static void __test_privacy_guard_client_dlp_get_leak_details_logs(void)
+{
+       __start_test(__FUNCTION__);
+
+       printf("  - List log details:\n");
+
+       int res = privacy_guard_client_foreach_leak_logs(getuid(), __get_dlp_leak_logs_cb2, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       __finish_test();
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Update custom rules
+static bool __update_first_dlp_custom_rule(int rule_id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id, int leaks_count, void *user_data)
+{
+
+       int res = privacy_guard_client_update_dlp_custom_rule(rule_id, action, pattern_id - 1, "new name xyz", "new desc abc", "new app id");
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       return false;
+}
+
+static void __test_privacy_guard_update_first_custom_rule(void)
+{
+       __start_test(__FUNCTION__);
+
+       int res = privacy_guard_client_foreach_dlp_rules(getuid(), PRIV_GUARD_DLP_PROFILE_CUSTOM, __update_first_dlp_custom_rule, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       __finish_test();
+}
+
+static bool __delete_first_dlp_custom_rule(int rule_id, PgDlpAction action, int pattern_id, const char *name, const char *description, const char *application_id, int leaks_count, void *user_data)
+{
+       int res = privacy_guard_client_delete_dlp_custom_rule(rule_id);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       return true;
+}
+
+static void __test_privacy_guard_delete_first_custom_rule(void)
+{
+       __start_test(__FUNCTION__);
+
+       int res = privacy_guard_client_foreach_dlp_rules(getuid(), PRIV_GUARD_DLP_PROFILE_CUSTOM, __delete_first_dlp_custom_rule, NULL);
+
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+       __finish_test();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Main
+//////////////////////////////////////////////////////////////////////////
+int main()
+{
+       __change_color_to_green();
+       printf("DLP Test Start\n");
+       __change_color_to_origin();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test Profiles
+       __change_dlp_set_profile(PRIV_GUARD_DLP_PROFILE_CUSTOM);
+       __change_dlp_set_profile(PRIV_GUARD_DLP_PROFILE_BASIC);
+       __change_dlp_set_profile(PRIV_GUARD_DLP_PROFILE_ADVANCED);
+       //__change_dlp_get_profile();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test Keep Logs dates
+       __change_dlp_set_keeplogs(1);
+       __change_dlp_set_keeplogs(2);
+       __change_dlp_set_keeplogs(7);
+       __change_dlp_set_keeplogs(14);
+       __change_dlp_set_keeplogs(30);
+       __change_dlp_set_keeplogs(300);
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test String Match (ahocorasick)
+       __test_string_match();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test Search Pattern (regex)
+       //__test_search_pattern();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test Add Pattern
+       __test_privacy_guard_client_add_custom_pattern();
+       __test_privacy_guard_client_foreach_dlp_patterns();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test Add Rules
+       __test_privacy_guard_client_add_custom_rules();
+       __test_privacy_guard_update_first_custom_rule();
+       __test_privacy_guard_delete_first_custom_rule();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Validate request
+       __test_privacy_guard_client_check_leak();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Test Delete Rules
+       __test_privacy_guard_client_delete_custom_rules();
+       __test_privacy_guard_client_delete_custom_pattern();
+
+       /////////////////////////////////////////////////////////////////////////
+       // Manage Logs
+       __test_privacy_guard_client_dlp_get_app_leak_count();
+       __test_privacy_guard_client_dlp_get_leak_logs();
+       __test_privacy_guard_client_dlp_get_category_leak_count();
+       __test_privacy_guard_client_dlp_get_leak_logs_by_timestamp();
+       __test_privacy_guard_client_dlp_get_leak_details_logs();
+       __test_privacy_guard_client_purge_leak_logs_by_id();
+       __test_privacy_guard_client_purge_leak_logs();
+
+       //__test_privacy_guard_client_validate_privacy_guard_client_validate_pattern();
+
+       //////////////////////////////////////////////////////////////////////////
+
+       __change_color_to_green();
+       printf("Test Complete\n");
+       printf("success : %d, ", success_cnt);
+       __change_color_to_red();
+       printf("fail : %d\n", fail_cnt);
+       __change_color_to_origin();
+
+       return 0;
+}
index 84e5380..9e11e15 100644 (file)
@@ -6,31 +6,33 @@
 #include <privacy_guard_client.h>
 #include <privacy_guard_client_internal.h>
 
-#define BRIGHTNESS     0
-#define RED            31
-#define GREEN          32
-#define YELLOW                 33
-#define BG_BLACK       40
+extern void pg_strlcpy(char *dst, const char *src, size_t dstsize);
 
-#define USER_ID_OWNER  5001
+#define BRIGHTNESS     0
+#define RED                    31
+#define GREEN          32
+#define YELLOW         33
+#define BG_BLACK       40
+
+#define USER_ID_OWNER  5001
 #define INVALID_USER_ID        -1
 
 #define LEN_FUNCTION_NAME      128
-#define LEN_PRIVACY_ID                 128
-#define LEN_PACKAGE_ID                 128
+#define LEN_PRIVACY_ID         128
+#define LEN_PACKAGE_ID         128
 #define LEN_PARAM                      128
 
 #define PRIVACY_ACCOUNT                "http://tizen.org/privacy/account"
 #define PRIVACY_BOOKMARK       "http://tizen.org/privacy/bookmark"
-#define PRIVACY_CALENDAR       "http://tizen.org/privacy/calendar"
-#define PRIVACY_CALL           "http://tizen.org/privacy/call"
+#define PRIVACY_CALENDAR       "http://tizen.org/privacy/calendar"
+#define PRIVACY_CALL           "http://tizen.org/privacy/call"
 #define PRIVACY_USERHISTORY    "http://tizen.org/privacy/userhistory"
-#define PRIVACY_CAMERA                 "http://tizen.org/privacy/camera"
-#define PRIVACY_CONTACTS       "http://tizen.org/privacy/contacts"
-#define PRIVACY_SENSOR                 "http://tizen.org/privacy/sensor"
-#define PRIVACY_LOCATION       "http://tizen.org/privacy/location"
-#define PRIVACY_MESSAGE        "http://tizen.org/privacy/message"
-#define PRIVACY_MICROPHONE     "http://tizen.org/privacy/microphone"
+#define PRIVACY_CAMERA         "http://tizen.org/privacy/camera"
+#define PRIVACY_CONTACTS       "http://tizen.org/privacy/contacts"
+#define PRIVACY_SENSOR         "http://tizen.org/privacy/sensor"
+#define PRIVACY_LOCATION       "http://tizen.org/privacy/location"
+#define PRIVACY_MESSAGE                "http://tizen.org/privacy/message"
+#define PRIVACY_MICROPHONE     "http://tizen.org/privacy/microphone"
 
 
 typedef struct {
@@ -72,22 +74,22 @@ static GList *package_list_using_sensor = NULL;
 ///////////////////////////////////////////////////////////////////////////////
 static void __change_color_to_red(void)
 {
-    printf("%c[%d;%dm", 0x1B, BRIGHTNESS, RED);
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, RED);
 }
 
 static void __change_color_to_green(void)
 {
-    printf("%c[%d;%dm", 0x1B, BRIGHTNESS, GREEN);
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, GREEN);
 }
 
 static void __change_color_to_yellow(void)
 {
-    printf("%c[%d;%dm", 0x1B, BRIGHTNESS, YELLOW);
+       printf("%c[%d;%dm", 0x1B, BRIGHTNESS, YELLOW);
 }
 
 static void __change_color_to_origin(void)
 {
-    printf("%c[%dm", 0x1B, 0);
+       printf("%c[%dm", 0x1B, 0);
 }
 
 static void __start_test(const char *function_name)
@@ -157,7 +159,7 @@ static void __check_result_error_code(int expected, int actual, int line)
 {
        printf("expected result = %s, actual result = %s\n", __get_result_string(expected), __get_result_string(actual));
 
-       if(expected != actual) {
+       if (expected != actual) {
                printf("not matched [line %d]\n", line);
                __change_color_to_red();
                printf("test fail\n");
@@ -175,7 +177,7 @@ static void __check_result_int(int expected, int actual, int line)
 {
        printf("expected result = %d, actual result = %d\n", expected, actual);
 
-       if(expected != actual) {
+       if (expected != actual) {
                printf("not matched [line %d]\n", line);
                __change_color_to_red();
                printf("test fail\n");
@@ -211,7 +213,7 @@ static void __check_result_bool(bool expected, bool actual, int line)
 {
        printf("expected result = %s, actual result = %s\n", __get_bool_string(expected), __get_bool_string(actual));
 
-       if(expected != actual) {
+       if (expected != actual) {
                printf("not matched [line %d]\n", line);
                __change_color_to_red();
                printf("test fail\n");
@@ -229,7 +231,7 @@ static void __check_pointer_not_null(const void *ptr, int line)
 {
        printf("expected result = \"NOT_NULL_POINTER\", actual result = %p\n", ptr);
 
-       if(!ptr) {
+       if (!ptr) {
                printf("null string [line %d]\n", line);
                __change_color_to_red();
                printf("test fail\n");
@@ -313,7 +315,7 @@ static bool __package_info_cb(const char *package_id, const int count, const tim
        if (strncmp(privacy_id, PRIVACY_ACCOUNT, strlen(privacy_id)) == 0) {
                node = g_list_find_custom(package_list_using_account, package_id, (GCompareFunc)strcmp);
                __check_pointer_not_null(node, __LINE__);
-       } else  if (strncmp(privacy_id, PRIVACY_BOOKMARK, strlen(privacy_id)) == 0) {
+       } else  if (strncmp(privacy_id, PRIVACY_BOOKMARK, strlen(privacy_id)) == 0) {
                node = g_list_find_custom(package_list_using_bookmark, package_id, (GCompareFunc)strcmp);
                __check_pointer_not_null(node, __LINE__);
        } else  if (strncmp(privacy_id, PRIVACY_CALENDAR, strlen(privacy_id)) == 0) {
@@ -958,12 +960,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_LOCATION, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_LOCATION, strlen(PRIVACY_LOCATION));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_LOCATION)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_LOCATION, strlen(PRIVACY_LOCATION));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -976,12 +975,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_ACCOUNT, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_ACCOUNT, strlen(PRIVACY_ACCOUNT));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_ACCOUNT)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_ACCOUNT, strlen(PRIVACY_ACCOUNT));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -994,12 +990,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_BOOKMARK, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_BOOKMARK, strlen(PRIVACY_BOOKMARK));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_BOOKMARK)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_BOOKMARK, strlen(PRIVACY_BOOKMARK));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1012,12 +1005,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_CALENDAR, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CALENDAR, strlen(PRIVACY_CALENDAR));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CALENDAR)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CALENDAR, strlen(PRIVACY_CALENDAR));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1030,12 +1020,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_CALL, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CALL, strlen(PRIVACY_CALL));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CALL)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CALL, strlen(PRIVACY_CALL));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1048,12 +1035,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_USERHISTORY, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_USERHISTORY, strlen(PRIVACY_USERHISTORY));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_USERHISTORY)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_USERHISTORY, strlen(PRIVACY_USERHISTORY));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1066,12 +1050,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_CAMERA, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CAMERA, strlen(PRIVACY_CAMERA));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CAMERA)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CAMERA, strlen(PRIVACY_CAMERA));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1084,12 +1065,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_CONTACTS, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CONTACTS, strlen(PRIVACY_CONTACTS));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CONTACTS)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CONTACTS, strlen(PRIVACY_CONTACTS));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1102,12 +1080,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_MESSAGE, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_MESSAGE, strlen(PRIVACY_MESSAGE));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_MESSAGE)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_MESSAGE, strlen(PRIVACY_MESSAGE));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1120,12 +1095,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_MICROPHONE, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_MICROPHONE, strlen(PRIVACY_MICROPHONE));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_MICROPHONE)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_MICROPHONE, strlen(PRIVACY_MICROPHONE));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1138,12 +1110,9 @@ static void __test_privacy_guard_client_update_monitor_policy_02(void)
                        res = privacy_guard_client_update_monitor_policy(USER_ID_OWNER, package_id, PRIVACY_SENSOR, off);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_SENSOR,  strlen(PRIVACY_SENSOR));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_SENSOR)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_SENSOR,  strlen(PRIVACY_SENSOR));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1207,12 +1176,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_location, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_LOCATION, strlen(PRIVACY_LOCATION));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_LOCATION)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_LOCATION, strlen(PRIVACY_LOCATION));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1223,12 +1189,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_account, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_ACCOUNT, strlen(PRIVACY_ACCOUNT));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_ACCOUNT)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_ACCOUNT, strlen(PRIVACY_ACCOUNT));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1239,12 +1202,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_bookmark, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_BOOKMARK, strlen(PRIVACY_BOOKMARK));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_BOOKMARK)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_BOOKMARK, strlen(PRIVACY_BOOKMARK));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1255,12 +1215,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_calendar, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CALENDAR, strlen(PRIVACY_CALENDAR));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CALENDAR)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CALENDAR, strlen(PRIVACY_CALENDAR));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1271,12 +1228,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_call, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CALL, strlen(PRIVACY_CALL));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CALL)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CALL, strlen(PRIVACY_CALL));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1287,12 +1241,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_userhistory, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_USERHISTORY, strlen(PRIVACY_USERHISTORY));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_USERHISTORY)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_USERHISTORY, strlen(PRIVACY_USERHISTORY));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1303,12 +1254,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_camera, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CAMERA, strlen(PRIVACY_CAMERA));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CAMERA)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CAMERA, strlen(PRIVACY_CAMERA));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1319,12 +1267,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_contacts, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_CONTACTS, strlen(PRIVACY_CONTACTS));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_CONTACTS)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_CONTACTS, strlen(PRIVACY_CONTACTS));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1335,12 +1280,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_message, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_MESSAGE, strlen(PRIVACY_MESSAGE));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_MESSAGE)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_MESSAGE, strlen(PRIVACY_MESSAGE));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1351,12 +1293,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_microphone, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_MICROPHONE, strlen(PRIVACY_MICROPHONE));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_MICROPHONE)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_MICROPHONE, strlen(PRIVACY_MICROPHONE));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1367,12 +1306,9 @@ static void __test_privacy_guard_client_foreach_monitor_policy_by_package_id_02(
                char *package_id = (char*)g_list_nth_data(package_list_using_sensor, i);
                if (package_id) {
                        memset(&data, 0x0, sizeof(TEST_DATA));
-                       strncpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
-                       data.function_name[strlen(__FUNCTION__)] = '\0';
-                       strncpy(data.privacy_id, PRIVACY_SENSOR, strlen(PRIVACY_SENSOR));
-                       strncpy(data.package_id, package_id, strlen(package_id));
-                       data.package_id[strlen(package_id)] = '\0';
-                       data.privacy_id[strlen(PRIVACY_SENSOR)] = '\0';
+                       pg_strlcpy(data.function_name, __FUNCTION__, strlen(__FUNCTION__));
+                       pg_strlcpy(data.privacy_id, PRIVACY_SENSOR, strlen(PRIVACY_SENSOR));
+                       pg_strlcpy(data.package_id, package_id, strlen(package_id));
                        res = privacy_guard_client_foreach_monitor_policy_by_package_id(USER_ID_OWNER, package_id, __monitor_policy_cb, &data);
                        __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
                }
@@ -1522,6 +1458,19 @@ static void __test_privacy_guard_client_foreach_package_info_by_privacy_id(void)
        __finish_test();
 }
 
+static void __test_privacy_guard_client_purge_leak_logs(void)
+{
+       __start_test(__FUNCTION__);
+
+       //////////////////////////////////////////////////////////////////////////
+       // positive case
+       //////////////////////////////////////////////////////////////////////////
+       int res = privacy_guard_client_purge_leak_logs(USER_ID_OWNER);
+       __check_result_error_code(PRIV_GUARD_ERROR_SUCCESS, res, __LINE__);
+
+       __finish_test();
+}
+
 int main()
 {
        __change_color_to_green();
@@ -1549,6 +1498,7 @@ int main()
        __test_privacy_guard_client_check_privacy_package_02();
        __test_privacy_guard_client_foreach_privacy_package_id();
        __test_privacy_guard_client_foreach_package_info_by_privacy_id();
+       __test_privacy_guard_client_purge_leak_logs();
        //////////////////////////////////////////////////////////////////////////
 
        __change_color_to_green();