tcpiputils/dnd/src/hosts.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dnd/src/hosts.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,353 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// hosts.cpp - name resolver hosts file parser module
+//
+
+#include <f32file.h>	// RFs
+#include <in_sock.h>	// TInetAddr
+#include "hosts.h"	// this
+
+RHostsFile::RHostsFile(RFs &aFs):
+	iBuf(NULL), iFs(aFs), iRefreshed(0)
+{
+}
+
+RHostsFile::~RHostsFile()
+{
+	if (iBuf)
+	{
+		delete iBuf;
+		iBuf = NULL;
+	}
+}
+
+//
+//
+//
+
+TInt RHostsFile::Open()
+{
+	if (iBuf)
+	{
+		return KErrNone;
+	}
+
+	const TDesC &file_name = HOSTS_FILE;
+	TInt err;
+
+	RFile file;
+	err = file.Open(iFs, file_name, EFileStreamText | EFileRead | EFileShareAny);
+
+	if (err != KErrNone)
+	{
+		return err;
+	}
+
+	TInt size;
+	err = file.Size(size);
+	
+	if (err != KErrNone)
+	{
+		file.Close();
+		return err;
+	}
+
+	iBuf = HBufC::NewMax(size);
+
+	if (iBuf == NULL)
+	{
+		file.Close();
+		return KErrNoMemory;
+	}
+
+	// Unicode fix.
+
+	HBufC8 *tempBuf = HBufC8::NewMax(size);
+
+	if (tempBuf == NULL)
+		{
+		delete iBuf;
+		iBuf = NULL;
+		file.Close();
+		return KErrNoMemory;
+		}
+
+	TPtr8 tempPtr(tempBuf->Des());
+	err = file.Read(tempPtr);
+
+	if (err != KErrNone)
+		{
+		delete iBuf;
+		delete tempBuf;
+		iBuf = NULL;
+		file.Close();
+		return err;
+		}
+
+	TPtr p(iBuf->Des());
+	p.Copy(tempPtr);
+	delete tempBuf;
+
+	iCharLex = p;
+	file.Close();
+
+	return KErrNone;
+}
+
+void RHostsFile::Close()
+{
+	delete iBuf;
+	iBuf = NULL;
+}
+
+//
+//
+//
+
+TInt RHostsFile::ReadLn(TPtrC& aLine)
+{
+	do
+	{
+		iCharLex.Mark();
+
+		if (iCharLex.Eos())
+		{
+			return KErrEof;
+		}
+		
+		TChar ch = 0;
+
+		while (!iCharLex.Eos() && (ch = iCharLex.Peek(), ch != '\n' && ch != '\r' && ch != '#' ))
+		{
+			iCharLex.Inc();
+		}
+
+		aLine.Set(iCharLex.MarkedToken());
+
+		if (ch == '#')
+		{
+			while (!iCharLex.Eos() && (ch = iCharLex.Peek(), ch != '\n' && ch != '\r'))
+			{
+				iCharLex.Inc();
+			}
+		}
+		
+		while (!iCharLex.Eos() && (ch = iCharLex.Peek(), ch == '\n' || ch == '\r'))
+		{
+			iCharLex.Inc();
+		}
+	}
+	while (!aLine.Length());
+	
+	return KErrNone;
+}
+
+
+void RHostsFile::Rewind()
+{
+	if (iBuf)
+		{
+		TPtr p(iBuf->Des());
+		iCharLex = p;
+		}
+}
+
+void RHostsFile::Refresh()
+	{
+	const TDesC &file_name = HOSTS_FILE;
+	TInt err;
+
+	TTime modified;
+	err = iFs.Modified(file_name, modified);
+	
+	if (err == KErrNone)
+		{
+		if (iRefreshed < modified)
+			{
+			Close();
+			Open();
+			iRefreshed = modified;
+			return;
+			}
+		}
+	Rewind();
+	}
+
+//
+//
+//
+
+void RHostsFile::GetByName(TNameRecord& aResult, TRequestStatus& err)
+{
+	Refresh();
+	TInt count = 0;	// ...to select correct result for Next()
+
+	for (;;)
+	{
+		TPtrC line;
+		err = ReadLn(line);
+		
+		if (err != KErrNone)
+		{
+			if (err == KErrEof)
+			{
+				err = KErrNotFound;
+			}
+			return;
+		}
+		
+		TLex wordLex(line);
+		TInetAddr addr;
+		TPtrC word;
+
+		word.Set(wordLex.NextToken());
+		err = addr.Input(word);
+
+		if (err != KErrNone)
+		{
+			return;
+		}
+
+		TPtrC name;
+		name.Set(wordLex.NextToken());
+
+		if (!name.Length())
+		{
+			err = KErrBadName;
+			return;
+		}
+
+		err = KErrNotFound;
+		
+		if (name.CompareF(aResult.iName) == 0 && ++count > aResult.iFlags)
+		{
+			err = KErrNone;
+		}
+		else
+		{
+			TPtrC alias;
+
+			for (
+				alias.Set(wordLex.NextToken());
+				alias.Length();
+				alias.Set(wordLex.NextToken())
+			){
+				if (alias.CompareF(aResult.iName) == 0 && ++count > aResult.iFlags)
+				{
+					err = KErrNone;
+					break;
+				}
+			}
+		}
+
+		if (err == KErrNone)
+		{
+			aResult.iAddr = addr;
+			aResult.iName = name;
+			return;
+		}
+	}
+}
+
+void RHostsFile::GetByAddress(TNameRecord& aResult, TRequestStatus& err)
+{
+#if 1
+	const TInt ipv6 = (aResult.iAddr.Family() == KAfInet6);
+	const TUint32 scope = TInetAddr::Cast(aResult.iAddr).Scope();
+#endif
+	Refresh();
+
+	TInt count = 0; // ...to select correct result for Next() 
+	for (;;)
+	{
+		TPtrC line;
+		err = ReadLn(line);
+		
+		if (err != KErrNone)
+		{
+			if (err == KErrEof)
+			{
+				err = KErrNotFound;
+			}
+			return;
+		}
+		
+		TLex wordLex(line);
+		TInetAddr addr;
+
+		TPtrC word;
+		word.Set(wordLex.NextToken());
+		err = addr.Input(word);
+
+		if (err != KErrNone)
+		{
+			return;
+		}
+#if 0
+		if (!addr.CmpAddr(aResult().iAddr))
+		{
+			continue;
+		}
+#else
+		// Plain IPv4 addresses in hosts will match the same
+		// address in IPv4mapped format. However, IPv4 mapped
+		// in hosts file will not match plain IPv4, if queried
+		if (ipv6 && addr.Family() == KAfInet)
+			addr.ConvertToV4Mapped();
+		// ... if the hosts file specifies the scope,
+		// require it to match too.
+		if (!addr.Match(aResult.iAddr) ||
+			(addr.Scope() != 0 && addr.Scope() != scope))
+		{
+			continue;
+		}
+#endif
+		TPtrC name;
+		name.Set(wordLex.NextToken());
+		while (name.Length() > 0)
+			{
+			if (++count > aResult.iFlags)
+				{
+				aResult.iAddr = addr;
+				aResult.iName = name;
+				err = KErrNone;
+				return;
+				}
+			name.Set(wordLex.NextToken());
+			}
+		err = count == 0 ? KErrBadName : KErrNotFound;
+		return;
+	}
+}
+
+void RHostsFile::Next(TNameRecord& /* aResult */, TRequestStatus& err)
+{
+#if 0
+	TPtrC alias;
+	alias.Set(iWordLex.NextToken());
+
+	if (!alias.Length())
+	{
+		err = KErrNotFound;
+		return;
+	}
+
+	aResult.iName = alias;
+	err = KErrNone;
+#else
+	// Next() is not used now
+	err = KErrNotFound;
+#endif
+}
+