LEFT | RIGHT |
(no file at all) | |
1 #include "PluginStdAfx.h" | |
2 | |
3 #include "PluginIniFile.h" | |
4 #include "PluginChecksum.h" | |
5 | |
6 #if (defined PRODUCT_ADBLOCKPLUS) | |
7 #include "PluginClient.h" | |
8 #endif | |
9 | |
10 | |
11 CPluginIniFile::CPluginIniFile(const CString& filename, bool hasChecksum) : | |
12 m_isValidChecksum(false), m_isDirty(false), m_filename(filename), m_hasChecksu
m(hasChecksum), m_lastError(0) | |
13 { | |
14 m_checksum = std::auto_ptr<CPluginChecksum>(new CPluginChecksum()); | |
15 } | |
16 | |
17 void CPluginIniFile::SetInitialChecksumString(const CString& str) | |
18 { | |
19 m_checksumInit = str; | |
20 } | |
21 | |
22 CString CPluginIniFile::GetFilePath() const | |
23 { | |
24 return m_filename; | |
25 } | |
26 | |
27 | |
28 void CPluginIniFile::Clear() | |
29 { | |
30 m_data.clear(); | |
31 m_sectionNames.clear(); | |
32 m_checksumInit.Empty(); | |
33 m_checksum->Clear(); | |
34 } | |
35 | |
36 | |
37 bool CPluginIniFile::Exists() | |
38 { | |
39 bool isExisting = false; | |
40 | |
41 HANDLE hFile = ::CreateFile(m_filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL); | |
42 if (hFile != INVALID_HANDLE_VALUE) | |
43 { | |
44 isExisting = true; | |
45 ::CloseHandle(hFile); | |
46 } | |
47 | |
48 return isExisting; | |
49 } | |
50 | |
51 | |
52 bool CPluginIniFile::ReadString(const CStringA& memFile) | |
53 { | |
54 bool isOk = true; | |
55 | |
56 DWORD checksumValue = 0; | |
57 | |
58 m_checksum->Clear(); | |
59 m_checksum->Add(m_checksumInit); | |
60 | |
61 // Read file | |
62 std::string buffer(memFile); | |
63 | |
64 std::istringstream is; | |
65 is.str(buffer); | |
66 | |
67 CPluginIniFile::TSectionData sectionData; | |
68 CStringA sectionName; | |
69 | |
70 bool bHasSection = false; | |
71 | |
72 while (isOk && !is.eof()) | |
73 { | |
74 char szLine[256]; | |
75 is.getline(szLine, 255); | |
76 | |
77 if (is.fail() && !is.eof()) | |
78 { | |
79 is.clear(); | |
80 isOk = false; | |
81 break; | |
82 } | |
83 | |
84 CStringA line(szLine); | |
85 line.Trim(); | |
86 | |
87 if (!line.IsEmpty()) | |
88 { | |
89 // Comment | |
90 if (line.GetAt(0) == '#') | |
91 { | |
92 } | |
93 // Section start | |
94 else if (line.GetAt(0) == '[' && line.GetAt(line.GetLength() - 1) == ']') | |
95 { | |
96 if (bHasSection) | |
97 { | |
98 m_data[sectionName] = sectionData; | |
99 sectionData.clear(); | |
100 } | |
101 | |
102 // Add section name to list | |
103 sectionName = line.Mid(1, line.GetLength() - 2); | |
104 | |
105 // Add to checksum | |
106 if (m_hasChecksum && sectionName != "Checksum") | |
107 { | |
108 m_checksum->Add(sectionName); | |
109 } | |
110 | |
111 m_sectionNames.insert(sectionName); | |
112 | |
113 bHasSection = true; | |
114 } | |
115 // Section data | |
116 else if (bHasSection) | |
117 { | |
118 int pos = 0; | |
119 if ((pos = line.Find('=')) > 0) | |
120 { | |
121 CStringA key = line.Left(pos).Trim(); | |
122 CStringA value = line.Right(line.GetLength() - pos - 1).Trim(); | |
123 | |
124 if (!key.IsEmpty()) | |
125 { | |
126 sectionData[key] = value; | |
127 } | |
128 | |
129 if (m_hasChecksum && sectionName != "Checksum") | |
130 { | |
131 m_checksum->Add(key); | |
132 m_checksum->Add(value); | |
133 } | |
134 } | |
135 else if (m_hasChecksum && sectionName == "Checksum") | |
136 { | |
137 checksumValue = (DWORD)atol(line); | |
138 } | |
139 } | |
140 } | |
141 } | |
142 | |
143 // Add final section | |
144 if (bHasSection) | |
145 { | |
146 m_data[sectionName] = sectionData; | |
147 } | |
148 | |
149 m_isValidChecksum = checksumValue == m_checksum->Get(); | |
150 | |
151 return isOk; | |
152 } | |
153 | |
154 | |
155 bool CPluginIniFile::Read() | |
156 { | |
157 bool isRead = true; | |
158 | |
159 m_lastError = 0; | |
160 | |
161 // Read file | |
162 HANDLE hFile = ::CreateFile(m_filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL); | |
163 if (hFile == INVALID_HANDLE_VALUE) | |
164 { | |
165 m_lastError = ::GetLastError(); | |
166 isRead = false; | |
167 } | |
168 else | |
169 { | |
170 DEBUG_INI("Ini::Reading file " + m_filename); | |
171 | |
172 DWORD checksumValue = 0; | |
173 m_checksum->Clear(); | |
174 | |
175 CPluginIniFile::TSectionData sectionData; | |
176 CStringA sectionName; | |
177 | |
178 bool bHasSection = false; | |
179 | |
180 // Read file | |
181 char buffer[8194]; | |
182 LPVOID pBuffer = buffer; | |
183 LPBYTE pByteBuffer = (LPBYTE)pBuffer; | |
184 DWORD dwBytesRead = 0; | |
185 CStringA fileContent; | |
186 BOOL bRead = TRUE; | |
187 while ((bRead = ::ReadFile(hFile, pBuffer, 8192, &dwBytesRead, NULL)) == TRU
E && dwBytesRead > 0) | |
188 { | |
189 pByteBuffer[dwBytesRead] = 0; | |
190 | |
191 fileContent += buffer; | |
192 } | |
193 | |
194 // Read error | |
195 if (!bRead) | |
196 { | |
197 m_lastError = ::GetLastError(); | |
198 isRead = false; | |
199 } | |
200 | |
201 // Close file | |
202 ::CloseHandle(hFile); | |
203 | |
204 // Parse the file | |
205 isRead = ReadString(fileContent); | |
206 } | |
207 | |
208 return isRead; | |
209 } | |
210 | |
211 | |
212 bool CPluginIniFile::Write() | |
213 { | |
214 bool isWritten = true; | |
215 | |
216 m_lastError = 0; | |
217 | |
218 DEBUG_INI("Ini::Write " + m_filename); | |
219 | |
220 // Save file | |
221 if (m_isDirty) | |
222 { | |
223 DEBUG_INI("Ini::Writing file " + m_filename); | |
224 | |
225 m_checksum->Clear(); | |
226 | |
227 // Create file | |
228 HANDLE hFile = ::CreateFile(m_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAY
S, FILE_ATTRIBUTE_NORMAL, NULL); | |
229 if (hFile == INVALID_HANDLE_VALUE) | |
230 { | |
231 m_lastError = ::GetLastError(); | |
232 isWritten = false; | |
233 } | |
234 else | |
235 { | |
236 CStringA line; | |
237 | |
238 // Write warning | |
239 if (m_hasChecksum) | |
240 { | |
241 line += "# Please do not edit this file!\r\n\r\n";; | |
242 } | |
243 | |
244 for (CPluginIniFile::TData::iterator it = m_data.begin(); it != m_data.end
(); ++it) | |
245 { | |
246 line += "[" + it->first + "]\r\n"; | |
247 | |
248 m_checksum->Add(it->first); | |
249 | |
250 for (CPluginIniFile::TSectionData::iterator itValues = it->second.begin(
); itValues != it->second.end(); ++itValues) | |
251 { | |
252 line += itValues->first + "=" + itValues->second + "\r\n"; | |
253 | |
254 m_checksum->Add(itValues->first); | |
255 m_checksum->Add(itValues->second); | |
256 } | |
257 | |
258 line += "\r\n"; | |
259 } | |
260 | |
261 // Add checksum | |
262 if (m_hasChecksum) | |
263 { | |
264 line += "[Checksum]\r\n"; | |
265 | |
266 CStringA checksum; | |
267 checksum.Format("%lu\r\n", m_checksum->Get()); | |
268 | |
269 line += checksum; | |
270 } | |
271 | |
272 // Write file | |
273 DWORD dwBytesWritten = 0; | |
274 if (::WriteFile(hFile, line.GetBuffer(), line.GetLength(), &dwBytesWritten
, NULL) && dwBytesWritten == line.GetLength()) | |
275 { | |
276 m_isDirty = false; | |
277 | |
278 Clear(); | |
279 } | |
280 else | |
281 { | |
282 m_lastError = ::GetLastError(); | |
283 isWritten = false; | |
284 } | |
285 | |
286 // Close file | |
287 ::CloseHandle(hFile); | |
288 } | |
289 } | |
290 | |
291 return isWritten; | |
292 } | |
293 | |
294 | |
295 // Used to retrieve a value give the section and key | |
296 CStringA CPluginIniFile::GetValue(const CStringA& section, const CStringA& key)
const | |
297 { | |
298 CStringA value; | |
299 | |
300 TSectionData sectionData = GetSectionData(section); | |
301 | |
302 TSectionData::iterator it = sectionData.find(key); | |
303 if (it != sectionData.end()) | |
304 { | |
305 value = it->second; | |
306 } | |
307 | |
308 return value; | |
309 } | |
310 | |
311 | |
312 // Used to add or set a key value pair to a section | |
313 bool CPluginIniFile::SetValue(const CStringA& section, const CStringA& key, cons
t CStringA& value) | |
314 { | |
315 bool isSet = false; | |
316 | |
317 CPluginIniFile::TData::iterator it = m_data.find(section); | |
318 if (it != m_data.end()) | |
319 { | |
320 CPluginIniFile::TSectionData::iterator itValue = it->second.find(key); | |
321 if (itValue != it->second.end()) | |
322 { | |
323 if (itValue->second != value) | |
324 { | |
325 m_isDirty = true; | |
326 } | |
327 } | |
328 | |
329 it->second[key] = value; | |
330 isSet = true; | |
331 } | |
332 | |
333 return isSet; | |
334 } | |
335 | |
336 | |
337 // Used to add or set a key value pair to a section | |
338 bool CPluginIniFile::SetValue(const CStringA& section, const CStringA& key, int
value) | |
339 { | |
340 CStringA valueStr; | |
341 valueStr.Format("%d", value); | |
342 | |
343 return SetValue(section, key, valueStr); | |
344 } | |
345 | |
346 | |
347 // Used to find out if a given section exists | |
348 bool CPluginIniFile::HasSection(const CStringA& section) const | |
349 { | |
350 return m_sectionNames.find(section) != m_sectionNames.end(); | |
351 } | |
352 | |
353 | |
354 // Used to find out if a given key exists | |
355 bool CPluginIniFile::HasKey(const CStringA& section, const CStringA& key) const | |
356 { | |
357 return !GetValue(section, key).IsEmpty(); | |
358 } | |
359 | |
360 | |
361 void CPluginIniFile::UpdateSection(const CStringA& section, const CPluginIniFile
::TSectionData& data) | |
362 { | |
363 m_data[section] = data; | |
364 m_isDirty = true; | |
365 } | |
366 | |
367 | |
368 // Used to retrieve all of the section names in the ini file | |
369 const CPluginIniFile::TSectionNames& CPluginIniFile::GetSectionNames() const | |
370 { | |
371 return m_sectionNames; | |
372 } | |
373 | |
374 | |
375 // Used to retrieve all key/value pairs of a given section. | |
376 CPluginIniFile::TSectionData CPluginIniFile::GetSectionData(const CStringA& sect
ion) const | |
377 { | |
378 CPluginIniFile::TSectionData sectionData; | |
379 | |
380 CPluginIniFile::TData::const_iterator it = m_data.find(section); | |
381 if (it != m_data.end()) | |
382 { | |
383 sectionData = it->second; | |
384 } | |
385 | |
386 return sectionData; | |
387 } | |
388 | |
389 bool CPluginIniFile::IsValidChecksum() const | |
390 { | |
391 return m_isValidChecksum && m_hasChecksum || !m_hasChecksum; | |
392 } | |
393 | |
394 unsigned int CPluginIniFile::GetLastError() const | |
395 { | |
396 return m_lastError; | |
397 } | |
LEFT | RIGHT |