/* --- CONFIG_USERS.CPP ---
/  
/ Written by Phil Himsworth, 2001-2002.
/
/*/

#include <windows.h>
#include "types.h"
#include "main.h"
#include "resource.h"
#include "plugin.h"

extern winampGeneralPurposePlugin plugin;

int securepassword;
int pass_debug;

extern HWND UsersWnd;

// --------------------------------------------------------------------------------
// WindowProc for Config dialog
BOOL CALLBACK ConfigUsersWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	int nItem;
	HWND hwndList;

	UsersWnd = hwndDlg;
	

	char ini_file[MAX_PATH], *p;
	hwndList = GetDlgItem(hwndDlg, IDC_USERS); 
	GetModuleFileName(plugin.hDllInstance,ini_file,sizeof(ini_file));
	p=ini_file+lstrlen(ini_file);
	while (p >= ini_file && *p != '\\') p--;
	if (++p >= ini_file) *p = 0;
	lstrcat(ini_file,"gen_httpsrv.ini");

	switch (uMsg)
	{
	case WM_INITDIALOG:

		UpdateUserList((char*)&ini_file, hwndList);

		PostMessage(hwndList,LB_SETCURSEL,0,0);
		UpdateUserInfoBoxes(hwndDlg,hwndList,ini_file,0);

		break;





	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDC_USERS:
			switch (HIWORD(wParam)) 
			{ 
			case LBN_SELCHANGE:
				hwndList = GetDlgItem(hwndDlg, IDC_USERS);
				nItem = SendMessage(hwndList, LB_GETCURSEL, 0, 0); 
				UpdateUserInfoBoxes(hwndDlg,hwndList,ini_file,nItem);

				break;
			}

			break;
			case IDC_UPDATE:
				UpdateDlgUser((char*)&ini_file, hwndDlg, hwndList);
				UpdateUserList((char*)&ini_file, hwndList);
				break;

			case IDC_DELETE:
				DeleteDlgUser((char*)&ini_file, hwndDlg, hwndList);
				UpdateUserList((char*)&ini_file, hwndList);
				UpdateUserInfoBoxes(hwndDlg,hwndList,(char*)&ini_file,0);
				break;

		}
		break;

	}
	return false;
}

// --------------------------------------------------------------------------------
// Enters use details into relevant boxes
void UpdateUserInfoBoxes(HWND hwndDlg, HWND hwndList, char * ini_file, int item)
{
	char userkey[30];
	char username[20];
	char password[40];
	int access;

	SendMessage(hwndList,LB_GETTEXT, item, (LPARAM)&username);

	SetDlgItemText(hwndDlg,IDC_USERNAME,username);
	GetPrivateProfileString("Users",username,"password",(char*)&password,40,ini_file);
	if (StrComp(username,"anon"))
		SetDlgItemText(hwndDlg,IDC_PASSWORD,"");
	else
		SetDlgItemText(hwndDlg,IDC_PASSWORD,password);

	wsprintf(userkey, "#%s_access", username);
	access = GetPrivateProfileInt("Users",userkey,AUTH_ANON,ini_file);

	DisplayDlgAccess(hwndDlg,access);

}

// --------------------------------------------------------------------------------
// Marks check boxes according to user access levels
void DisplayDlgAccess(HWND hwndDlg, int access)
{
	if (access & AUTH_SERVER)
		CheckDlgButton(hwndDlg,IDC_AUTH_SHUTDOWN,BST_CHECKED);
	else
		CheckDlgButton(hwndDlg,IDC_AUTH_SHUTDOWN,BST_UNCHECKED);

	if (access & AUTH_CONTROL)
		CheckDlgButton(hwndDlg,IDC_AUTH_CONTROL,BST_CHECKED);
	else
		CheckDlgButton(hwndDlg,IDC_AUTH_CONTROL,BST_UNCHECKED);

	if (access & AUTH_CLEAR)
		CheckDlgButton(hwndDlg,IDC_AUTH_CLEAR,BST_CHECKED);
	else
		CheckDlgButton(hwndDlg,IDC_AUTH_CLEAR,BST_UNCHECKED);

	if (access & AUTH_PLAYLIST)
		CheckDlgButton(hwndDlg,IDC_AUTH_PLAYLIST,BST_CHECKED);
	else
		CheckDlgButton(hwndDlg,IDC_AUTH_PLAYLIST,BST_UNCHECKED);

	if (access & AUTH_DOWNLOAD)
		CheckDlgButton(hwndDlg,IDC_AUTH_DOWNLOAD,BST_CHECKED);
	else
		CheckDlgButton(hwndDlg,IDC_AUTH_DOWNLOAD,BST_UNCHECKED);

	if (access & AUTH_BROWSE)
		CheckDlgButton(hwndDlg,IDC_AUTH_BROWSE,BST_CHECKED);
	else
		CheckDlgButton(hwndDlg,IDC_AUTH_BROWSE,BST_UNCHECKED);
}

// --------------------------------------------------------------------------------
// Retrieves user access from check boxes
int GetDlgAccess(HWND hwndDlg)
{
	int access = 0;
	if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_BROWSE) == BST_CHECKED)
		access += 1;
	if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_DOWNLOAD) == BST_CHECKED)
		access += 2;
	if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_PLAYLIST) == BST_CHECKED)
		access += 4;
	if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_CLEAR) == BST_CHECKED)
		access += 8;
	if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_CONTROL) == BST_CHECKED)
		access += 16;
	if (IsDlgButtonChecked(hwndDlg,IDC_AUTH_SERVER) == BST_CHECKED)
		access += 32;

	return access;
}

