1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "nsINIParserImpl.h"
8 
9 #include "nsINIParser.h"
10 #include "nsStringEnumerator.h"
11 #include "nsTArray.h"
12 #include "mozilla/Attributes.h"
13 
14 class nsINIParserImpl final : public nsIINIParser, public nsIINIParserWriter {
15   ~nsINIParserImpl() = default;
16 
17  public:
18   NS_DECL_ISUPPORTS
19   NS_DECL_NSIINIPARSER
20   NS_DECL_NSIINIPARSERWRITER
21 
Init(nsIFile * aINIFile)22   nsresult Init(nsIFile* aINIFile) { return mParser.Init(aINIFile); }
23 
24  private:
25   nsINIParser mParser;
26   bool ContainsNull(const nsACString& aStr);
27 };
28 
NS_IMPL_ISUPPORTS(nsINIParserFactory,nsIINIParserFactory,nsIFactory)29 NS_IMPL_ISUPPORTS(nsINIParserFactory, nsIINIParserFactory, nsIFactory)
30 
31 NS_IMETHODIMP
32 nsINIParserFactory::CreateINIParser(nsIFile* aINIFile, nsIINIParser** aResult) {
33   *aResult = nullptr;
34 
35   RefPtr<nsINIParserImpl> p(new nsINIParserImpl());
36 
37   if (aINIFile) {
38     nsresult rv = p->Init(aINIFile);
39     if (NS_FAILED(rv)) {
40       return rv;
41     }
42   }
43 
44   p.forget(aResult);
45   return NS_OK;
46 }
47 
48 NS_IMETHODIMP
CreateInstance(nsISupports * aOuter,REFNSIID aIID,void ** aResult)49 nsINIParserFactory::CreateInstance(nsISupports* aOuter, REFNSIID aIID,
50                                    void** aResult) {
51   if (NS_WARN_IF(aOuter)) {
52     return NS_ERROR_NO_AGGREGATION;
53   }
54 
55   // We are our own singleton.
56   return QueryInterface(aIID, aResult);
57 }
58 
59 NS_IMETHODIMP
LockFactory(bool aLock)60 nsINIParserFactory::LockFactory(bool aLock) { return NS_OK; }
61 
NS_IMPL_ISUPPORTS(nsINIParserImpl,nsIINIParser,nsIINIParserWriter)62 NS_IMPL_ISUPPORTS(nsINIParserImpl, nsIINIParser, nsIINIParserWriter)
63 
64 bool nsINIParserImpl::ContainsNull(const nsACString& aStr) {
65   return aStr.CountChar('\0') > 0;
66 }
67 
SectionCB(const char * aSection,void * aClosure)68 static bool SectionCB(const char* aSection, void* aClosure) {
69   nsTArray<nsCString>* strings = static_cast<nsTArray<nsCString>*>(aClosure);
70   strings->AppendElement()->Assign(aSection);
71   return true;
72 }
73 
74 NS_IMETHODIMP
GetSections(nsIUTF8StringEnumerator ** aResult)75 nsINIParserImpl::GetSections(nsIUTF8StringEnumerator** aResult) {
76   nsTArray<nsCString>* strings = new nsTArray<nsCString>;
77 
78   nsresult rv = mParser.GetSections(SectionCB, strings);
79   if (NS_SUCCEEDED(rv)) {
80     rv = NS_NewAdoptingUTF8StringEnumerator(aResult, strings);
81   }
82 
83   if (NS_FAILED(rv)) {
84     delete strings;
85   }
86 
87   return rv;
88 }
89 
KeyCB(const char * aKey,const char * aValue,void * aClosure)90 static bool KeyCB(const char* aKey, const char* aValue, void* aClosure) {
91   nsTArray<nsCString>* strings = static_cast<nsTArray<nsCString>*>(aClosure);
92   strings->AppendElement()->Assign(aKey);
93   return true;
94 }
95 
96 NS_IMETHODIMP
GetKeys(const nsACString & aSection,nsIUTF8StringEnumerator ** aResult)97 nsINIParserImpl::GetKeys(const nsACString& aSection,
98                          nsIUTF8StringEnumerator** aResult) {
99   if (ContainsNull(aSection)) {
100     return NS_ERROR_INVALID_ARG;
101   }
102 
103   nsTArray<nsCString>* strings = new nsTArray<nsCString>;
104 
105   nsresult rv =
106       mParser.GetStrings(PromiseFlatCString(aSection).get(), KeyCB, strings);
107   if (NS_SUCCEEDED(rv)) {
108     rv = NS_NewAdoptingUTF8StringEnumerator(aResult, strings);
109   }
110 
111   if (NS_FAILED(rv)) {
112     delete strings;
113   }
114 
115   return rv;
116 }
117 
118 NS_IMETHODIMP
GetString(const nsACString & aSection,const nsACString & aKey,nsACString & aResult)119 nsINIParserImpl::GetString(const nsACString& aSection, const nsACString& aKey,
120                            nsACString& aResult) {
121   if (ContainsNull(aSection) || ContainsNull(aKey)) {
122     return NS_ERROR_INVALID_ARG;
123   }
124 
125   return mParser.GetString(PromiseFlatCString(aSection).get(),
126                            PromiseFlatCString(aKey).get(), aResult);
127 }
128 
129 NS_IMETHODIMP
SetString(const nsACString & aSection,const nsACString & aKey,const nsACString & aValue)130 nsINIParserImpl::SetString(const nsACString& aSection, const nsACString& aKey,
131                            const nsACString& aValue) {
132   if (ContainsNull(aSection) || ContainsNull(aKey) || ContainsNull(aValue)) {
133     return NS_ERROR_INVALID_ARG;
134   }
135 
136   return mParser.SetString(PromiseFlatCString(aSection).get(),
137                            PromiseFlatCString(aKey).get(),
138                            PromiseFlatCString(aValue).get());
139 }
140 
141 NS_IMETHODIMP
WriteFile(nsIFile * aINIFile)142 nsINIParserImpl::WriteFile(nsIFile* aINIFile) {
143   return mParser.WriteToFile(aINIFile);
144 }
145