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