Merge "[Security] Fixed build warnings" into devel_3.0_main
[platform/framework/native/appfw.git] / src / io / FIo_RegistryCore.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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 /**
18  * @file        FIo_RegistryCore.cpp
19  * @brief       This is the implementation file for _RegistryCore class.
20  */
21
22 #include <unistd.h>
23 #include <new>
24 #include <unique_ptr.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include <FBaseInteger.h>
29 #include <FBaseDouble.h>
30 #include <FBaseFloat.h>
31 #include <FBaseUuId.h>
32 #include <FBaseByteBuffer.h>
33 #include <FBaseColIEnumerator.h>
34 #include <FBaseUtilStringTokenizer.h>
35 #include <FBaseResult.h>
36 #include <FBaseSysLog.h>
37 #include <FBaseColAllElementsDeleter.h>
38 #include <FIoFile.h>
39 #include <FIoRegistry.h>
40
41 #include <FBase_StringConverter.h>
42 #include <FBase_LocalizedNumParser.h>
43 #include <FBase_NativeError.h>
44 #include <FApp_AppInfo.h>
45 #include "FIo_FileImpl.h"
46 #include "FIo_NormalRegistry.h"
47 #include "FIo_SecureRegistry.h"
48 #include "FIo_RegistryCore.h"
49 #include "FIo_SecureIoUtil.h"
50
51 using namespace std;
52 using namespace Tizen::Base;
53 using namespace Tizen::Base::Utility;
54 using namespace Tizen::Base::Collection;
55
56 namespace Tizen { namespace Io
57 {
58
59 static const size_t _MAX_REG_OPENMODE_LENGTH = 2;
60
61 #define _REGISTRY_SECTION_MARKER_CHAR   L'#'
62 #define _REGISTRY_SECTION_VALUE_ASSIGNMENT_MARKER_CHAR L'='
63
64 class _RegistrySection
65         : public Object
66 {
67 public:
68         ~_RegistrySection(void);
69 private:
70         String __sectionName;
71         LinkedList __entryList;
72         friend class _RegistryCore;
73 };
74
75 _RegistrySection::~_RegistrySection(void)
76 {
77         __entryList.RemoveAll(true);
78 }
79
80 class _RegistryEntry
81         : public Object
82 {
83 public:
84         String entryName;
85         String entryValue;
86 };
87
88 _RegistryCore::_RegistryCore(void)
89         : _constructed(false)
90         , _read(false)
91         , _write(false)
92         , _truncate(false)
93         , _append(false)
94         , _update(false)
95         , _pBuffer(null)
96         , _length(0)
97         , __pFileImpl(null)
98 {
99 }
100
101 _RegistryCore::~_RegistryCore(void)
102 {
103         delete __pFileImpl;
104 }
105
106 bool
107 _RegistryCore::VerifyRegistryOpenMode(const char* pOpenMode)
108 {
109         if (pOpenMode == null)
110         {
111                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
112                 return false;
113         }
114
115         if (strlen(pOpenMode) > _MAX_REG_OPENMODE_LENGTH)
116         {
117                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
118                 return false;
119         }
120
121         switch (pOpenMode[0])
122         {
123         case 'r':
124                 _read = true;
125                 break;
126         case 'w':
127                 _write = true;
128                 _truncate = true;
129                 break;
130         case 'a':
131                 _write = true;
132                 _append = true;
133                 break;
134         default:
135                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
136                 return false;
137         }
138
139         switch (pOpenMode[1])
140         {
141         case '\0':
142                 break;
143         case '+':
144                 if (pOpenMode[2] == '\0')
145                 {
146                         _read = true;
147                         _write = true;
148                         break;
149                 }
150                 else
151                 {
152                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
153                         return false;
154                 }
155         default:
156                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
157                 return false;
158         }
159
160         return true;
161 }
162
163 result
164 _RegistryCore::Parse(void)
165 {
166         result r = E_SUCCESS;
167         wchar_t ch = '\0';
168         bool sectionFound = false;
169         String sectionName;
170         int length = 0;
171         unique_ptr<char[]> pEntryName(null);
172         unique_ptr<char[]> pEntryValue(null);
173         int firstTokenPos = 0;
174         String line;
175
176         if (_pBuffer == null)
177         {
178                 SysLog(NID_IO, "The buffer is empty.");
179                 return E_SUCCESS;
180         }
181
182         String inputStr = String((char*)_pBuffer);
183         StringTokenizer lineTok(inputStr, L"\n");
184
185         r = lineTok.GetNextToken(line);
186
187         while (r == E_SUCCESS)
188         {
189                 // skip empty lines
190                 if (line.GetLength() == 0)
191                 {
192                         r = lineTok.GetNextToken(line);
193                         continue;
194                 }
195
196                 // find registry section marker
197                 line.GetCharAt(0, ch);
198                 if (ch == _REGISTRY_SECTION_MARKER_CHAR)
199                 {
200                         sectionFound = true;
201
202                         // skip '#' and "\n' at the end
203                         r = line.SubString(1, line.GetLength() - 1, sectionName);
204                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
205
206                         // if End of the document follows section name without newline character.
207                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
208                         if (ch == L'\n')
209                         {
210                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\n'
211                         }
212
213                         // for compatibility check if line contains  '\r' at the end
214                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
215                         if (ch == L'\r')
216                         {
217                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\r'
218                         }
219
220                         //TODO: check if remaining data in sectionName is valid or not
221                         //after removing '#', '\n', and '\r', sectionName should contain at least 1 valid character
222                         SysTryCatch(NID_IO,
223                                            sectionName.GetLength() > 0, r = E_PARSING_FAILED, E_PARSING_FAILED,
224                                            "[E_PARSING_FAILED] Section length cannot be <2.");
225
226                         unique_ptr<char[]> pSectionName(_StringConverter::CopyToCharArrayN(sectionName));
227                         SysTryCatch(NID_IO, pSectionName != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
228                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
229
230                         if (!_RegistryCore::CheckSectionName(pSectionName.get()))
231                         {
232                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
233                                                    "[E_PARSING_FAILED] Section name could not be parsed.");
234                         }
235
236                         r = _RegistryCore::AddSection(_sectionList, sectionName);
237                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
238                 }
239                 else    // not a section.. but may belongs to a section (entry)
240                 {
241                         // ignores blank lines
242                         line.GetCharAt(0, ch);
243                         if ((ch == L'\n') || (ch == L'\r'))
244                         {
245                                 r = lineTok.GetNextToken(line);
246                                 continue;
247                         }
248
249                         //TODO
250                         // Need to check for tabs, spaces in the beginning of each line
251
252                         // if no section found till now.. ignore
253                         if (sectionFound == false)
254                         {
255                                 r = lineTok.GetNextToken(line);
256                                 continue;
257                         }
258
259                         // if End of the document follows entry value without newline character.
260                         line.GetCharAt(line.GetLength() - 1, ch);
261                         if (ch == L'\n')
262                         {
263                                 line.SetLength(line.GetLength() - 1); //Remove '\n'
264                         }
265
266                         line.GetCharAt(line.GetLength() - 1, ch);
267                         if (ch == L'\r')
268                         {
269                                 line.SetLength(line.GetLength() - 1); //Remove '\r'
270                         }
271
272                         String entryName("");
273                         String entryVal("");
274
275                         // we will have sectionitem=value (or) sectionitem= (or) sectionitem
276                         // as our string. Break this into entry and value
277                         StringTokenizer strTok(line, L"=");
278
279                         // extract entry name
280                         if (strTok.HasMoreTokens())
281                         {
282                                 line.IndexOf(L'=', 0, firstTokenPos); // position of first occurance of '=' in a line
283                                 if (firstTokenPos == 0)
284                                 {
285                                         // entryName should not be empty. i.e., "=value"  or just '=' is invalid case
286                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
287                                                            "[E_PARSING_FAILED] Entry name cannot be empty.");
288                                 }
289                                 else
290                                 {
291                                         strTok.GetNextToken(entryName);
292                                 }
293                         }
294                         else // missing '=' in  entry line or entry line does not seem to contain "xxx=xxx" format
295                         {
296                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED, "[E_PARSING_FAILED] invalid entry Line found.");
297                         }
298
299                         // check if entry name contains invalid chars
300                         pEntryName.reset(_StringConverter::CopyToCharArrayN(entryName));
301                         SysTryCatch(NID_IO, pEntryName, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
302                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
303
304                         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
305                         {
306                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
307                                                    "[E_PARSING_FAILED] Entry name could not be parsed.");
308                         }
309
310                         line.SubString(firstTokenPos + 1, entryVal); // extract entry value
311
312                         // check if entry value contains invalid chars
313                         pEntryValue.reset(_StringConverter::CopyToCharArrayN(entryVal));
314                         SysTryCatch(NID_IO, pEntryValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
315                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
316
317                         length = strlen(pEntryValue.get());
318                         if (length > 0)
319                         {
320                                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
321                                 {
322                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
323                                                            "[E_PARSING_FAILED] Entry value could not be parsed.");
324                                 }
325                         }
326
327                         // add the entry and value
328                         r = _RegistryCore::AddValue(_sectionList, sectionName, entryName, entryVal);
329                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
330                 }
331                 r = lineTok.GetNextToken(line);
332         } // while()
333
334         if (r == E_OUT_OF_RANGE)
335         {
336                 r = E_SUCCESS;
337         }
338
339         // fall through
340 CATCH:
341
342         if (r == E_PARSING_FAILED && Tizen::App::_AppInfo::IsOspCompat() == false)
343         {
344                 r = E_INVALID_FORMAT;
345         }
346
347         SysLog(NID_IO, "[%s] exception occurred.", GetErrorMessage(r));
348         return r;
349 }
350
351 result
352 _RegistryCore::Load(const String& regPath, const char* pOpenMode)
353 {
354         result r = E_SUCCESS;
355         delete[] _pBuffer; //clear existing buffer
356         _pBuffer = null;
357         _length = 0;
358
359         // open registry file
360         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl());
361         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
362
363         r = pFileImpl->Construct(regPath, pOpenMode, null);
364         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
365
366         // reset the section list to be sure that its empty
367         _sectionList.RemoveAll(true);
368
369         if (_truncate == false)
370         {
371                 // load the registry file
372                 r = pFileImpl->ReadN((char**)&_pBuffer, _length);
373                 if (_length > 0)
374                 {
375                         _length--;
376                 }
377         }
378
379         __pFileImpl = pFileImpl.release();
380
381         return r;
382 }
383
384 result
385 _RegistryCore::AddSection(const String& sectionName)
386 {
387         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
388
389         result r = E_SUCCESS;
390         bool sectionFound = false;
391
392         // Get section information
393         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
394         if (pEnum == null)
395         {
396                 return GetLastResult();
397         }
398
399         while (pEnum->MoveNext() == E_SUCCESS)
400         {
401                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
402                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
403                                    GetErrorMessage(GetLastResult()));
404
405                 if (pRegSection->__sectionName == sectionName)
406                 {
407                         sectionFound = true;
408                         break;
409                 }
410         }
411
412         if (sectionFound == true)
413         {
414                 return E_SECTION_ALREADY_EXIST;
415         }
416
417         // create a key with section name
418         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
419         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
420                            "The memory is insufficient.");
421
422         pRegSection->__sectionName = sectionName;
423
424         // add new section and section-entry map
425         r = _sectionList.Add(*(pRegSection.release()));
426         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
427
428         _update = true;
429         return E_SUCCESS;
430 }
431
432 result
433 _RegistryCore::RemoveSection(const String& sectionName)
434 {
435         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
436
437         result r = E_SUCCESS;
438         _RegistrySection* pRegSection = null;
439         bool sectionFound = false;
440
441         if (_sectionList.GetCount() == 0)
442         {
443                 return E_SECTION_NOT_FOUND;
444         }
445
446         // Get section information
447         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
448         if (pEnum == null)
449         {
450                 return GetLastResult();
451         }
452
453         while (pEnum->MoveNext() == E_SUCCESS)
454         {
455                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
456                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagating.",
457                                    GetErrorMessage(GetLastResult()));
458
459                 if (pRegSection->__sectionName == sectionName)
460                 {
461                         sectionFound = true;
462                         break;
463                 }
464         }
465
466         if (sectionFound == false)
467         {
468                 return E_SECTION_NOT_FOUND;
469         }
470
471         r = _sectionList.Remove(*pRegSection, true);
472         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
473
474         _update = true;
475         return E_SUCCESS;
476 }
477
478 result
479 _RegistryCore::GetSectionListN(IList** pRetList)
480 {
481         result r = E_SUCCESS;
482         unique_ptr<IEnumerator> pEnum(null);
483         _RegistrySection* pSection = null;
484
485         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
486         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pList cannot be null.");
487
488         // construct an array list to be returned
489         unique_ptr<ArrayList, AllElementsDeleter> pSectionList(new (std::nothrow) ArrayList());
490         SysTryReturnResult(NID_IO, pSectionList != null, E_OUT_OF_MEMORY,
491                            "The memory is insufficient.");
492
493         r = pSectionList->Construct();
494         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
495
496         // if no sectons, return empty list
497         if (_sectionList.GetCount() == 0)
498         {
499                 *pRetList = pSectionList.release();
500                 return E_SUCCESS;
501         }
502
503         // copy from class section list to the new list and return
504         pEnum.reset(_sectionList.GetEnumeratorN());
505         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.", GetErrorMessage(GetLastResult()));
506
507         while (pEnum->MoveNext() == E_SUCCESS)
508         {
509                 pSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
510                 SysTryReturn(NID_IO, pSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
511                                    GetErrorMessage(GetLastResult()));
512
513                 unique_ptr<String> pSectionName(new (std::nothrow) String(pSection->__sectionName));
514                 SysTryReturnResult(NID_IO, pSectionName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
515
516                 r = pSectionList->Add(*(pSectionName.release()));
517                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
518         }
519
520         *pRetList = pSectionList.release();
521
522         return E_SUCCESS;
523 }
524
525 result
526 _RegistryCore::GetEntryList(const String& sectionName, Collection::HashMap& retMap)
527 {
528         result r = E_SUCCESS;
529         unique_ptr<IEnumerator> pEnum(null);
530         unique_ptr<String> pKeyEntryStr(null);
531         unique_ptr<String> pKeyValStr(null);
532         bool sectionFound = false;
533         _RegistrySection* pRegSection = null;
534         _RegistryEntry* pRegEntry = null;
535
536         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
537
538         if (_sectionList.GetCount() == 0)
539         {
540                 return E_SECTION_NOT_FOUND;
541         }
542
543         // Get section information
544         pEnum.reset(_sectionList.GetEnumeratorN());
545         SysTryReturnResult(NID_IO, pEnum != null, E_SYSTEM, "Section list is empty.");
546
547         while (pEnum->MoveNext() == E_SUCCESS)
548         {
549                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
550                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
551                                    GetErrorMessage(GetLastResult()));
552
553                 if (pRegSection->__sectionName == sectionName)
554                 {
555                         sectionFound = true;
556                         break;
557                 }
558         }
559
560         if (sectionFound == false)
561         {
562                 return E_SECTION_NOT_FOUND;
563         }
564
565         // copy from item list to the new list and return
566         pEnum.reset((pRegSection->__entryList).GetEnumeratorN());
567         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
568                                            GetErrorMessage(GetLastResult()));
569
570         while (pEnum->MoveNext() == E_SUCCESS)
571         {
572                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
573                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
574                                    GetErrorMessage(GetLastResult()));
575
576                 pKeyEntryStr.reset(new (std::nothrow) String((pRegEntry->entryName)));
577                 SysTryCatch(NID_IO, pKeyEntryStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
578                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
579                 pKeyValStr.reset(new (std::nothrow) String((pRegEntry->entryValue)));
580                 SysTryCatch(NID_IO, pKeyValStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
581                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
582
583                 r = retMap.Add(*(pKeyEntryStr.release()), *(pKeyValStr.release()));
584                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
585         }
586
587         return E_SUCCESS;
588
589 CATCH:
590         retMap.RemoveAll(true);
591
592         return r;
593 }
594
595 result
596 _RegistryCore::GetEntryListN(const String& sectionName, HashMap** pRetList)
597 {
598         result r = E_SUCCESS;
599
600         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
601         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pRetList cannot be null.");
602
603         // construct an array list to be returned
604         unique_ptr<HashMap, AllElementsDeleter> pEntryList(new (std::nothrow) HashMap());
605         SysTryReturnResult(NID_IO, pEntryList != null, E_OUT_OF_MEMORY,
606                         "The memory is insufficient.");
607         r = pEntryList->Construct();
608         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
609         r = GetEntryList(sectionName, *(pEntryList.get()));
610         *pRetList = pEntryList.release();
611
612         return r;
613 }
614
615 IMap*
616 _RegistryCore::GetAllEntriesN(const String& sectionName)
617 {
618         result r = E_SUCCESS;
619         HashMap* pMap = null;
620
621         r = GetEntryListN(sectionName, &pMap);
622         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
623
624         SetLastResult(E_SUCCESS);
625         return pMap;
626
627 CATCH:
628         SetLastResult(r);
629         return null;
630 }
631
632 IList*
633 _RegistryCore::GetAllEntryNamesN(const String& sectionName)
634 {
635         result r = E_SUCCESS;
636
637         unique_ptr<ArrayList, AllElementsDeleter> pEntryList(new (std::nothrow) ArrayList());
638         SysTryReturn(NID_IO, pEntryList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
639
640         r = pEntryList->Construct();
641         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
642
643         unique_ptr<IMap, AllElementsDeleter> pMap(this->GetAllEntriesN(sectionName));
644         SysTryReturn(NID_IO, pMap != null, null, GetLastResult(), "[%s] Getting all entries was failed.",
645                         GetErrorMessage(GetLastResult()));
646
647         unique_ptr<IMapEnumerator> pMapEnum(pMap->GetMapEnumeratorN());
648         SysTryReturn(NID_IO, pMapEnum, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
649         while (pMapEnum->MoveNext() == E_SUCCESS)
650         {
651                 String* pKey = dynamic_cast< String* >(pMapEnum->GetKey());
652                 SysTryReturn(NID_IO, pKey != null, null, E_IO, "[E_OUT_OF_MEMORY] The system error occurred.");
653
654                 String* pEntryName = new (std::nothrow) String(*pKey);
655                 SysTryReturn(NID_IO, pEntryName != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
656
657                 r = pEntryList->Add(*pEntryName);
658                 SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
659         }
660
661         SetLastResult(E_SUCCESS);
662         return pEntryList.release();
663 }
664
665 result
666 _RegistryCore::GetValue(const String& sectionName, const String& entryName, String& valStr)
667 {
668         bool sectionFound = false;
669         bool entryFound = false;
670         _RegistrySection* pRegSection = null;
671         _RegistryEntry* pRegEntry = null;
672
673         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
674
675         if (_sectionList.GetCount() == 0)
676         {
677                 return E_SECTION_NOT_FOUND;
678         }
679
680         // Get section information
681         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
682         if (pEnum == null)
683         {
684                 return GetLastResult();
685         }
686
687         while (pEnum->MoveNext() == E_SUCCESS)
688         {
689                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
690                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
691                                    GetErrorMessage(GetLastResult()));
692
693                 if (pRegSection->__sectionName == sectionName)
694                 {
695                         sectionFound = true;
696                         break;
697                 }
698         }
699
700         if (sectionFound == false)
701         {
702                 return E_SECTION_NOT_FOUND;
703         }
704
705         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
706         if (pEnum == null)
707         {
708                 return GetLastResult();
709         }
710
711         while (pEnum->MoveNext() == E_SUCCESS)
712         {
713                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
714                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
715                                    GetErrorMessage(GetLastResult()));
716
717                 if (pRegEntry->entryName == entryName)
718                 {
719                         valStr = pRegEntry->entryValue;
720                         entryFound = true;
721                         break;
722                 }
723         }
724
725         SysTryLog(NID_IO, entryFound, "Entry not found");
726
727         return((entryFound == true) ? E_SUCCESS : E_KEY_NOT_FOUND);
728 }
729
730 result
731 _RegistryCore::AddValue(const String& sectionName, const String& entryName, const String& valStr)
732 {
733         result r = E_SUCCESS;
734         bool sectionFound = false;
735         bool entryFound = false;
736         _RegistrySection* pRegSection = null;
737         int length = 0;
738
739         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
740
741         // Get section information
742         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
743         if (pEnum == null)
744         {
745                 return GetLastResult();
746         }
747
748         while (pEnum->MoveNext() == E_SUCCESS)
749         {
750                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
751                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
752                                    GetErrorMessage(GetLastResult()));
753
754                 if (pRegSection->__sectionName == sectionName)
755                 {
756                         sectionFound = true;
757                         break;
758                 }
759         }
760
761         if (sectionFound == false)
762         {
763                 return E_SECTION_NOT_FOUND;
764         }
765
766         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
767         if (pEnum == null)
768         {
769                 return GetLastResult();
770         }
771
772         while (pEnum->MoveNext() == E_SUCCESS)
773         {
774                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
775                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
776                                    GetErrorMessage(GetLastResult()));
777
778                 if (pRegEntry->entryName == entryName)
779                 {
780                         entryFound = true;
781                         break;
782                 }
783         }
784
785         if (entryFound == true)
786         {
787                 return E_KEY_ALREADY_EXIST;
788         }
789
790         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
791         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
792
793         unique_ptr<char[]> pEntryName(_StringConverter::CopyToCharArrayN(entryName));
794         SysTryReturnResult(NID_IO, pEntryName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
795
796         length = strlen(pEntryName.get());
797         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
798         {
799                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry name could not be parsed.");
800         }
801
802         unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
803         SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
804
805         length = strlen(pEntryValue.get());
806         if (length > 0 && !_RegistryCore::CheckEntryValue(pEntryValue.get()))
807         {
808                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry value could not be parsed.");
809         }
810
811         pRegEntry->entryName = entryName;
812         pRegEntry->entryValue = valStr;
813
814         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
815         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
816
817         _update = true;
818         return E_SUCCESS;
819 }
820
821 result
822 _RegistryCore::SetValue(const String& sectionName, const String& entryName, const String& valStr)
823 {
824         result r = E_SUCCESS;
825         bool sectionFound = false;
826         bool entryFound = false;
827         _RegistryEntry* pRegEntry = null;
828         _RegistrySection* pRegSection = null;
829         int length = 0;
830         int entryIndex = 0;
831
832         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
833
834         if (_sectionList.GetCount() == 0)
835         {
836                 return E_SECTION_NOT_FOUND;
837         }
838
839         // Get section information
840         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
841         if (pEnum == null)
842         {
843                 return GetLastResult();
844         }
845
846         while (pEnum->MoveNext() == E_SUCCESS)
847         {
848                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
849                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
850                                    GetErrorMessage(GetLastResult()));
851
852                 if (pRegSection->__sectionName == sectionName)
853                 {
854                         sectionFound = true;
855                         break;
856                 }
857         }
858
859         if (sectionFound == false)
860         {
861                 return E_SECTION_NOT_FOUND;
862         }
863
864         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
865         if (pEnum == null)
866         {
867                 return GetLastResult();
868         }
869
870         while (pEnum->MoveNext() == E_SUCCESS)
871         {
872                 pRegEntry = dynamic_cast< _RegistryEntry* >(pEnum->GetCurrent());
873                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
874                                    GetErrorMessage(GetLastResult()));
875
876                 if (pRegEntry->entryName == entryName)
877                 {
878                         entryFound = true;
879                         break;
880                 }
881                 entryIndex++;
882         }
883
884         if (entryFound == false)
885         {
886                 return E_KEY_NOT_FOUND;
887         }
888
889         if (valStr.GetLength() > 0)
890         {
891                 unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
892                 SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
893
894                 length = strlen(pEntryValue.get());
895                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
896                 {
897                         return E_PARSING_FAILED;
898                 }
899         }
900
901         pRegEntry->entryValue = valStr;
902         r = pRegSection->__entryList.SetAt(*pRegEntry, entryIndex);
903         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
904
905         _update = true;
906         return E_SUCCESS;
907 }
908
909 result
910 _RegistryCore::RemoveValue(const String& sectionName, const String& entryName)
911 {
912         result r = E_SUCCESS;
913         bool sectionFound = false;
914         bool entryFound = false;
915         _RegistryEntry* pRegEntry = null;
916         _RegistrySection* pRegSection = null;
917
918         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
919
920         if (_sectionList.GetCount() <= 0)
921         {
922                 return E_SECTION_NOT_FOUND;
923         }
924
925         // Get section information
926         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
927         if (pEnum == null)
928         {
929                 return E_SECTION_NOT_FOUND;
930         }
931
932         while (pEnum->MoveNext() == E_SUCCESS)
933         {
934                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
935                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
936                                    GetErrorMessage(GetLastResult()));
937
938                 if (pRegSection->__sectionName == sectionName)
939                 {
940                         sectionFound = true;
941                         break;
942                 }
943         }
944
945         if (sectionFound == false)
946         {
947                 return E_SECTION_NOT_FOUND;
948         }
949
950         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
951         if (pEnum == null)
952         {
953                 return E_SECTION_NOT_FOUND;
954         }
955
956         while (pEnum->MoveNext() == E_SUCCESS)
957         {
958                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
959                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
960                                    GetErrorMessage(GetLastResult()));
961
962                 if (pRegEntry->entryName == entryName)
963                 {
964                         entryFound = true;
965                         break;
966                 }
967         }
968
969         if (entryFound == false)
970         {
971                 return E_KEY_NOT_FOUND;
972         }
973
974         r = pRegSection->__entryList.Remove(*pRegEntry, true);
975         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
976
977         _update = true;
978         return E_SUCCESS;
979 }
980
981 result
982 _RegistryCore::Flush(void)
983 {
984         return E_SUCCESS;
985 }
986
987 result
988 _RegistryCore::Write(void)
989 {
990         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
991
992         if (_pBuffer == null)
993         {
994                 SysLog(NID_IO, "The buffer is empty.");
995                 return E_SUCCESS;
996         }
997
998         result r = E_SUCCESS;
999
1000         String openMode(L"w+");
1001         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl);
1002         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1003
1004         //TODO: Secure mode is to be handled
1005         r = pFileImpl->Construct(_regPath, "w+", null);
1006         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1007
1008         r = pFileImpl->Write(_pBuffer, _length);
1009         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1010
1011         r = pFileImpl->Flush();
1012         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1013
1014         return r;
1015 }
1016
1017 result
1018 _RegistryCore::PrepareToWrite(void)
1019 {
1020         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1021
1022         result r = E_SUCCESS;
1023         _RegistryEntry* pRegEntry = null;
1024         _RegistrySection* pRegSection = null;
1025         String inputBuffer;
1026
1027         delete[] _pBuffer; //clear existing buffer
1028         _pBuffer = null;
1029         _length = 0;
1030
1031         if (_write == false)
1032         {
1033                 SysLog(NID_IO, "[E_ILLEGAL_ACCESS] Registry cannot be flushed as it was opened in read only mode.");
1034                 return E_ILLEGAL_ACCESS;
1035         }
1036
1037         // if no sections, do nothing
1038         if (_sectionList.GetCount() == 0)
1039         {
1040                 unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(_regPath));
1041                 int res = truncate(pFilePath.get(), 0);
1042                 SysTryReturnResult(NID_IO, res == 0, __ConvertNativeErrorToResult(errno),
1043                                 "Failed to truncate. errno: %d (%s)", errno, strerror(errno));
1044                 return E_SUCCESS;
1045         }
1046
1047         // write the registry map to a file
1048         // Get section information
1049         unique_ptr<IEnumerator> pSectionEnum(_sectionList.GetEnumeratorN());
1050         SysTryReturn(NID_IO, pSectionEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.",
1051                            GetErrorMessage(GetLastResult()));
1052
1053         while (pSectionEnum->MoveNext() == E_SUCCESS)
1054         {
1055                 // get section name
1056                 pRegSection = dynamic_cast <_RegistrySection*>(pSectionEnum->GetCurrent());
1057                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1058                                    GetErrorMessage(GetLastResult()));
1059
1060                 // write section name to file
1061                 r = inputBuffer.Append(String(L"#" + pRegSection->__sectionName + String(L'\n')));
1062                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1063
1064                 // read the entries for this section
1065                 unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1066                 SysTryReturn(NID_IO, pSectionEnum != null, GetLastResult(), GetLastResult(), "[%s] Entry list is empty.",
1067                                    GetErrorMessage(GetLastResult()));
1068
1069                 while (pEntryEnum->MoveNext() == E_SUCCESS)
1070                 {
1071                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1072                         SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1073                                            GetErrorMessage(GetLastResult()));
1074
1075                         // write entry name to file
1076                         r = inputBuffer.Append(pRegEntry->entryName + String(L"=" + pRegEntry->entryValue + String(L'\n')));
1077                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1078                 }
1079
1080         }
1081
1082         _pBuffer = (byte*)_StringConverter::CopyToCharArrayN(inputBuffer);
1083         SysTryReturn(NID_IO, _pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1084                                                    GetErrorMessage(GetLastResult()));
1085
1086         _length = strlen((char*)_pBuffer);
1087
1088         return r;
1089 }
1090
1091 int
1092 _RegistryCore::GetSectionIndex(const String& sectionName)
1093 {
1094         bool sectionFound = false;
1095         _RegistrySection* pRegSection = null;
1096         int index = 0;
1097
1098         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1099         SysTryReturn(NID_IO, sectionName.GetLength() > 0, -1, E_INVALID_ARG,
1100                            "[E_INVALID_ARG] sectionName.GetLength() <= 0");
1101
1102         SysTryReturn(NID_IO, _sectionList.GetCount() > 0, -1, E_SECTION_NOT_FOUND, "[E_SECTION_NOT_FOUND] Section not found.");
1103
1104         // Get section information
1105         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
1106         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.",
1107                            GetErrorMessage(GetLastResult()));
1108
1109         while (pEnum->MoveNext() == E_SUCCESS)
1110         {
1111                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1112                 SysTryReturn(NID_IO, pRegSection != null, -1, GetLastResult(), "[%s] Propagated.",
1113                                    GetErrorMessage(GetLastResult()));
1114
1115                 if (pRegSection->__sectionName == sectionName)
1116                 {
1117                         sectionFound = true;
1118                         break;
1119                 }
1120                 index++;
1121         }
1122
1123         if (sectionFound == false)
1124         {
1125                 return E_SECTION_NOT_FOUND;
1126         }
1127
1128         SetLastResult(E_SUCCESS);
1129         return index;
1130 }
1131
1132 void
1133 _RegistryCore::Removekey(const String& sectionName, const String& keyName)
1134 {
1135         result r = E_SUCCESS;
1136         int sectionIndex = -1;
1137         int entryIndex = -1;
1138
1139         sectionIndex = GetSectionIndex(sectionName);
1140         r = GetLastResult();
1141         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1142
1143         entryIndex = GetEntryIndex(sectionIndex, keyName);
1144         r = GetLastResult();
1145         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1146
1147         RemoveEntry(sectionIndex, entryIndex);
1148         r = GetLastResult();
1149         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1150
1151         SetLastResult(E_SUCCESS);
1152         return;
1153 }
1154
1155 int
1156 _RegistryCore::GetAllSectionCount(void)
1157 {
1158         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1159
1160         SetLastResult(E_SUCCESS);
1161         return _sectionList.GetCount();
1162 }
1163
1164 int
1165 _RegistryCore::GetAllEntryCount(int sectionIndex)
1166 {
1167         _RegistrySection* pRegSection = null;
1168         int listSize = 0;
1169
1170         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1171         SysTryReturn(NID_IO, sectionIndex >= 0, 0, E_INVALID_ARG, "[E_INVALID_ARG] sectionIndex < 0.");
1172         listSize = _sectionList.GetCount();
1173         SysTryReturn(NID_IO, listSize > 0, 0, E_SECTION_NOT_FOUND, "[E_INVALID_ARG] section listSize <= 0.");
1174         SysTryReturn(NID_IO, sectionIndex >= listSize, 0, E_SECTION_NOT_FOUND,
1175                            "[E_INVALID_ARG] sectionIndex > listSize.");
1176
1177         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1178         SysTryReturn(NID_IO, pRegSection != null, 0, E_SECTION_NOT_FOUND,
1179                            "[E_SECTION_NOT_FOUND] section was not found.");
1180
1181         SetLastResult(E_SUCCESS);
1182         return pRegSection->__entryList.GetCount();
1183 }
1184
1185 void
1186 _RegistryCore::RemoveEntry(int sectionIndex, int entryIndex)
1187 {
1188         result r = E_SUCCESS;
1189         int listSize = 0;
1190         int entryListSize = 0;
1191         _RegistrySection* pRegSection = null;
1192
1193         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1194         SysTryReturnVoidResult(NID_IO, sectionIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG] sectionIndex < 0.");
1195         SysTryReturnVoidResult(NID_IO, entryIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG] entryIndex < 0.");
1196
1197         listSize = _sectionList.GetCount();
1198         SysTryReturnVoidResult(NID_IO, listSize > 0, E_SECTION_NOT_FOUND,
1199                            "[E_SECTION_NOT_FOUND] section listSize <= 0.");
1200         SysTryReturnVoidResult(NID_IO, sectionIndex < listSize, E_SECTION_NOT_FOUND,
1201                            "[E_SECTION_NOT_FOUND] sectionIndex >= listSize.");
1202
1203         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1204         SysTryReturnVoidResult(NID_IO, pRegSection != null, E_SECTION_NOT_FOUND,
1205                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1206
1207         r = GetLastResult();
1208         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r,"[%s] Propagated.", GetErrorMessage(r));
1209
1210         entryListSize = pRegSection->__entryList.GetCount();
1211         SysTryReturnVoidResult(NID_IO, (entryListSize > 0 || entryIndex < entryListSize), E_KEY_NOT_FOUND,
1212                            "[E_KEY_NOT_FOUND] entryListSize is 0 or entryIndex >= entryListSize.");
1213
1214         r = pRegSection->__entryList.RemoveAt(entryIndex, true);
1215         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1216
1217         SetLastResult(E_SUCCESS);
1218 }
1219
1220 void
1221 _RegistryCore::ModifyEntryValue(int sectionIndex, int entryIndex, _RegValueType type, const void* pValue, int size)
1222 {
1223         SetLastResult(E_UNSUPPORTED_OPERATION);
1224 }
1225
1226 int
1227 _RegistryCore::GetEntryIndex(int sectionIndex, const String& entryName)
1228 {
1229         _RegistrySection* pRegSection = null;
1230         _RegistryEntry* pRegEntry = null;
1231         int listSize = 0;
1232         bool entryFound = false;
1233         int entryIndex = -1;
1234
1235         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1236         SysTryReturn(NID_IO, sectionIndex >= 0, -1, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1237         SysTryReturn(NID_IO, entryName.GetLength() > 0, -1, E_INVALID_ARG, "[E_INVALID_ARG]entryName length < 0.");
1238
1239         listSize = _sectionList.GetCount();
1240         SysTryReturn(NID_IO, listSize > 0, -1, E_SECTION_NOT_FOUND,
1241                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1242         SysTryReturn(NID_IO, sectionIndex < listSize, -1, E_SECTION_NOT_FOUND,
1243                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1244
1245         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1246         SysTryReturn(NID_IO, pRegSection != null, -1, E_SECTION_NOT_FOUND,
1247                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1248
1249         // read the entries for this section
1250         unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1251         SysTryReturn(NID_IO, pEntryEnum != null, -1, GetLastResult(), "[%s] Entry list is empty.",
1252                            GetErrorMessage(GetLastResult()));
1253
1254         entryIndex = 0;
1255         while (pEntryEnum->MoveNext() == E_SUCCESS)
1256         {
1257                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1258                 SysTryReturn(NID_IO, pRegEntry != null, -1, GetLastResult(), "[%s] Propagated.",
1259                                    GetErrorMessage(GetLastResult()));
1260
1261                 if (entryName == pRegEntry->entryName)
1262                 {
1263                         entryFound = true;
1264                         break;
1265                 }
1266                 entryIndex++;
1267         }
1268
1269         SysTryReturn(NID_IO, entryFound != false, -1, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] entry was not found.");
1270
1271         SetLastResult(E_SUCCESS);
1272         return entryIndex;
1273 }
1274
1275 String
1276 _RegistryCore::GetEntryName(int sectionIndex, int entryIndex)
1277 {
1278         _RegistrySection* pRegSection = null;
1279         _RegistryEntry* pRegEntry = null;
1280         int listSize = 0;
1281         int tmpIndex = -1;
1282         String empty;
1283
1284         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1285         SysTryReturn(NID_IO, sectionIndex >= 0, empty, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1286         SysTryReturn(NID_IO, entryIndex >= 0, empty, E_INVALID_ARG, "[E_INVALID_ARG]entryIndex < 0.");
1287
1288         listSize = _sectionList.GetCount();
1289         SysTryReturn(NID_IO, listSize > 0, empty, E_SECTION_NOT_FOUND,
1290                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1291         SysTryReturn(NID_IO, sectionIndex < listSize, empty, E_SECTION_NOT_FOUND,
1292                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1293
1294         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1295         SysTryReturn(NID_IO, pRegSection != null, empty, E_SECTION_NOT_FOUND,
1296                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1297
1298         // read the entries for this section
1299         unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1300         SysTryReturn(NID_IO, pEntryEnum != null, empty, GetLastResult(), "[%s] Entry list is empty.",
1301                         GetErrorMessage(GetLastResult()));
1302
1303         tmpIndex = entryIndex;
1304         while (pEntryEnum->MoveNext() == E_SUCCESS)
1305         {
1306                 if (tmpIndex == 0)
1307                 {
1308                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1309                         SysTryReturn(NID_IO, pRegEntry != null, empty, GetLastResult(), "[%s] Propagated.",
1310                                            GetErrorMessage(GetLastResult()));
1311
1312                         break;
1313                 }
1314                 tmpIndex--;
1315         }
1316
1317         SysTryReturn(NID_IO, pRegEntry != null, empty, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] entry was not found.");
1318
1319         SetLastResult(E_SUCCESS);
1320         return pRegEntry->entryName;
1321 }
1322
1323 void
1324 _RegistryCore::GetEntryValue(int sectionIndex, int entryIndex, _RegValueType type, void* pValue, int* pSize)
1325 {
1326         _RegistrySection* pRegSection = null;
1327         _RegistryEntry* pRegEntry = null;
1328         result r = E_SUCCESS;
1329         int listSize = 0;
1330         int tmpEntryIndex = -1;
1331         int entryListSize = 0;
1332         String strValueEncoded;
1333
1334         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1335         SysTryReturnVoidResult(NID_IO, sectionIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1336         SysTryReturnVoidResult(NID_IO, type >= 0 && type <= REG_VALUE_TYPE_MAX, E_INVALID_ARG,
1337                            "[E_INVALID_ARG] invalid registry type.");
1338         SysTryReturnVoidResult(NID_IO, pValue != null, E_INVALID_ARG, "[E_INVALID_ARG]pValue is null.");
1339         SysTryReturnVoidResult(NID_IO, pSize != null, E_INVALID_ARG, "[E_INVALID_ARG]pSize is null.");
1340         SysTryReturnVoidResult(NID_IO, *pSize > 0, E_INVALID_ARG, "[E_INVALID_ARG] *pSize < 0.");
1341
1342         listSize = _sectionList.GetCount();
1343         SysTryReturnVoidResult(NID_IO, listSize > 0, E_SECTION_NOT_FOUND,
1344                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1345         SysTryReturnVoidResult(NID_IO, sectionIndex < listSize, E_SECTION_NOT_FOUND,
1346                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1347
1348         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1349         SysTryReturnVoidResult(NID_IO, pRegSection != null, E_SECTION_NOT_FOUND,
1350                            "[E_SECTION_NOT_FOUND] section at index (%d) is not available.", sectionIndex);
1351
1352         entryListSize = pRegSection->__entryList.GetCount();
1353         SysTryReturnVoidResult(NID_IO, entryListSize > 0, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND]Entry list is empty.");
1354         SysTryReturnVoidResult(NID_IO, entryIndex < entryListSize, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND]Entry not found.");
1355
1356         // read the entries for this section
1357         unique_ptr< IEnumerator > pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1358         SysTryReturnVoidResult(NID_IO, pEntryEnum != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND]Entry list is empty.");
1359
1360         tmpEntryIndex = entryIndex;
1361         while (pEntryEnum->MoveNext() == E_SUCCESS)
1362         {
1363                 if (entryIndex == 0)
1364                 {
1365                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1366                         SysTryReturnVoidResult(NID_IO, pRegEntry != null, GetLastResult(), "[%s] Propagated.",
1367                                            GetErrorMessage(GetLastResult()));
1368
1369                         break;
1370                 }
1371                 entryIndex--;
1372
1373         }
1374
1375         SysTryReturnVoidResult(NID_IO, pRegEntry != null, E_KEY_NOT_FOUND,
1376                            "[E_KEY_NOT_FOUND] Entry was not found.");
1377
1378         strValueEncoded = pRegEntry->entryValue;
1379
1380         DecodeData(strValueEncoded, type, pValue, pSize);
1381         r = GetLastResult();
1382         SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1383
1384         SetLastResult(E_SUCCESS);
1385         return;
1386 }
1387
1388 String
1389 _RegistryCore::GetSectionName(int sectionIndex)
1390 {
1391         _RegistrySection* pRegSection = null;
1392         result r = E_SUCCESS;
1393         int listSize = 0;
1394         String sectionName("");
1395
1396         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1397         SysTryReturn(NID_IO, sectionIndex >= 0, sectionName, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1398
1399         listSize = _sectionList.GetCount();
1400         SysTryReturn(NID_IO, listSize > 0, sectionName, E_SECTION_NOT_FOUND,
1401                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1402         SysTryReturn(NID_IO, sectionIndex < listSize, sectionName, E_SECTION_NOT_FOUND,
1403                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1404
1405         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1406         SysTryReturn(NID_IO, pRegSection != null, sectionName, E_SECTION_NOT_FOUND,
1407                            "[E_SECTION_NOT_FOUND] sectionIndex is not available.");
1408
1409         r = GetLastResult();
1410         SysTryReturn(NID_IO, !IsFailed(r), sectionName, r, "[%s] Propagated.", GetErrorMessage(r));
1411
1412         SetLastResult(E_SUCCESS);
1413         return pRegSection->__sectionName;
1414 }
1415
1416 void*
1417 _RegistryCore::GetSectionByIndex(int sectionIndex)
1418 {
1419         _RegistrySection* pRegSection = null;
1420         int index = sectionIndex;
1421
1422         // Get section information
1423         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
1424         SysTryReturn(NID_IO, pEnum != null, null, GetLastResult(),
1425                            "[%s] section list is empty.", GetErrorMessage(GetLastResult()));
1426
1427         while (pEnum->MoveNext() == E_SUCCESS)
1428         {
1429                 if (index == 0)
1430                 {
1431                         pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
1432                         SysTryReturn(NID_IO, pRegSection != null, null, GetLastResult(), "[%s] Propagated.",
1433                                            GetErrorMessage(GetLastResult()));
1434                         break;
1435                 }
1436                 index--;
1437
1438         }
1439
1440         SysTryReturn(NID_IO, pRegSection != null, null, E_SECTION_NOT_FOUND,
1441                            "[E_SECTION_NOT_FOUND] Section was not found.");
1442
1443         SetLastResult(E_SUCCESS);
1444
1445         return pRegSection;
1446 }
1447
1448 void
1449 _RegistryCore::DecodeData(const String& strValueEncoded, _RegValueType type, void* pValue, int* pSize)
1450 {
1451         SysAssert(strValueEncoded.GetLength() > 0);
1452         SysAssert(pValue);
1453         SysAssert(pSize);
1454         SysAssert(pSize && *pSize > 0);
1455
1456         SysTryReturnVoidResult(NID_IO, pValue != null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument.");
1457         SysTryReturnVoidResult(NID_IO, pSize != null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument.");
1458
1459         switch (type)
1460         {
1461         case REG_VALUE_TYPE_INT: // (-2147483647 - 1) ~ 2147483647
1462         {
1463                 int retIntVal = 0;
1464                 result r = E_SUCCESS;
1465
1466                 if (*pSize != sizeof(int))
1467                 {
1468                         SetLastResult(E_INVALID_ARG);
1469                         return;
1470                 }
1471
1472                 r = Integer::Parse(strValueEncoded, retIntVal);
1473                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1474
1475                 *(int*) pValue = retIntVal;
1476                 break;
1477         }
1478
1479         case REG_VALUE_TYPE_REAL:  // Holds signed IEEE 64-bit (8-byte) double-precision floating-point numbers
1480                                         // ranging in value from -1.79769313486231570E+308 through -4.94065645841246544E-324
1481                                         // for negative values and from 4.94065645841246544E-324 through 1.79769313486231570E+308
1482                                         // for positive values.
1483         {
1484                 double retDoubleVal = 0;
1485
1486                 if (*pSize != sizeof(double))
1487                 {
1488                         SetLastResult(E_INVALID_ARG);
1489                         return;
1490                 }
1491
1492                 retDoubleVal = _LocalizedNumParser::ToDouble(strValueEncoded, "C");
1493                 result r = GetLastResult();
1494                 SysTryReturnVoidResult(NID_IO, r == E_SUCCESS, E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1495
1496                 *(double*) pValue = retDoubleVal;
1497
1498                 break;
1499         }
1500
1501         case REG_VALUE_TYPE_STRING:
1502         {
1503 //              if(*pSize != sizeof(String))
1504 //              {
1505 //                      SetLastResult(E_INVALID_ARG);
1506 //                      return;
1507 //              }
1508                 *(String*) pValue = strValueEncoded;
1509                 break;
1510         }
1511
1512         case REG_VALUE_TYPE_BINARY:
1513         {
1514                 SetLastResult(E_PARSING_FAILED);
1515                 return;
1516         }
1517
1518         case REG_VALUE_TYPE_UUID:
1519         {
1520                 UuId retUuIdVal;
1521                 result r = E_SUCCESS;
1522
1523                 r = UuId::Parse(strValueEncoded, retUuIdVal);
1524                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1525
1526                 *(UuId*) pValue = retUuIdVal;
1527                 break;
1528         }
1529
1530         case REG_VALUE_TYPE_UUIDSET:
1531         {
1532                 SetLastResult(E_PARSING_FAILED);
1533                 return;
1534         }
1535
1536         default:
1537                 SysAssert(0); // should not happen!
1538                 return;
1539         }
1540
1541         SetLastResult(E_SUCCESS);
1542         return;
1543 }
1544
1545 result
1546 _RegistryCore::AddSection(LinkedList& sectionList, const String& sectionName)
1547 {
1548         result r = E_SUCCESS;
1549         bool sectionFound = false;
1550
1551         // Get section information
1552         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1553         if (pEnum == null)
1554         {
1555                 return GetLastResult();
1556         }
1557
1558         while (pEnum->MoveNext() == E_SUCCESS)
1559         {
1560                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1561                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1562                                    GetErrorMessage(GetLastResult()));
1563
1564                 if (pRegSection->__sectionName == sectionName)
1565                 {
1566                         sectionFound = true;
1567                         break;
1568                 }
1569         }
1570
1571         if (sectionFound == true)
1572         {
1573                 return E_SECTION_ALREADY_EXIST;
1574         }
1575
1576         // create a key with section name
1577         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
1578
1579         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
1580                            "The memory is insufficient.");
1581
1582         pRegSection->__sectionName = sectionName;
1583
1584         // add new section and section-entry map
1585         r = sectionList.Add(*(pRegSection.release()));
1586         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1587
1588         return E_SUCCESS;
1589 }
1590
1591 result
1592 _RegistryCore::AddValue(LinkedList& sectionList, const String& sectionName, const String& entryName, const String& valStr)
1593 {
1594         result r = E_SUCCESS;
1595         bool sectionFound = false;
1596         bool entryFound = false;
1597         _RegistrySection* pRegSection = null;
1598
1599         // Get section information
1600         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1601         if (pEnum == null)
1602         {
1603                 return GetLastResult();
1604         }
1605
1606         while (pEnum->MoveNext() == E_SUCCESS)
1607         {
1608                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1609                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1610                                    GetErrorMessage(GetLastResult()));
1611
1612                 if (pRegSection->__sectionName == sectionName)
1613                 {
1614                         sectionFound = true;
1615                         break;
1616                 }
1617         }
1618
1619         if (sectionFound == false)
1620         {
1621                 return E_SECTION_NOT_FOUND;
1622         }
1623
1624         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
1625         if (pEnum == null)
1626         {
1627                 return GetLastResult();
1628         }
1629
1630         while (pEnum->MoveNext() == E_SUCCESS)
1631         {
1632                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
1633                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1634                                    GetErrorMessage(GetLastResult()));
1635
1636                 if (pRegEntry->entryName == entryName)
1637                 {
1638                         entryFound = true;
1639                         break;
1640                 }
1641         }
1642
1643         if (entryFound == true)
1644         {
1645                 return E_KEY_ALREADY_EXIST;
1646         }
1647
1648         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
1649         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY,
1650                         "The memory is insufficient.");
1651
1652         pRegEntry->entryName = entryName;
1653         pRegEntry->entryValue = valStr;
1654
1655         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
1656         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1657
1658         return E_SUCCESS;
1659 }
1660
1661 bool
1662 _RegistryCore::CheckSectionName(char* pSectionName)
1663 {
1664         char* pTemp = null;
1665         int length = 0;
1666         char* pFrom = null;
1667         char* pTo = null;
1668
1669         if (pSectionName == null)
1670         {
1671                 return false;
1672         }
1673
1674         pFrom = pSectionName;
1675         length = strlen(pSectionName);
1676         pTo = pSectionName + (length - 1);
1677
1678         if (!pFrom || !pTo || pFrom > pTo)
1679         {
1680                 return false;
1681         }
1682
1683         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1684         {
1685                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1686                 {
1687                         return false;
1688                 }
1689         }
1690
1691         return true;
1692 }
1693
1694 bool
1695 _RegistryCore::CheckEntryName(char* pEntryName)
1696 {
1697         char* pTemp = null;
1698         int length = 0;
1699         char* pFrom = null;
1700         char* pTo = null;
1701
1702         if (pEntryName == null)
1703         {
1704                 return false;
1705         }
1706
1707         pFrom = pEntryName;
1708         length = strlen(pEntryName);
1709         pTo = pEntryName + (length - 1);
1710
1711         if (!pFrom || !pTo || pFrom > pTo)
1712         {
1713                 return false;
1714         }
1715
1716         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1717         {
1718                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1719                 {
1720                         return false;
1721                 }
1722         }
1723
1724         return true;
1725 }
1726
1727 bool
1728 _RegistryCore::CheckEntryValue(char* pEntryVal)
1729 {
1730         char* pTemp = null;
1731         int length = 0;
1732         char* pFrom = null;
1733         char* pTo = null;
1734
1735         if (pEntryVal == null)
1736         {
1737                 return false;
1738         }
1739
1740         pFrom = pEntryVal;
1741         length = strlen(pEntryVal);
1742         pTo = pEntryVal + (length - 1);
1743
1744         if (!pFrom || !pTo || pFrom > pTo)
1745         {
1746                 return false;
1747         }
1748
1749         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1750         {
1751                 if (*pTemp == '\0' || *pTemp == '\n')
1752                 {
1753                         return false;
1754                 }
1755         }
1756
1757         return true;
1758 }
1759
1760 result
1761 _RegistryCore::ConvertToSecureRegistry(const String& plainRegPath, const String& secureRegPath, const ByteBuffer* pKey)
1762 {
1763         result  r = E_SUCCESS;
1764
1765         if (File::IsFileExist(secureRegPath))
1766         {
1767                 r = GetLastResult();
1768                 if (r == E_SUCCESS)
1769                 {
1770                         r = E_FILE_ALREADY_EXIST;
1771                         SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] The secure registry already exists.");
1772                 }
1773                 else
1774                 {
1775                         SysLog(NID_IO, "[%s]Propagated.", GetErrorMessage(r));
1776                 }
1777                 return r;
1778         }
1779
1780         unique_ptr<_NormalRegistry> pNormalReg(new (std::nothrow) _NormalRegistry());
1781         SysTryReturnResult(NID_IO, pNormalReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1782
1783         r = pNormalReg->Load(plainRegPath, "r");
1784         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1785
1786         unique_ptr<_SecureRegistry> pSecureReg(new (std::nothrow) _SecureRegistry());
1787         SysTryReturnResult(NID_IO, pSecureReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1788
1789         r = pSecureReg->Construct(secureRegPath, "w+", pKey);
1790         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1791
1792         if (pNormalReg->_pBuffer != null && pNormalReg->_length > 0)
1793         {
1794                 pSecureReg->_pBuffer = pNormalReg->_pBuffer;
1795                 pSecureReg->_length = pNormalReg->_length;
1796
1797                 pNormalReg->_pBuffer = null;
1798                 pNormalReg->_length = 0;
1799
1800                 r = pSecureReg->Parse();
1801                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1802         }
1803
1804         r = pSecureReg->Flush();
1805         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1806
1807         return E_SUCCESS;
1808 }
1809
1810 FileLock*
1811 _RegistryCore::LockN(FileLockType lockType)
1812 {
1813         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1814         return __pFileImpl->LockN(lockType);
1815 }
1816
1817 FileLock*
1818 _RegistryCore::TryToLockN(FileLockType lockType)
1819 {
1820         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1821         return __pFileImpl->TryToLockN(lockType);
1822 }
1823
1824 }} // Tizen::Io
1825