Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_wearable / 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_dao.h>
24 #include <wrt-commons/security-origin-dao/security_origin_dao_types.h>
25 #include <orm_generator_security_origin.h>
26 #include <dpl/foreach.h>
27 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
28 #include <dpl/wrt-dao-ro/WrtDatabase.h>
29 #include <dpl/wrt-dao-ro/widget_config.h>
30 #include <dpl/wrt-dao-ro/global_config.h>
31 #include <dpl/wrt-dao-ro/common_dao_types.h>
32 #include <sys/stat.h>
33 #include <fstream>
34 #include <unistd.h>
35
36 using namespace DPL::DB::ORM;
37 using namespace DPL::DB::ORM::security_origin;
38
39 namespace SecurityOriginDB {
40 using namespace WrtDB;
41 #define SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN          Try
42
43 #define SQL_CONNECTION_EXCEPTION_HANDLER_END(message)   \
44     Catch(DPL::DB::SqlConnection::Exception::Base) {       \
45         LogError(message);                              \
46         ReThrowMsg(SecurityOriginDAO::Exception::DatabaseError, \
47                    message);                            \
48     }
49
50 // database connection
51 #define SECURITY_ORIGIN_DB_INTERNAL(tlsCommand, InternalType, interface) \
52     InternalType tlsCommand(interface);
53 #define SECURITY_ORIGIN_DB_SELECT(name, type, interface) \
54     SECURITY_ORIGIN_DB_INTERNAL(name, type::Select, interface)
55 #define SECURITY_ORIGIN_DB_INSERT(name, type, interface) \
56     SECURITY_ORIGIN_DB_INTERNAL(name, type::Insert, interface)
57 #define SECURITY_ORIGIN_DB_UPDATE(name, type, interface) \
58     SECURITY_ORIGIN_DB_INTERNAL(name, type::Update, interface)
59 #define SECURITY_ORIGIN_DB_DELETE(name, type, interface) \
60     SECURITY_ORIGIN_DB_INTERNAL(name, type::Delete, interface)
61
62 typedef DPL::DB::ORM::security_origin::SecurityOriginInfo::Row
63     SecurityOriginInfoRow;
64 typedef DPL::DB::ORM::security_origin::SecurityOriginInfo::Select::RowList
65     SecurityOriginInfoRowList;
66
67 namespace {
68 DPL::DB::SqlConnection::Flag::Option SECURITY_ORIGIN_DB_OPTION =
69     DPL::DB::SqlConnection::Flag::RW;
70 DPL::DB::SqlConnection::Flag::Type SECURITY_ORIGIN_DB_TYPE =
71     DPL::DB::SqlConnection::Flag::UseLucene;
72 const char* const SECURITY_ORIGIN_DB_NAME = ".security_origin.db";
73 const char* const SECURITY_ORIGIN_DB_SQL_PATH =
74     "/usr/share/wrt-engine/security_origin_db.sql";
75 const char* const SECURITY_DATABASE_JOURNAL_FILENAME = "-journal";
76
77 const int WEB_APPLICATION_UID = 5000;
78 const int WEB_APPLICATION_GUID = 5000;
79
80 std::string createDatabasePath(const WrtDB::TizenPkgId &pkgName)
81 {
82     std::stringstream filename;
83
84     filename << WrtDB::WidgetConfig::GetWidgetPersistentStoragePath(pkgName)
85              << "/"
86              << SECURITY_ORIGIN_DB_NAME;
87     return filename.str();
88 }
89
90 void checkDatabase(std::string databasePath)
91 {
92     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
93     {
94         if (databasePath.empty()) {
95             ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
96                      "Wrong database Path is passed");
97         }
98
99         struct stat buffer;
100         if (stat(databasePath.c_str(), &buffer) != 0) {
101             //Create fresh database
102             LogDebug("Creating database " << databasePath);
103
104             std::fstream file;
105             file.open(SECURITY_ORIGIN_DB_SQL_PATH, std::ios_base::in);
106             if (!file) {
107                 ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
108                          "Fail to get database Path");
109             }
110
111             std::stringstream ssBuffer;
112             ssBuffer << file.rdbuf();
113
114             file.close();
115
116             DPL::DB::SqlConnection con(databasePath,
117                                        SECURITY_ORIGIN_DB_TYPE,
118                                        SECURITY_ORIGIN_DB_OPTION);
119             con.ExecCommand(ssBuffer.str().c_str());
120
121             if(chown(databasePath.c_str(),
122                      WEB_APPLICATION_UID,
123                      WEB_APPLICATION_GUID) != 0)
124             {
125                 ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
126                      "Fail to change uid/guid");
127             }
128             std::string databaseJournal =
129                 databasePath + SECURITY_DATABASE_JOURNAL_FILENAME;
130             if(chown(databaseJournal.c_str(),
131                      WEB_APPLICATION_UID,
132                      WEB_APPLICATION_GUID) != 0)
133             {
134                 ThrowMsg(SecurityOriginDAO::Exception::DatabaseError,
135                      "Fail to change uid/guid");
136             }
137         }
138     }
139     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to get database Path")
140 }
141 } // namespace SecurityOriginDB
142
143 SecurityOriginDAO::SecurityOriginDAO(const WrtDB::TizenPkgId &pkgName) :
144     m_dbPath(createDatabasePath(pkgName)),
145     m_dbInterface(m_dbPath, SECURITY_ORIGIN_DB_TYPE)
146 {
147     checkDatabase(m_dbPath);
148     m_dbInterface.AttachToThread(SECURITY_ORIGIN_DB_OPTION);
149 }
150
151 SecurityOriginDAO::~SecurityOriginDAO()
152 {
153     m_dbInterface.DetachFromThread();
154 }
155
156 SecurityOriginDataList SecurityOriginDAO::getSecurityOriginDataList(void)
157 {
158     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
159     {
160         SecurityOriginDataList list;
161         SECURITY_ORIGIN_DB_SELECT(select, SecurityOriginInfo, &m_dbInterface);
162         typedef std::list<SecurityOriginInfo::Row> RowList;
163         RowList rowList = select.GetRowList();
164
165         FOREACH(it, rowList) {
166             Origin origin(it->Get_scheme(), it->Get_host(), it->Get_port());
167             list.push_back(
168                 SecurityOriginDataPtr(
169                     new SecurityOriginData(
170                         static_cast<Feature>(it->Get_feature()), origin)));
171         }
172         return list;
173     }
174     SQL_CONNECTION_EXCEPTION_HANDLER_END("Failed to get data  list")
175 }
176
177 Result SecurityOriginDAO::getResult(const SecurityOriginData &data)
178 {
179     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
180     {
181         SECURITY_ORIGIN_DB_SELECT(select, SecurityOriginInfo, &m_dbInterface);
182         Equals<SecurityOriginInfo::feature> eFeature(data.feature);
183         Equals<SecurityOriginInfo::scheme> eScheme(data.origin.scheme);
184         Equals<SecurityOriginInfo::host> eHost(data.origin.host);
185         Equals<SecurityOriginInfo::port> ePort(data.origin.port);
186         select.Where(And(And(And(eFeature, eScheme), eHost), ePort));
187         SecurityOriginInfoRowList rows = select.GetRowList();
188         if (rows.empty()) {
189             return RESULT_UNKNOWN;
190         }
191         SecurityOriginInfoRow row = rows.front();
192         return static_cast<Result>(row.Get_result());
193     }
194     SQL_CONNECTION_EXCEPTION_HANDLER_END("getResult error")
195 }
196
197 bool SecurityOriginDAO::isReadOnly(const SecurityOriginData &data)
198 {
199     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
200     {
201         SECURITY_ORIGIN_DB_SELECT(select, SecurityOriginInfo, &m_dbInterface);
202         Equals<SecurityOriginInfo::feature> eFeature(data.feature);
203         Equals<SecurityOriginInfo::scheme> eScheme(data.origin.scheme);
204         Equals<SecurityOriginInfo::host> eHost(data.origin.host);
205         Equals<SecurityOriginInfo::port> ePort(data.origin.port);
206         select.Where(And(And(And(eFeature, eScheme), eHost), ePort));
207         SecurityOriginInfoRowList rows = select.GetRowList();
208         if (rows.empty()) {
209             return RESULT_UNKNOWN;
210         }
211         SecurityOriginInfoRow row = rows.front();
212         return row.Get_readonly() ? true : false;
213     }
214     SQL_CONNECTION_EXCEPTION_HANDLER_END("isReadOnly error")
215 }
216
217 void SecurityOriginDAO::setSecurityOriginData(const SecurityOriginData &data,
218                                               const Result result,
219                                               const bool readOnly)
220 {
221     if (true == hasResult(data)) {
222         updateData(data, result, readOnly);
223     } else {
224         insertData(data, result, readOnly);
225     }
226 }
227
228 void SecurityOriginDAO::setPrivilegeSecurityOriginData(
229     const Feature feature,
230     bool isOnlyAllowedLocalOrigin)
231 {
232     //TODO: this breaks app:// scheme code -> no case for app scheme
233     Origin origin(DPL::FromUTF8String("file"),
234                   DPL::FromUTF8String(""),
235                   0);
236     if (!isOnlyAllowedLocalOrigin) {
237         origin.scheme = DPL::FromUTF8String("");
238     }
239     SecurityOriginData data(feature, origin);
240     setSecurityOriginData(data, RESULT_ALLOW_ALWAYS, true);
241 }
242
243 void SecurityOriginDAO::removeSecurityOriginData(
244     const SecurityOriginData &data)
245 {
246     if (false == hasResult(data)) {
247         // There is no data
248         return;
249     }
250
251     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
252     {
253         ScopedTransaction transaction(&m_dbInterface);
254         SECURITY_ORIGIN_DB_DELETE(del, SecurityOriginInfo, &m_dbInterface)
255         Equals<SecurityOriginInfo::feature> eFeature(data.feature);
256         Equals<SecurityOriginInfo::scheme> eScheme(data.origin.scheme);
257         Equals<SecurityOriginInfo::host> eHost(data.origin.host);
258         Equals<SecurityOriginInfo::port> ePort(data.origin.port);
259         del.Where(And(And(And(eFeature, eScheme), eHost), ePort));
260         del.Execute();
261         transaction.Commit();
262     }
263     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to remove security origin data")
264 }
265
266 void SecurityOriginDAO::removeSecurityOriginData(const Result result)
267 {
268     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
269     {
270         ScopedTransaction transaction(&m_dbInterface);
271         SECURITY_ORIGIN_DB_DELETE(del, SecurityOriginInfo, &m_dbInterface)
272         del.Where(Equals<SecurityOriginInfo::result>(result));
273         del.Execute();
274         transaction.Commit();
275     }
276     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to remove data by result")
277 }
278
279 bool SecurityOriginDAO::hasResult(const SecurityOriginData &data)
280 {
281     Result ret = getResult(data);
282     return (ret != RESULT_UNKNOWN);
283 }
284
285 void SecurityOriginDAO::insertData(const SecurityOriginData &data,
286                                    const Result result,
287                                    const bool readOnly)
288 {
289     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
290     {
291         SecurityOriginInfoRow row;
292         row.Set_feature(data.feature);
293         row.Set_scheme(data.origin.scheme);
294         row.Set_host(data.origin.host);
295         row.Set_port(data.origin.port);
296         row.Set_result(result);
297         row.Set_readonly(readOnly ? 1 : 0);
298
299         ScopedTransaction transaction(&m_dbInterface);
300         SECURITY_ORIGIN_DB_INSERT(insert, SecurityOriginInfo, &m_dbInterface);
301         insert.Values(row);
302         insert.Execute();
303         transaction.Commit();
304     }
305     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to insert")
306 }
307
308 void SecurityOriginDAO::updateData(const SecurityOriginData &data,
309                                    const Result result,
310                                    const bool readOnly)
311 {
312     SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
313     {
314         SecurityOriginInfoRow row;
315         row.Set_feature(data.feature);
316         row.Set_scheme(data.origin.scheme);
317         row.Set_host(data.origin.host);
318         row.Set_port(data.origin.port);
319         row.Set_result(result);
320         row.Set_readonly(readOnly ? 1 : 0);
321
322         ScopedTransaction transaction(&m_dbInterface);
323         SECURITY_ORIGIN_DB_UPDATE(update, SecurityOriginInfo, &m_dbInterface);
324         Equals<SecurityOriginInfo::feature> eFeature(data.feature);
325         Equals<SecurityOriginInfo::scheme> eScheme(data.origin.scheme);
326         Equals<SecurityOriginInfo::host> eHost(data.origin.host);
327         Equals<SecurityOriginInfo::port> ePort(data.origin.port);
328         update.Where(And(And(And(eFeature, eScheme), eHost), ePort));
329         update.Values(row);
330         update.Execute();
331         transaction.Commit();
332     }
333     SQL_CONNECTION_EXCEPTION_HANDLER_END("Fail to update")
334 }
335 #undef SQL_CONNECTION_EXCEPTION_HANDLER_BEGIN
336 #undef SQL_CONNECTION_EXCEPTION_HANDLER_END
337 } // namespace SecurityOriginDB