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