// --------------------------------------------------------------------------------
// Builds a list of usernames from the ini file
user * RetrieveUsers(user * users, char * ini_file)
{
	bool anon = false;
	int userslen, uptr, tptr;
	char t_users[10000];

	userslen = GetPrivateProfileSection("Users",(char*)t_users,10000,ini_file);
	uptr = 0;
	tptr = 0;

	while(uptr < userslen)		// until we're done
	{
		// weedle through to the end, replacing the equals sign as we go.
		tptr = uptr;
		//MessageBox(NULL,users+uptr,"start of section",MB_OK | MB_TOPMOST);
		while(t_users[tptr] != 0)
		{
			if (t_users[tptr] == '=')		// equals - make it a null
				t_users[tptr] = 0;
			tptr++;
		}
		if (StrComp("anon",t_users+uptr))
			anon = true;
		user * newuser = new user;
		lstrcpy(newuser->name,t_users+uptr);
		newuser->next = users;
		users = newuser;
		
		tptr++;							// move to char after null
		//if (users[tptr] == 0)			// if it's null too, that's the lot; end
		//	break;
		if (t_users[tptr] == '#')			// if it's a hash, it's the access level - skip it
		{
			while(t_users[tptr] != 0)		
				tptr++;
			tptr++;
		//	if (users[tptr] == 0)		// if that's null it's the end
		//		break;
		}


		uptr = tptr;					// move on to next
	}

	if (!anon)				// anonymous user has not been added; add it
	{
		user * anonuser = new user;
		lstrcpy(anonuser->name,"anon");
		anonuser->next = users;
		users = anonuser;
	}

	return users;
}


// --------------------------------------------------------------------------------
// Enters usernames into the dialog box list
void UpdateUserList(char * ini_file, HWND hwndList)
{

	SendMessage(hwndList, LB_RESETCONTENT, 0, 0);

	user * users = NULL;
	users = RetrieveUsers(users, ini_file);		// fill list 'users' with usernames
	user * current = users;				// pointer to start of list

	while(current != NULL)
	{
		SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) (current->name)); // add it
		current = current->next;
		delete users;
		users = current;
	}
}



// --------------------------------------------------------------------------------
// Updates user information in the ini file
void UpdateDlgUser(char * ini_file, HWND hwndDlg, HWND hwndList)
{

	char username[20];
	char password[40];

	int access = GetDlgAccess(hwndDlg);

	GetDlgItemText(hwndDlg,IDC_USERNAME,(char*)&username,20);
	GetDlgItemText(hwndDlg,IDC_PASSWORD,(char*)&password,40);

	if (StrComp(password,"password"))
	{
		MessageBox(hwndDlg,"Choosing a slightly better password than 'password' provides better security.","WAWI User Config",MB_OK | MB_ICONINFORMATION);
		return;
	}

	UpdateUser(ini_file,username,password,access);
}

// --------------------------------------------------------------------------------
// Adds/updates user with passed-in information
void UpdateUser(char * ini_file,char * username, char * password, int access)
{
	
	char debugtemp[100];
	char oldmd5password[40];
	char md5password[40];
	char userkey[30];
	char str_access[5];

	wsprintf(str_access,"%d",access);
	
	if (pass_debug == 1)
	{
		wsprintf(debugtemp,"User: %s\nPassword: %s\nAccess: %d",username,password,access);
		MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
	}

	wsprintf(userkey,"#%s_access",username);
	if (securepassword == 1)
	{
		MD5(password,(char*)&md5password,40);
		if (pass_debug == 1)
		{
			wsprintf(debugtemp,"MD5 encoded: %s",md5password);
			MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
		}
	}
	else
	{
		ToBase64(password,(char*)&md5password);
		if (pass_debug == 1)
		{
		wsprintf(debugtemp,"Base64 encoded: %s",md5password);
		MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
		}
	}

	GetPrivateProfileString("Users",username,"password",(char*)&oldmd5password,40,ini_file);
	if (pass_debug == 1)
	{
		wsprintf(debugtemp,"Previous password (or 'password' if none):\n%s",oldmd5password);
		MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
	}

	if (!StrComp(password,oldmd5password))
	{
		WritePrivateProfileString("Users",username,md5password,ini_file);
		if (pass_debug == 1)
		{
			wsprintf(debugtemp,"Written to gen_httpsrv.ini - \nUser: %s\nPassword: %s",username,md5password);
			MessageBox(NULL,debugtemp,"WAWI Password Debug",MB_OK | MB_TOPMOST);
		}
	}
	WritePrivateProfileString("Users",userkey,str_access,ini_file);
}

// --------------------------------------------------------------------------------
// Deletes a user from the user dialog
void DeleteDlgUser(char * ini_file, HWND hwndDlg, HWND hwndList)
{
	char username[20];

	GetDlgItemText(hwndDlg,IDC_USERNAME,(char*)&username,20);
	DeleteUser(ini_file,username);
}

// --------------------------------------------------------------------------------
// Deletes a user
void DeleteUser(char * ini_file, char * username)
{
	char userkey[30];
	wsprintf(userkey,"#%s_access",username);
	WritePrivateProfileString("Users",username,NULL,ini_file);
	WritePrivateProfileString("Users",userkey,NULL,ini_file);
}
