0293898ea94d1f2f55ba7de9f896b1f08a461a83
[platform/framework/web/wrt-commons.git] / modules / security_origin_dao / dao / security_origin_dao.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file    security_origin_dao.cpp
18  * @author  Jihoon Chung (jihoon.chung@samsung.com)
19  * @version 1.0
20  * @brief    This file contains the definition of security origin dao class.
21  */
22
23 #include <wrt-commons/security-origin-dao/security_origin_database.h>
24 #include <wrt-commons/security-origin-dao/security_origin_dao.h>
25 #include <wrt-commons/security-origin-dao/security_origin_dao_types.h>
26 #include <orm_generator_security_origin.h>
27 #include <dpl/foreach.h>
28 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
29 #include <dpl/wrt-dao-ro/WrtDatabase.h>
30 #include <dpl/wrt-dao-ro/widget_config.h>
31 #include <dpl/wrt-dao-ro/global_config.h>
32 #include <dpl/wrt-dao-ro/common_dao_types.h>
33 #include <sys/stat.h>
34 #include <fstream>
35 #include <unistd.h>
36
37 using namespace DPL::DB::ORM;
38 using namespace DPL::DB::ORM::security_origin;
39
40 namespace SecurityOriginDB {
41 using namespace WrtDB;
42 #define SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN          Try
43
44 #define SQL_CONNECTION_EXCEPTION_HANDLER_END(message)   \
45     Catch(DPL::DB::SqlConnection::Exception::Base) {       \
46         LogError(message);                              \
47         ReThrowMsg(SecurityOriginDAO::Exception::DatabaseError, \
48                    message);                            \
49     }
50
51 namespace {
52 DPL::DB::SqlConnection::Flag::Option SECURITY_ORIGIN_DB_OPTION =
53     DPL::DB::SqlConnection::Flag::RW;
54 DPL::DB::SqlConnection::Flag::Type SECURITY_ORIGIN_DB_TYPE =
55     DPL::DB::SqlConnection::Flag::UseLucene;
56 const char* const SECURITY_ORIGIN_DB_NAME = ".security_origin.db";
57 const char* const SECURITY_ORIGIN_DB_SQL_PATH =
58     "/usr/share/wrt-engine/security_origin_db.sql";
59 const char* const SECURITY_DATABASE_JOURNAL_FILENAME = "-journal";
60
61 const int WEB_APPLICATION_UID = 5000;
62 const int WEB_APPLICATION_GUID = 5000;
63
64 std::string createDatabasePath(const WrtDB::TizenPkgId &pkgName)
65 {
66     std::stringstream filename;
67
68     filename << WrtDB::WidgetConfig::GetWidgetPersistentStoragePath(pkgName)
69              << "/"
70              << SECURITY_ORIGIN_DB_NAME;
71     return filename.str();
72 }
73
74 void checkDatabase(std::string databasePath)
75 {
76     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
77     {
78         if (databasePath.empty()) {
79             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
80                      "Wrong database Path is passed");
81         }
82
83         struct stat buffer;
84         if (stat(databasePath.c_str(), &buffer) != 0) {
85             //Create fresh database
86             LogInfo("Creating database " << databasePath);
87
88             std::fstream file;
89             file.open(SECURITY_ORIGIN_DB_SQL_PATH, std::ios_base::in);
90             if (!file) {
91                 ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
92                          "Fail to get database Path");
93             }
94
95             std::stringstream ssBuffer;
96             ssBuffer << file.rdbuf();
97
98             file.close();
99
100             DPL::DB::SqlConnection con(databasePath,
101                                        SECURITY_ORIGIN_DB_TYPE,
102                                        SECURITY_ORIGIN_DB_OPTION);
103             con.ExecCommand(ssBuffer.str().c_str());
104         }
105
106         if(chown(databasePath.c_str(),
107                  WEB_APPLICATION_UID,
108                  WEB_APPLICATION_GUID) != 0)
109         {
110             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
111                  "Fail to change uid/guid");
112         }
113         std::string databaseJournal =
114             databasePath + SECURITY_DATABASE_JOURNAL_FILENAME;
115         if(chown(databaseJournal.c_str(),
116                  WEB_APPLICATION_UID,
117                  WEB_APPLICATION_GUID) != 0)
118         {
119             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
120                  "Fail to change uid/guid");
121         }
122     }
123     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to get database Path")
124 }
125 }
126
127 SecurityOriginDAO::SecurityOriginDAO(const WrtDB::TizenPkgId &pkgName) :
128     m_securityOriginDBPath(createDatabasePath(pkgName)),
129     m_securityOriginDBInterface(m_securityOriginDBPath, SECURITY_ORIGIN_DB_TYPE)
130 {
131     checkDatabase(m_securityOriginDBPath);
132     m_securityOriginDBInterface.AttachToThread(SECURITY_ORIGIN_DB_OPTION);
133 }
134
135 SecurityOriginDAO::~SecurityOriginDAO()
136 {
137     m_securityOriginDBInterface.DetachFromThread();
138 }
139
140 SecurityOriginDataList SecurityOriginDAO::getSecurityOriginDataList(void)
141 {
142     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
143     {
144         SecurityOriginDataList list;
145         SECURITY_ORIGIN_DB_SELECT(select,
146                                   SecurityOriginInfo,
147                                   &m_securityOriginDBInterface);
148         typedef std::list<SecurityOriginInfo::Row> RowList;
149         RowList rowList = select->GetRowList();
150
151         FOREACH(it, rowList) {
152             Origin origin(it->Get_scheme(), it->Get_host(), it->Get_port());
153             list.push_back(
154                 SecurityOriginDataPtr(
155                     new SecurityOriginData(
156                         static_cast<Feature>(it->Get_feature()), origin)));
157         }
158         return list;
159     }
160     SQL_CONNECTION_EXCEPTION_HANDLER_END("Failed to get data  list")
161 }
162
163 Result SecurityOriginDAO::getResult(
164     const SecurityOriginData &securityOriginData)
165 {
166     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
167     {
168         SECURITY_ORIGIN_DB_SELECT(select,
169                                   SecurityOriginInfo,
170                                   &m_securityOriginDBInterface);
171         select->Where(
172             And(And(And(Equals<SecurityOriginInfo::feature>(securityOriginData.
173                                                                 feature),
174                         Equals<SecurityOriginInfo::scheme>(securityOriginData.
175                                                                origin.scheme)),
176                     Equals<SecurityOriginInfo::host>(securityOriginData.origin.
177                                                          host)),
178                 Equals<SecurityOriginInfo::port>(securityOriginData.origin.port)));
179         SecurityOriginInfo::Select::RowList rows = select->GetRowList();
180
181         if (rows.empty()) {
182             return RESULT_UNKNOWN;
183         }
184         SecurityOriginInfo::Row row = rows.front();
185         return static_cast<Result>(row.Get_result());
186     }
187     SQL_CONNECTION_EXCEPTION_HANDLER_END(
188         "Failed to get result for security origin")
189 }
190
191 bool SecurityOriginDAO::isReadOnly(const SecurityOriginData &securityOriginData)
192 {
193     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
194     {
195         SECURITY_ORIGIN_DB_SELECT(select, SecurityOriginInfo, &m_securityOriginDBInterface);
196         select->Where(
197             And(And(And(Equals<SecurityOriginInfo::feature>(securityOriginData.feature),
198                         Equals<SecurityOriginInfo::scheme>(securityOriginData.origin.scheme)),
199                     Equals<SecurityOriginInfo::host>(securityOriginData.origin.host)),
200                 Equals<SecurityOriginInfo::port>(securityOriginData.origin.port)));
201         SecurityOriginInfo::Select::RowList rows = select->GetRowList();
202
203         if (rows.empty()) {
204             return RESULT_UNKNOWN;
205         }
206         SecurityOriginInfo::Row row = rows.front();
207         return row.Get_readonly() ? true : false;
208     }
209     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to get readonly property")
210 }
211
212 void SecurityOriginDAO::setSecurityOriginData(const SecurityOriginData &securityOriginData,
213                                               const Result result,
214                                               const bool readOnly)
215 {
216     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
217     {
218         ScopedTransaction transaction(&m_securityOriginDBInterface);
219         SecurityOriginInfo::Row row;
220         row.Set_feature(securityOriginData.feature);
221         row.Set_scheme(securityOriginData.origin.scheme);
222         row.Set_host(securityOriginData.origin.host);
223         row.Set_port(securityOriginData.origin.port);
224         row.Set_result(result);
225         row.Set_readonly(readOnly ? 1 : 0);
226
227         if (true == hasResult(securityOriginData)) {
228             SECURITY_ORIGIN_DB_UPDATE(update,
229                                       SecurityOriginInfo,
230                                       &m_securityOriginDBInterface);
231             update->Values(row);
232             update->Execute();
233         } else {
234             SECURITY_ORIGIN_DB_INSERT(
235                 insert,
236                 SecurityOriginInfo,
237                 &m_securityOriginDBInterface);
238             insert->Values(row);
239             insert->Execute();
240         }
241         transaction.Commit();
242     }
243     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to set security origin data")
244 }
245
246 void SecurityOriginDAO::setPrivilegeSecurityOriginData(const Feature feature,
247                                                        bool isOnlyAllowedLocalOrigin)
248 {
249     Origin origin(DPL::FromUTF8String("file"),
250                   DPL::FromUTF8String(""),
251                   0);
252     if (!isOnlyAllowedLocalOrigin) {
253         origin.scheme = DPL::FromUTF8String("");
254     }
255     SecurityOriginData data(feature, origin);
256     setSecurityOriginData(data, RESULT_ALLOW_ALWAYS, true);
257 }
258
259 void SecurityOriginDAO::removeSecurityOriginData(
260     const SecurityOriginData &securityOriginData)
261 {
262     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
263     {
264         ScopedTransaction transaction(&m_securityOriginDBInterface);
265
266         if (true == hasResult(securityOriginData)) {
267             SECURITY_ORIGIN_DB_DELETE(del,
268                                       SecurityOriginInfo,
269                                       &m_securityOriginDBInterface)
270             del->Where(
271                 And(And(And(Equals<SecurityOriginInfo::feature>(
272                                 securityOriginData.feature),
273                             Equals<SecurityOriginInfo::scheme>(
274                                 securityOriginData.origin.scheme)),
275                         Equals<SecurityOriginInfo::host>(securityOriginData.
276                                                              origin.host)),
277                     Equals<SecurityOriginInfo::port>(securityOriginData.origin.
278                                                          port)));
279             del->Execute();
280             transaction.Commit();
281         }
282     }
283     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to set security origin data")
284 }
285
286 void SecurityOriginDAO::removeSecurityOriginData(const Result result)
287 {
288     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
289     {
290         ScopedTransaction transaction(&m_securityOriginDBInterface);
291         SECURITY_ORIGIN_DB_DELETE(del,
292                                   SecurityOriginInfo,
293                                   &m_securityOriginDBInterface)
294         del->Where(Equals<SecurityOriginInfo::result>(result));
295         del->Execute();
296         transaction.Commit();
297     }
298     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to remove data by result")
299 }
300
301 bool SecurityOriginDAO::hasResult(const SecurityOriginData &securityOriginData)
302 {
303     Result res = getResult(securityOriginData);
304     return (res != RESULT_UNKNOWN);
305 }
306
307 #undef SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
308 #undef SQL_CONNECTION_EXCEPTION_HANDLER_END
309 } // namespace SecurityOriginDB