/* -*- Mode: C; tab-width: 4 -*-
 *
 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <Secret.h>
#include "RegistrationPage.h"
#include "resource.h"

#include "ConfigPropertySheet.h"
extern "C"
{
#include <ClientCommon.h>
}
#include <WinServices.h>

#define MAX_KEY_LENGTH 255


IMPLEMENT_DYNCREATE(CRegistrationPage, CPropertyPage)

//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::CRegistrationPage
//---------------------------------------------------------------------------------------------------------------------------

CRegistrationPage::CRegistrationPage()
:
	CPropertyPage(CRegistrationPage::IDD),
	m_ignoreChanges( false ),
	m_hostnameSetupKey( NULL ),
	m_registrationSetupKey( NULL ),
	m_statusKey( NULL )
{
	//{{AFX_DATA_INIT(CRegistrationPage)
	//}}AFX_DATA_INIT

	OSStatus err;

	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\Hostnames", 0,
	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_hostnameSetupKey, NULL );
	check_noerr( err );

	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\Setup\\" kServiceDynDNSRegistrationDomains, 0,
	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_registrationSetupKey, NULL );
	check_noerr( err );

	err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, kServiceParametersNode L"\\DynDNS\\State\\Hostnames", 0,
	                      NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &m_statusKey, NULL );
	check_noerr( err );

	
}

CRegistrationPage::~CRegistrationPage()
{
	if ( m_hostnameSetupKey )
	{
		RegCloseKey( m_hostnameSetupKey );
		m_hostnameSetupKey = NULL;
	}

	if ( m_registrationSetupKey )
	{
		RegCloseKey( m_registrationSetupKey );
		m_registrationSetupKey = NULL;
	}

	if ( m_statusKey )
	{
		RegCloseKey( m_statusKey );
		m_statusKey = NULL;
	}
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::DoDataExchange
//---------------------------------------------------------------------------------------------------------------------------

void CRegistrationPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRegistrationPage)
	//}}AFX_DATA_MAP
	DDX_Control(pDX, IDC_HOSTNAME, m_hostnameControl);
	DDX_Control(pDX, IDC_USERNAME, m_usernameControl);
	DDX_Control(pDX, IDC_PASSWORD, m_passwordControl);
	DDX_Control(pDX, IDC_ADVERTISE_SERVICES, m_advertiseServices);
}

BEGIN_MESSAGE_MAP(CRegistrationPage, CPropertyPage)
	//{{AFX_MSG_MAP(CRegistrationPage)
	//}}AFX_MSG_MAP
	ON_EN_CHANGE(IDC_HOSTNAME, OnEnChangeHostname)
	ON_EN_CHANGE(IDC_USERNAME, OnEnChangeUsername)
	ON_EN_CHANGE(IDC_PASSWORD, OnEnChangePassword)
	ON_BN_CLICKED(IDC_ADVERTISE_SERVICES, OnBnClickedAdvertiseServices)
END_MESSAGE_MAP()


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::OnEnChangedHostname
//---------------------------------------------------------------------------------------------------------------------------

void CRegistrationPage::OnEnChangeHostname()
{
	if ( !m_ignoreChanges )
	{
		SetModified( TRUE );
	}
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::OnEnChangedUsername
//---------------------------------------------------------------------------------------------------------------------------

void CRegistrationPage::OnEnChangeUsername()
{
	if ( !m_ignoreChanges )
	{
		SetModified( TRUE );
	}
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::OnEnChangedPassword
//---------------------------------------------------------------------------------------------------------------------------

void CRegistrationPage::OnEnChangePassword()
{
	if ( !m_ignoreChanges )
	{
		SetModified( TRUE );
	}
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::OnBnClickedAdvertiseServices
//---------------------------------------------------------------------------------------------------------------------------

void CRegistrationPage::OnBnClickedAdvertiseServices()
{
	if ( !m_ignoreChanges )
	{
		SetModified( TRUE );
	}
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::SetModified
//---------------------------------------------------------------------------------------------------------------------------

void CRegistrationPage::SetModified( BOOL bChanged )
{
	m_modified = bChanged ? true : false;

	CPropertyPage::SetModified( bChanged );
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::OnSetActive
//---------------------------------------------------------------------------------------------------------------------------

BOOL
CRegistrationPage::OnSetActive()
{
	TCHAR	name[kDNSServiceMaxDomainName + 1];
	DWORD	nameLen = ( kDNSServiceMaxDomainName + 1 ) * sizeof( TCHAR );
	DWORD	err;

	BOOL b = CPropertyPage::OnSetActive();

	m_ignoreChanges = true;
	m_modified = FALSE;
	
	if ( m_hostnameSetupKey )
	{
		err = RegQueryValueEx( m_hostnameSetupKey, L"", NULL, NULL, (LPBYTE) name, &nameLen );

		if ( !err )
		{
			char	hostnameUTF8[ 256 ];
			char	outDomain[ 256 ];
			char	outUsername[ 256 ];
			char	outPassword[ 256 ];
			CString hostname = name;
			CString username;
			CString password;

			m_hostnameControl.SetWindowText( hostname );

			StringObjectToUTF8String( hostname, hostnameUTF8, sizeof( hostnameUTF8 ) );

			if ( LsaGetSecret( hostnameUTF8, outDomain, sizeof( outDomain ) / sizeof( TCHAR ), outUsername, sizeof( outUsername ) / sizeof( TCHAR ), outPassword, sizeof( outPassword ) / sizeof( TCHAR ) ) )
			{
				username = outUsername;
				m_usernameControl.SetWindowText( username );

				password = outPassword;
				m_passwordControl.SetWindowText( password );
			}
		}
	}

	m_advertiseServices.SetCheck( 0 );

	if ( m_registrationSetupKey )
	{
		HKEY		subKey = NULL;
		DWORD		dwSize;
		DWORD		enabled = 0;
		TCHAR		subKeyName[MAX_KEY_LENGTH];
		DWORD		cSubKeys = 0;
		DWORD		cbMaxSubKey;
		DWORD		cchMaxClass;
		OSStatus	err;

		err = RegQueryInfoKey( m_registrationSetupKey, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
		if ( !err )
		{
			if ( cSubKeys > 0 )
			{	
				dwSize = MAX_KEY_LENGTH;
	            
				err = RegEnumKeyEx( m_registrationSetupKey, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
				if ( !err )
				{
					err = RegOpenKey( m_registrationSetupKey, subKeyName, &subKey );
					if ( !err )
					{
						dwSize = sizeof( DWORD );
						err = RegQueryValueEx( subKey, L"Enabled", NULL, NULL, (LPBYTE) &enabled, &dwSize );
						if ( !err && enabled )
						{
							m_advertiseServices.SetCheck( enabled );
						}

						RegCloseKey( subKey );
						subKey = NULL;
					}
				}
			}
		}
	}

	m_ignoreChanges = false;

	return b;
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::OnOK
//---------------------------------------------------------------------------------------------------------------------------

void
CRegistrationPage::OnOK()
{
	if ( m_modified )
	{
		Commit();
	}
}


//---------------------------------------------------------------------------------------------------------------------------
//	CRegistrationPage::Commit
//---------------------------------------------------------------------------------------------------------------------------

void
CRegistrationPage::Commit()
{
	CString	hostname;
	char	hostnameUTF8[ 256 ];
	CString username;
	char	usernameUTF8[ 256 ];
	CString password;
	char	passwordUTF8[ 256 ];
	DWORD	enabled = 1;
	BOOL	secret = FALSE;
	DWORD	err;

	m_hostnameControl.GetWindowText( hostname );
	hostname.MakeLower();
	hostname.TrimRight( '.' );
	StringObjectToUTF8String( hostname, hostnameUTF8, sizeof( hostnameUTF8 ) );
	
	m_usernameControl.GetWindowText( username );
	m_passwordControl.GetWindowText( password );
	
	if ( username.GetLength() && password.GetLength() )
	{
		StringObjectToUTF8String( username, usernameUTF8, sizeof( usernameUTF8 ) );	
		StringObjectToUTF8String( password, passwordUTF8, sizeof( passwordUTF8 ) );
		secret = TRUE;
	}

	if ( m_hostnameSetupKey != NULL )
	{
		err = RegSetValueEx( m_hostnameSetupKey, L"", 0, REG_SZ, (LPBYTE) (LPCTSTR) hostname, ( hostname.GetLength() + 1 ) * sizeof( TCHAR ) );
		require_noerr( err, exit );
		
		err = RegSetValueEx( m_hostnameSetupKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
		require_noerr( err, exit );

		if ( secret )
		{
			LsaSetSecret( hostnameUTF8, usernameUTF8, passwordUTF8 );
		}
	}

	if ( m_registrationSetupKey != NULL )
	{
		TCHAR		subKeyName[MAX_KEY_LENGTH];
		DWORD		cSubKeys = 0;
		DWORD		cbMaxSubKey;
		DWORD		cchMaxClass;
		DWORD		dwSize;
		int			i;
		OSStatus	err = kNoErr;

		// First, remove all the entries that are there

		err = RegQueryInfoKey( m_registrationSetupKey, NULL, NULL, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, NULL, NULL, NULL, NULL, NULL );       
		if ( !err )
		{
			for ( i = 0; i < (int) cSubKeys; i++ )
			{	
				dwSize = MAX_KEY_LENGTH;
		            
				err = RegEnumKeyEx( m_registrationSetupKey, 0, subKeyName, &dwSize, NULL, NULL, NULL, NULL );
				require_noerr( err, exit );
					
				err = RegDeleteKey( m_registrationSetupKey, subKeyName );
				require_noerr( err, exit );
			}
		}

		if ( m_advertiseServices.GetCheck() )
		{
			const char	* domainUTF8;
			CString		  domain;
			char		  label[ 64 ];
			HKEY		  subKey = NULL;

			domainUTF8	= GetNextLabel( hostnameUTF8, label );
			domain		= domainUTF8;

			err = RegCreateKeyEx( m_registrationSetupKey, domain, 0,
									 NULL, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &subKey, NULL );
			if ( !err )
			{
				err = RegSetValueEx( subKey, L"Enabled", 0, REG_DWORD, (LPBYTE) &enabled, sizeof( DWORD ) );
				check_noerr( err );

				RegCloseKey( subKey );
				subKey = NULL;
			}

			if ( secret )
			{
				LsaSetSecret( domainUTF8, usernameUTF8, passwordUTF8 );
			}
		}
	}

exit:

	return;
}
