|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // hosts.cpp - name resolver hosts file parser module |
|
15 // |
|
16 |
|
17 #include <f32file.h> // RFs |
|
18 #include <in_sock.h> // TInetAddr |
|
19 #include "hosts.h" // this |
|
20 |
|
21 RHostsFile::RHostsFile(RFs &aFs): |
|
22 iBuf(NULL), iFs(aFs), iRefreshed(0) |
|
23 { |
|
24 } |
|
25 |
|
26 RHostsFile::~RHostsFile() |
|
27 { |
|
28 if (iBuf) |
|
29 { |
|
30 delete iBuf; |
|
31 iBuf = NULL; |
|
32 } |
|
33 } |
|
34 |
|
35 // |
|
36 // |
|
37 // |
|
38 |
|
39 TInt RHostsFile::Open() |
|
40 { |
|
41 if (iBuf) |
|
42 { |
|
43 return KErrNone; |
|
44 } |
|
45 |
|
46 const TDesC &file_name = HOSTS_FILE; |
|
47 TInt err; |
|
48 |
|
49 RFile file; |
|
50 err = file.Open(iFs, file_name, EFileStreamText | EFileRead | EFileShareAny); |
|
51 |
|
52 if (err != KErrNone) |
|
53 { |
|
54 return err; |
|
55 } |
|
56 |
|
57 TInt size; |
|
58 err = file.Size(size); |
|
59 |
|
60 if (err != KErrNone) |
|
61 { |
|
62 file.Close(); |
|
63 return err; |
|
64 } |
|
65 |
|
66 iBuf = HBufC::NewMax(size); |
|
67 |
|
68 if (iBuf == NULL) |
|
69 { |
|
70 file.Close(); |
|
71 return KErrNoMemory; |
|
72 } |
|
73 |
|
74 // Unicode fix. |
|
75 |
|
76 HBufC8 *tempBuf = HBufC8::NewMax(size); |
|
77 |
|
78 if (tempBuf == NULL) |
|
79 { |
|
80 delete iBuf; |
|
81 iBuf = NULL; |
|
82 file.Close(); |
|
83 return KErrNoMemory; |
|
84 } |
|
85 |
|
86 TPtr8 tempPtr(tempBuf->Des()); |
|
87 err = file.Read(tempPtr); |
|
88 |
|
89 if (err != KErrNone) |
|
90 { |
|
91 delete iBuf; |
|
92 delete tempBuf; |
|
93 iBuf = NULL; |
|
94 file.Close(); |
|
95 return err; |
|
96 } |
|
97 |
|
98 TPtr p(iBuf->Des()); |
|
99 p.Copy(tempPtr); |
|
100 delete tempBuf; |
|
101 |
|
102 iCharLex = p; |
|
103 file.Close(); |
|
104 |
|
105 return KErrNone; |
|
106 } |
|
107 |
|
108 void RHostsFile::Close() |
|
109 { |
|
110 delete iBuf; |
|
111 iBuf = NULL; |
|
112 } |
|
113 |
|
114 // |
|
115 // |
|
116 // |
|
117 |
|
118 TInt RHostsFile::ReadLn(TPtrC& aLine) |
|
119 { |
|
120 do |
|
121 { |
|
122 iCharLex.Mark(); |
|
123 |
|
124 if (iCharLex.Eos()) |
|
125 { |
|
126 return KErrEof; |
|
127 } |
|
128 |
|
129 TChar ch = 0; |
|
130 |
|
131 while (!iCharLex.Eos() && (ch = iCharLex.Peek(), ch != '\n' && ch != '\r' && ch != '#' )) |
|
132 { |
|
133 iCharLex.Inc(); |
|
134 } |
|
135 |
|
136 aLine.Set(iCharLex.MarkedToken()); |
|
137 |
|
138 if (ch == '#') |
|
139 { |
|
140 while (!iCharLex.Eos() && (ch = iCharLex.Peek(), ch != '\n' && ch != '\r')) |
|
141 { |
|
142 iCharLex.Inc(); |
|
143 } |
|
144 } |
|
145 |
|
146 while (!iCharLex.Eos() && (ch = iCharLex.Peek(), ch == '\n' || ch == '\r')) |
|
147 { |
|
148 iCharLex.Inc(); |
|
149 } |
|
150 } |
|
151 while (!aLine.Length()); |
|
152 |
|
153 return KErrNone; |
|
154 } |
|
155 |
|
156 |
|
157 void RHostsFile::Rewind() |
|
158 { |
|
159 if (iBuf) |
|
160 { |
|
161 TPtr p(iBuf->Des()); |
|
162 iCharLex = p; |
|
163 } |
|
164 } |
|
165 |
|
166 void RHostsFile::Refresh() |
|
167 { |
|
168 const TDesC &file_name = HOSTS_FILE; |
|
169 TInt err; |
|
170 |
|
171 TTime modified; |
|
172 err = iFs.Modified(file_name, modified); |
|
173 |
|
174 if (err == KErrNone) |
|
175 { |
|
176 if (iRefreshed < modified) |
|
177 { |
|
178 Close(); |
|
179 Open(); |
|
180 iRefreshed = modified; |
|
181 return; |
|
182 } |
|
183 } |
|
184 Rewind(); |
|
185 } |
|
186 |
|
187 // |
|
188 // |
|
189 // |
|
190 |
|
191 void RHostsFile::GetByName(TNameRecord& aResult, TRequestStatus& err) |
|
192 { |
|
193 Refresh(); |
|
194 TInt count = 0; // ...to select correct result for Next() |
|
195 |
|
196 for (;;) |
|
197 { |
|
198 TPtrC line; |
|
199 err = ReadLn(line); |
|
200 |
|
201 if (err != KErrNone) |
|
202 { |
|
203 if (err == KErrEof) |
|
204 { |
|
205 err = KErrNotFound; |
|
206 } |
|
207 return; |
|
208 } |
|
209 |
|
210 TLex wordLex(line); |
|
211 TInetAddr addr; |
|
212 TPtrC word; |
|
213 |
|
214 word.Set(wordLex.NextToken()); |
|
215 err = addr.Input(word); |
|
216 |
|
217 if (err != KErrNone) |
|
218 { |
|
219 return; |
|
220 } |
|
221 |
|
222 TPtrC name; |
|
223 name.Set(wordLex.NextToken()); |
|
224 |
|
225 if (!name.Length()) |
|
226 { |
|
227 err = KErrBadName; |
|
228 return; |
|
229 } |
|
230 |
|
231 err = KErrNotFound; |
|
232 |
|
233 if (name.CompareF(aResult.iName) == 0 && ++count > aResult.iFlags) |
|
234 { |
|
235 err = KErrNone; |
|
236 } |
|
237 else |
|
238 { |
|
239 TPtrC alias; |
|
240 |
|
241 for ( |
|
242 alias.Set(wordLex.NextToken()); |
|
243 alias.Length(); |
|
244 alias.Set(wordLex.NextToken()) |
|
245 ){ |
|
246 if (alias.CompareF(aResult.iName) == 0 && ++count > aResult.iFlags) |
|
247 { |
|
248 err = KErrNone; |
|
249 break; |
|
250 } |
|
251 } |
|
252 } |
|
253 |
|
254 if (err == KErrNone) |
|
255 { |
|
256 aResult.iAddr = addr; |
|
257 aResult.iName = name; |
|
258 return; |
|
259 } |
|
260 } |
|
261 } |
|
262 |
|
263 void RHostsFile::GetByAddress(TNameRecord& aResult, TRequestStatus& err) |
|
264 { |
|
265 #if 1 |
|
266 const TInt ipv6 = (aResult.iAddr.Family() == KAfInet6); |
|
267 const TUint32 scope = TInetAddr::Cast(aResult.iAddr).Scope(); |
|
268 #endif |
|
269 Refresh(); |
|
270 |
|
271 TInt count = 0; // ...to select correct result for Next() |
|
272 for (;;) |
|
273 { |
|
274 TPtrC line; |
|
275 err = ReadLn(line); |
|
276 |
|
277 if (err != KErrNone) |
|
278 { |
|
279 if (err == KErrEof) |
|
280 { |
|
281 err = KErrNotFound; |
|
282 } |
|
283 return; |
|
284 } |
|
285 |
|
286 TLex wordLex(line); |
|
287 TInetAddr addr; |
|
288 |
|
289 TPtrC word; |
|
290 word.Set(wordLex.NextToken()); |
|
291 err = addr.Input(word); |
|
292 |
|
293 if (err != KErrNone) |
|
294 { |
|
295 return; |
|
296 } |
|
297 #if 0 |
|
298 if (!addr.CmpAddr(aResult().iAddr)) |
|
299 { |
|
300 continue; |
|
301 } |
|
302 #else |
|
303 // Plain IPv4 addresses in hosts will match the same |
|
304 // address in IPv4mapped format. However, IPv4 mapped |
|
305 // in hosts file will not match plain IPv4, if queried |
|
306 if (ipv6 && addr.Family() == KAfInet) |
|
307 addr.ConvertToV4Mapped(); |
|
308 // ... if the hosts file specifies the scope, |
|
309 // require it to match too. |
|
310 if (!addr.Match(aResult.iAddr) || |
|
311 (addr.Scope() != 0 && addr.Scope() != scope)) |
|
312 { |
|
313 continue; |
|
314 } |
|
315 #endif |
|
316 TPtrC name; |
|
317 name.Set(wordLex.NextToken()); |
|
318 while (name.Length() > 0) |
|
319 { |
|
320 if (++count > aResult.iFlags) |
|
321 { |
|
322 aResult.iAddr = addr; |
|
323 aResult.iName = name; |
|
324 err = KErrNone; |
|
325 return; |
|
326 } |
|
327 name.Set(wordLex.NextToken()); |
|
328 } |
|
329 err = count == 0 ? KErrBadName : KErrNotFound; |
|
330 return; |
|
331 } |
|
332 } |
|
333 |
|
334 void RHostsFile::Next(TNameRecord& /* aResult */, TRequestStatus& err) |
|
335 { |
|
336 #if 0 |
|
337 TPtrC alias; |
|
338 alias.Set(iWordLex.NextToken()); |
|
339 |
|
340 if (!alias.Length()) |
|
341 { |
|
342 err = KErrNotFound; |
|
343 return; |
|
344 } |
|
345 |
|
346 aResult.iName = alias; |
|
347 err = KErrNone; |
|
348 #else |
|
349 // Next() is not used now |
|
350 err = KErrNotFound; |
|
351 #endif |
|
352 } |
|
353 |