[Release] wrt-commons 0.2.115
[platform/framework/web/wrt-commons.git] / modules / localization / src / w3c_file_localization.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    w3c_file_localization.cpp
18  * @author  Lukasz Wrzosek (l.wrzosek@samsung.com)
19  * @version 1.0
20  */
21 #include <stddef.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <assert.h>
26
27 #include <dpl/localization/w3c_file_localization.h>
28
29 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
30 #include <dpl/localization/localization_utils.h>
31
32 #include <dpl/log/log.h>
33 #include <dpl/string.h>
34 #include <dpl/optional.h>
35 #include <dpl/foreach.h>
36
37 #include <LanguageTagsProvider.h>
38
39 using namespace WrtDB;
40
41 namespace {
42 const DPL::String FILE_URI_BEGIN = L"file://";
43 const DPL::String WIDGET_URI_BEGIN = L"widget://";
44 const DPL::String APP_URI_BEGIN = L"app://";
45 const DPL::String LOCALE_PREFIX = L"locales/";
46
47 DPL::Optional<std::string> GetFilePathInWidgetPackageInternal(
48     const std::string& basePath,
49     std::string filePath)
50 {
51     LogDebug("Looking for file: " << filePath << "  in: " << basePath);
52
53     const LanguageTags& ltags =
54         LanguageTagsProviderSingleton::Instance().getLanguageTags();
55
56     //Check if string isn't empty
57     if (filePath.size() == 0) {
58         return DPL::Optional<std::string>::Null;
59     }
60     //Removing preceding '/'
61     if (filePath[0] == '/') {
62         filePath.erase(0, 1);
63     }
64     // In some cases (start file localization) url has unnecessary "/" at the
65     // end
66     if (filePath[filePath.size() - 1] == '/') {
67         filePath.erase(filePath.size() - 1, 1);
68     }
69     //Check if string isn't empty
70     if (filePath.size() == 0) {
71         return DPL::Optional<std::string>::Null;
72     }
73
74     LogDebug("locales size = " << ltags.size());
75     for (LanguageTags::const_iterator it = ltags.begin();
76          it != ltags.end();
77          ++it)
78     {
79         LogDebug("Trying locale: " << *it);
80         std::string path = basePath;
81         if (path[path.size() - 1] == '/') {
82             path.erase(path.size() - 1);
83         }
84
85         if (it->empty()) {
86             path += "/" + filePath;
87         } else {
88             path += "/locales/" + DPL::ToUTF8String(*it) + "/" + filePath;
89         }
90
91         LogDebug("Trying locale: " << *it << " | " << path);
92         struct stat buf;
93         if (0 == stat(path.c_str(), &buf)) {
94             if ((buf.st_mode & S_IFMT) == S_IFREG) {
95                 path.erase(0, basePath.length());
96                 return DPL::Optional<std::string>(path);
97             }
98         }
99     }
100
101     return DPL::Optional<std::string>::Null;
102 }
103
104 DPL::Optional<DPL::String> GetFilePathInWidgetPackageInternal(
105     const DPL::String& basePath,
106     const DPL::String& filePath)
107 {
108     DPL::Optional<std::string> path =
109         GetFilePathInWidgetPackageInternal(DPL::ToUTF8String(basePath),
110                                            DPL::ToUTF8String(filePath));
111     DPL::Optional<DPL::String> dplPath;
112     if (!!path) {
113         dplPath = DPL::FromUTF8String(*path);
114     }
115     return dplPath;
116 }
117 }
118
119 namespace W3CFileLocalization {
120 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
121     DbWidgetHandle widgetHandle,
122     const DPL::String &url)
123 {
124     return getFilePathInWidgetPackageFromUrl(
125                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)),
126                url);
127 }
128
129 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
130     const WrtDB::TizenAppId &tzAppId,
131     const DPL::String &url)
132 {
133     return getFilePathInWidgetPackageFromUrl(
134                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)),
135                url);
136 }
137
138 DPL::Optional<DPL::String> getFilePathInWidgetPackageFromUrl(
139     WrtDB::WidgetDAOReadOnlyPtr dao,
140     const DPL::String &url)
141 {
142     DPL::String req = url;
143
144     DPL::String suffix;
145     DPL::String::size_type pos = req.find_first_of('#');
146     if(pos != DPL::String::npos)
147     {
148         suffix = req.substr(pos) + suffix;
149         req.resize(pos); //truncate fragment identifier
150     }
151
152     pos = req.find_first_of('?');
153     if(pos != DPL::String::npos)
154     {
155         suffix = req.substr(pos) + suffix;
156         req.resize(pos); //truncate query string
157     }
158
159     if (req.find(WIDGET_URI_BEGIN) == 0) {
160         req.erase(0, WIDGET_URI_BEGIN.length());
161     } else if (req.find(FILE_URI_BEGIN) == 0) {
162         req.erase(0, FILE_URI_BEGIN.length());
163         if (req.find(dao->getPath()) == 0) {
164             req.erase(0, dao->getPath().length());
165         }
166         if (req.find(LOCALE_PREFIX) == 0) {
167             req.erase(0, LOCALE_PREFIX.length());
168             size_t position = req.find('/');
169             // should always be >0 as correct locales path is
170             // always locales/xx/ or locales/xx-XX/
171             if (position != std::string::npos && position > 0) {
172                 req.erase(0, position + 1);
173             }
174         }
175     } else if(req.find(APP_URI_BEGIN) == 0) {
176         req.erase(0, APP_URI_BEGIN.length());
177         DPL::String id = *dao->getTizenAppId();
178         if(req.substr(0, id.size()) != id)
179         {
180             LogError("Tizen id does not match, ignoring");
181             return DPL::Optional<DPL::String>::Null;
182         }
183         req.erase(0, id.length());
184     } else {
185         LogDebug("Unknown path format, ignoring");
186         return DPL::Optional<DPL::String>::Null;
187     }
188
189     auto widgetPath = dao->getPath();
190
191     LogDebug("Required path: " << req);
192     DPL::Optional<DPL::String> found =
193         GetFilePathInWidgetPackageInternal(widgetPath, req);
194
195     if (!found) {
196         LogError("Path not found within current locale in current widget");
197         return DPL::Optional<DPL::String>::Null;
198     }
199
200     found = widgetPath + *found + suffix;
201
202     return found;
203 }
204
205 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
206     WrtDB::DbWidgetHandle widgetHandle,
207     const DPL::String& file)
208 {
209     return getFilePathInWidgetPackage(
210                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)),
211                file);
212 }
213
214 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
215     const WrtDB::TizenAppId &tzAppId,
216     const DPL::String& file)
217 {
218     return getFilePathInWidgetPackage(
219                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)),
220                file);
221 }
222
223 DPL::Optional<DPL::String> getFilePathInWidgetPackage(
224     WrtDB::WidgetDAOReadOnlyPtr dao,
225     const DPL::String& file)
226 {
227     return GetFilePathInWidgetPackageInternal(dao->getPath(), file);
228 }
229
230 DPL::OptionalString getStartFile(const WrtDB::TizenAppId & tzAppId)
231 {
232     return getStartFile(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
233 }
234
235 DPL::OptionalString getStartFile(const WrtDB::DbWidgetHandle handle)
236 {
237     return getStartFile(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(handle)));
238 }
239
240 DPL::OptionalString getStartFile(WrtDB::WidgetDAOReadOnlyPtr dao)
241 {
242     WidgetDAOReadOnly::LocalizedStartFileList locList =
243         dao->getLocalizedStartFileList();
244     WidgetDAOReadOnly::WidgetStartFileList list = dao->getStartFileList();
245     LanguageTags tagsList =
246         LanguageTagsProviderSingleton::Instance().getLanguageTags();
247
248     DPL::OptionalString defaultLoc = dao->getDefaultlocale();
249     if (!!defaultLoc) {
250         tagsList.push_back(*defaultLoc);
251     }
252
253     FOREACH(tag, tagsList)
254     {
255         FOREACH(sFile, locList)
256         {
257             if (*tag == sFile->widgetLocale) {
258                 FOREACH(it, list)
259                 {
260                     if (it->startFileId == sFile->startFileId) {
261                         return it->src;
262                     }
263                 }
264             }
265         }
266     }
267
268     return DPL::OptionalString::Null;
269 }
270
271 OptionalWidgetIcon getIcon(const WrtDB::TizenAppId & tzAppId)
272 {
273     return getIcon(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
274 }
275
276 OptionalWidgetIcon getIcon(WrtDB::DbWidgetHandle widgetHandle)
277 {
278     return getIcon(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)));
279 }
280
281 OptionalWidgetIcon getIcon(WrtDB::WidgetDAOReadOnlyPtr dao)
282 {
283     WidgetDAOReadOnly::WidgetLocalizedIconList locList =
284         dao->getLocalizedIconList();
285     WidgetDAOReadOnly::WidgetIconList list = dao->getIconList();
286     LanguageTags tagsList =
287         LanguageTagsProviderSingleton::Instance().getLanguageTags();
288
289     DPL::OptionalString defaultLoc = dao->getDefaultlocale();
290     if (!!defaultLoc) {
291         tagsList.push_back(*defaultLoc);
292     }
293
294     FOREACH(tag, tagsList)
295     {
296         FOREACH(icon, locList)
297         {
298             if (*tag == icon->widgetLocale) {
299                 FOREACH(it, list)
300                 {
301                     if (it->iconId == icon->iconId) {
302                         WidgetIcon ret;
303                         ret.src = it->iconSrc;
304                         ret.width = it->iconWidth;
305                         ret.height = it->iconHeight;
306                         return ret;
307                     }
308                 }
309             }
310         }
311     }
312
313     return OptionalWidgetIcon::Null;
314 }
315
316 WidgetIconList getValidIconsList(WrtDB::DbWidgetHandle widgetHandle)
317 {
318     return getValidIconsList(
319                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)));
320 }
321
322 WidgetIconList getValidIconsList(const WrtDB::TizenAppId &tzAppId)
323 {
324     return getValidIconsList(
325                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
326 }
327
328 WidgetIconList getValidIconsList(WrtDB::WidgetDAOReadOnlyPtr dao)
329 {
330     WidgetDAOReadOnly::WidgetIconList list = dao->getIconList();
331
332     WidgetIconList outlist;
333
334     FOREACH(it, list)
335     {
336         LogDebug(":" << it->iconSrc);
337         if (!!getFilePathInWidgetPackage(dao->getHandle(),
338                                          it->iconSrc))
339         {
340             WidgetIcon ret;
341             ret.src = it->iconSrc;
342             ret.width = it->iconWidth;
343             ret.height = it->iconHeight;
344             outlist.push_back(ret);
345         }
346     }
347     return outlist;
348 }
349
350 OptionalWidgetStartFileInfo getStartFileInfo(WrtDB::DbWidgetHandle widgetHandle)
351 {
352     return getStartFileInfo(
353                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(widgetHandle)));
354 }
355
356 OptionalWidgetStartFileInfo getStartFileInfo(
357     const WrtDB::TizenAppId &tzAppId)
358 {
359     return getStartFileInfo(
360                WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
361 }
362
363 OptionalWidgetStartFileInfo getStartFileInfo(WrtDB::WidgetDAOReadOnlyPtr dao)
364 {
365     WidgetStartFileInfo info;
366
367     WidgetDAOReadOnly::LocalizedStartFileList locList =
368         dao->getLocalizedStartFileList();
369     WidgetDAOReadOnly::WidgetStartFileList list = dao->getStartFileList();
370     const LanguageTags tagsList =
371         LanguageTagsProviderSingleton::Instance().getLanguageTags();
372
373     FOREACH(tag, tagsList)
374     {
375         FOREACH(sFile, locList)
376         {
377             if (*tag == sFile->widgetLocale) {
378                 FOREACH(it, list)
379                 {
380                     if (it->startFileId ==
381                         sFile->startFileId)
382                     {
383                         info.file = it->src;
384                         info.encoding = sFile->encoding;
385                         info.type = sFile->type;
386                         if (tag->empty()) {
387                             info.localizedPath = it->src;
388                         } else {
389                             info.localizedPath = L"locales/" + *tag + L"/";
390                             info.localizedPath += it->src;
391                         }
392                         return info;
393                     }
394                 }
395             }
396         }
397     }
398
399     return OptionalWidgetStartFileInfo::Null;
400 }
401
402 WidgetLocalizedInfo getLocalizedInfo(const WrtDB::DbWidgetHandle handle)
403 {
404     return getLocalizedInfo(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(handle)));
405 }
406
407 WidgetLocalizedInfo getLocalizedInfo(const WrtDB::TizenAppId & tzAppId)
408 {
409     return getLocalizedInfo(WidgetDAOReadOnlyPtr(new WidgetDAOReadOnly(tzAppId)));
410 }
411
412 WidgetLocalizedInfo getLocalizedInfo(WidgetDAOReadOnlyPtr dao)
413 {
414     LanguageTags languages =
415         LanguageTagsProviderSingleton::Instance().getLanguageTags();
416     DPL::OptionalString dl = dao->getDefaultlocale();
417     if (!!dl) {
418         languages.push_back(*dl);
419     }
420
421     WidgetLocalizedInfo result;
422     FOREACH(i, languages)
423     {
424         WidgetLocalizedInfo languageResult = dao->getLocalizedInfo(*i);
425
426 #define OVERWRITE_IF_NULL(FIELD) if (!result.FIELD) { \
427         result.FIELD = languageResult.FIELD; \
428 }
429
430         OVERWRITE_IF_NULL(name);
431         OVERWRITE_IF_NULL(shortName);
432         OVERWRITE_IF_NULL(description);
433         OVERWRITE_IF_NULL(license);
434         OVERWRITE_IF_NULL(licenseHref);
435
436 #undef OVERWRITE_IF_NULL
437     }
438
439     return result;
440 }
441 }