Update change log and spec for wrt-plugins-tizen_0.4.13
[framework/web/wrt-plugins-tizen.git] / src / Filesystem / FilesystemUtils.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18
19 #include <map>
20 #include <string>
21 #include <dpl/log/log.h>
22 #include <dpl/assert.h>
23 #include <Commons/Exception.h>
24 #include "Enums.h"
25 #include "IManager.h"
26 #include <Commons/WrtAccess/WrtAccess.h>
27 #include <WidgetDB/WidgetDBMgr.h>
28 #include <iconv.h>
29 #include "FilesystemUtils.h"
30
31 using namespace WrtDeviceApis;
32 using namespace WrtDeviceApis::Commons;
33
34 namespace {
35 const std::string PATH_INVALID_COMPONENT_PARENT_DIR("..");
36 const std::string PATH_INVALID_COMPONENT_CURRENT_DIR(".");
37
38 typedef std::map<std::string, std::string> RootToPathMap;
39 typedef RootToPathMap::const_iterator RootToPathMapIterator;
40 typedef std::map<std::string, std::string> PathToRootMap;
41 typedef PathToRootMap::const_iterator PathToRootMapIterator;
42 }
43
44 namespace DeviceAPI {
45 namespace Filesystem {
46 namespace Utils{
47 const RootToPathMap& getRootToPathMap()
48 {
49         static RootToPathMap result;
50         if (result.empty()) {
51         IManager& manager = IManager::getInstance();
52                 std::map<std::string, IPathPtr> locations = manager.getStorageList();
53
54                 std::map<std::string, IPathPtr>::const_iterator it;
55
56                 for (it = locations.begin(); it != locations.end(); ++it) {
57                         result[it->first] = it->second->getFullPath();
58                 }
59         }
60         return result;
61 }
62
63 const PathToRootMap& getPathToRootMap()
64 {
65         static PathToRootMap result;
66         if (result.empty()) {
67                 IManager& manager = IManager::getInstance();
68                 std::map<std::string, IPathPtr> locations = manager.getStorageList();
69
70                 std::map<std::string, IPathPtr>::const_iterator it;
71
72                 for (it = locations.begin(); it != locations.end(); ++it) {
73                         result[it->second->getFullPath()] = it->first;
74                 }
75         }
76         return result;
77 }
78
79 IPathPtr fromVirtualPath(JSContextRef context,
80                          const std::string& arg)
81 {
82         LogDebug("arg:[" << arg << "]");
83
84         // uri path, strip file://
85         if (isUriPath(arg)) {
86                 std::string stripPath = arg.substr(strlen("file://"));
87                 LogDebug("uri absolute path" << stripPath);
88                 IPathPtr result = IPath::create(stripPath);
89                 
90                 return result;
91         }
92         
93         if (!isPathValid(arg)) {
94                 LogDebug("virtual path is invalid:[" << arg << "]");
95                 ThrowMsg(Commons::ConversionException, "Not found path component.");
96         }
97
98         std::string root;
99         std::string tail;
100         std::string::size_type separatorPosition = arg.find(IPath::getSeparator());
101         if (separatorPosition != std::string::npos) {
102                 root = arg.substr(0, separatorPosition);
103                 tail = arg.substr(separatorPosition + 1, arg.size() - 1);
104         } else {
105                 root = arg;
106         }
107
108         int widgetId = WrtAccessSingleton::Instance().getWidgetId();
109         WidgetDB::Api::IWidgetDBPtr widgetDB = WidgetDB::Api::getWidgetDB(widgetId);
110
111         RootToPathMap rootToPath = getRootToPathMap();
112         rootToPath["wgt-package"] = widgetDB->getWidgetInstallationPath();
113         rootToPath["wgt-private"] = widgetDB->getWidgetPersistentStoragePath();
114         rootToPath["wgt-private-tmp"] = widgetDB->getWidgetTemporaryStoragePath();
115         RootToPathMapIterator it = rootToPath.find(root);
116
117         if (it == rootToPath.end()) {
118                 //ThrowMsg(Commons::NotFoundException, "Location not found.");
119                 LogDebug("Allow non virtual root path " << arg);
120                 return IPath::create(arg);
121         }
122         
123         IPathPtr result = IPath::create(it->second);
124
125         if (!tail.empty()) {
126                 result->append(tail);
127         }
128
129         return result;
130 }
131
132 std::string toVirtualPath(JSContextRef context, const std::string& arg) {
133
134     int widgetId = WrtAccessSingleton::Instance().getWidgetId();
135     WidgetDB::Api::IWidgetDBPtr widgetDB =
136         WidgetDB::Api::getWidgetDB(widgetId);
137
138         PathToRootMap pathToRoot = getPathToRootMap();
139         pathToRoot[widgetDB->getWidgetInstallationPath()] = "wgt-package";
140         pathToRoot[widgetDB->getWidgetPersistentStoragePath()] = "wgt-private";
141         pathToRoot[widgetDB->getWidgetTemporaryStoragePath()] = "wgt-private-tmp";
142
143         std::string path = arg;
144         
145         std::string::size_type pos = path.size();
146         while (std::string::npos != (pos = path.rfind(IPath::getSeparator(), pos))) {
147                 PathToRootMapIterator it = pathToRoot.find(path);
148                 if (pathToRoot.end() != it) {
149                         return it->second + arg.substr(path.size());
150                 }
151                 path.erase(pos, path.size());
152         }
153         LogDebug("Allow non virtual root path");
154         
155         return arg;
156 //      ThrowMsg(Commons::ConversionException, "Path doesn't contain a valid location type.");
157 }
158
159 bool isUriPath(const std::string& path) {
160                 const char* uriPrefix = "file://";
161                 const char* stringFromPath = path.c_str();
162
163                 if (!strncmp(uriPrefix, stringFromPath, strlen(uriPrefix)) && path[strlen(uriPrefix)] == '/') {
164                         return true;
165                 }
166                 
167                 return false;
168 }
169
170 bool isPathValid(const std::string& path) {
171         static const std::string currentDirBegin(PATH_INVALID_COMPONENT_CURRENT_DIR + IPath::getSeparator());
172         static const std::string parentDirBegin(PATH_INVALID_COMPONENT_PARENT_DIR +
173                 IPath::getSeparator());
174         static const std::string currentDirMiddle(IPath::getSeparator() +
175                 PATH_INVALID_COMPONENT_CURRENT_DIR +IPath::getSeparator());
176         static const std::string parentDirMiddle(IPath::getSeparator() +
177                 PATH_INVALID_COMPONENT_PARENT_DIR +IPath::getSeparator());
178
179         if (path.find(parentDirBegin) == 0 ||
180                         path.find(currentDirBegin) == 0 ||
181                 path.find(parentDirMiddle) != std::string::npos ||
182                 path.find(currentDirMiddle) != std::string::npos) {
183                 return false;
184         }
185
186         return true;
187 }
188
189 void toUTF8String(std::string fromEncoding, const char* from, const size_t fromLength, std::string &outputString) 
190 {
191         const char *fromEncodingSet = fromEncoding.c_str();
192         char *outputBuf = NULL;
193         char *buf = NULL;
194         int ret = 0;
195         iconv_t cd;
196         size_t outputLength= 0;
197                 
198         try {
199 //              LogDebug("from " << fromEncodingSet << " to UTF8 conversion " << fromLength);
200                 
201                 cd = iconv_open("UTF-8", fromEncodingSet);
202
203                 if (cd == (iconv_t) -1) 
204                 {
205                         LogDebug("charset conversion exception iconv -1");
206                         ThrowMsg(Commons::PlatformException, "charset conversion exception");
207                 }
208
209                 if (fromLength == 0) 
210                 {
211                         LogDebug("from length 0");
212                         ThrowMsg(Commons::PlatformException, "Couldn't allocate output buffer.");
213                 }
214                 
215                 outputBuf = new char[fromLength * 4 + 1];
216                 outputLength = fromLength * 4;
217                 memset(outputBuf, 0, outputLength + 1);
218                 buf = outputBuf;
219                 
220                 
221                 ret = iconv(cd, (char**)&from, (size_t*)&fromLength, &buf, &outputLength);
222
223                 LogDebug(fromLength << " " << outputLength);
224                 
225                 if (ret < 0) 
226                 {
227                         iconv_close(cd);
228                         LogDebug("charset conversion exception ret " << ret);
229                         ThrowMsg(Commons::PlatformException, "charset conversion exception");
230                 }
231
232                 iconv_close(cd);
233                 outputString = outputBuf;
234                 
235                 if (outputBuf) 
236                         delete[] outputBuf;
237                 
238         }
239         Catch(std::bad_alloc) {
240                 LogDebug("Couldn't allocate output buffer.");
241                 ThrowMsg(Commons::PlatformException, "Couldn't allocate output buffer.");
242         }
243 }
244 }
245 }
246 }