/*
 * UserTool - A Tool for managing users in a MuFS environment.
 *
 * $VER: stubs.c 37.1 (10.1.94)
 */

#include <exec/memory.h>
#include <exec/execbase.h>
#include <intuition/intuition.h>
#include <dos/dos.h>
#include <workbench/workbench.h>

#include <libraries/gadtools.h>
#include <libraries/reqtools.h>

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/reqtools_protos.h>
#include <clib/dos_protos.h>
#include <clib/icon_protos.h>
#include <clib/alib_protos.h>

#include <proto/multiuser.h>

#include <string.h>

#include "UserTool_rev.h"
#include "UserTool.h"
#include "parse.h"
#include "funcs.h"

extern struct ExecBase *ExecBase;
extern struct List *Users, *Groups;
extern UserStruct *CurUser;
extern GroupStruct *CurGroup;
extern LONG Tags[], PasswdFileDirty, GroupFileDirty;

UBYTE *Ptr;

int HOMEDIRClicked( void )
{
	BPTR HomeDirLock;

	if( ExecBase->LibNode.lib_Version < 39 )
		Ptr = (( struct StringInfo * )
			   UserToolGadgets[GD_HOMEDIR]->SpecialInfo )->Buffer;
	else
		GT_GetGadgetAttrs( UserToolGadgets[GD_HOMEDIR], UserToolWnd, 0L,
						  GTST_String, &Ptr, TAG_END );
	
	if( strcmp( CurUser->us_HomeDir, Ptr )) {
		strcpy( CurUser->us_HomeDir, Ptr );
		PasswdFileDirty = 1;
		HomeDirLock = Lock( CurUser->us_HomeDir, ACCESS_READ );
		if( !HomeDirLock ) {
			Tags[7] = ( LONG )"Home Directory Information";
			switch( rtEZRequest( "That directory does not exist, would you"
								" like to have it created?",
								"_Yes|Yes, with _Icon|_No", 0L,
								( struct TagItem * )Tags )) {
			case 0:
				break;	
			case 2: {
				struct DiskObject *HomeDirIcon;
				
				if( HomeDirIcon = GetDefDiskObject( WBDRAWER )) {
					if( !PutDiskObject( CurUser->us_HomeDir, HomeDirIcon ))
						rtEZRequest( "An error occured when trying to write"
									" the icon for the directory.", "_Ok", 0L,
									( struct TagItem * )Tags );
					FreeDiskObject( HomeDirIcon );
				} else	
					rtEZRequest( "An error occured when trying to get the"
								" default drawer icon.", "_Ok", 0L,
								( struct TagItem * )Tags );
			}
			case 1:
				if( HomeDirLock = CreateDir( CurUser->us_HomeDir )) {
					UnLock( HomeDirLock );
					rtEZRequest( "Directory successfully created.", "_Ok", 0L,
								( struct TagItem * )Tags );
				} else
					rtEZRequest( "An error occured when trying to create the"
								" directory.", "_Ok", 0L,
								( struct TagItem * )Tags );
				break;
			default:
				break;
			}
		} else
			UnLock( HomeDirLock );
	}

	return 1;
}

int REALNAMEClicked( void )
{
	if( ExecBase->LibNode.lib_Version < 39 )
		Ptr = (( struct StringInfo * )
			   UserToolGadgets[GD_REALNAME]->SpecialInfo )->Buffer;
	else
		GT_GetGadgetAttrs( UserToolGadgets[GD_REALNAME], UserToolWnd, 0L,
						  GTST_String, &Ptr, TAG_END );
	if( strcmp( CurUser->us_RealName, Ptr )) {
		strcpy( CurUser->us_RealName, Ptr );
		PasswdFileDirty = 1;
	}
	
	return 1;
}

int USERIDClicked( void )
{
	LONG OldID = CurUser->us_UserID;
	
	if( ExecBase->LibNode.lib_Version < 39 )
		CurUser->us_UserID = (( struct StringInfo * )
							  UserToolGadgets[GD_USERID]->SpecialInfo
							  )->LongInt;
	else
		GT_GetGadgetAttrs( UserToolGadgets[GD_USERID], UserToolWnd, 0L,
						  GTIN_Number, &CurUser->us_UserID, TAG_END );
	
	if( !UniqueID( CurUser )) {
		Tags[7] = ( LONG )"UserID Information";
		rtEZRequest( "User ID number is already in use, please enter another.",
					"_Ok", 0L, ( struct TagItem * )Tags );
		ActivateGadget( UserToolGadgets[GD_USERID], UserToolWnd, 0L );
	}
	
	if( CurUser->us_UserID != OldID )
		PasswdFileDirty = 1;
	
	return 1;
}

int PORTClicked( void )
{
	if( ExecBase->LibNode.lib_Version < 39 )
		Ptr = (( struct StringInfo * )
			   UserToolGadgets[GD_PORT]->SpecialInfo )->Buffer;
	else
		GT_GetGadgetAttrs( UserToolGadgets[GD_PORT], UserToolWnd, 0L,
					  GTST_String, &Ptr, TAG_END );
	if( strcmp( CurUser->us_Port, Ptr )) {
		strcpy( CurUser->us_Port, Ptr );
		PasswdFileDirty = 1;
	}

	return 1;
}

int USERSSTRClicked( void )
{
	if( ExecBase->LibNode.lib_Version < 39 )
		Ptr = (( struct StringInfo * )
			   UserToolGadgets[GD_USERSSTR]->SpecialInfo )->Buffer;
	else
		GT_GetGadgetAttrs( UserToolGadgets[GD_USERSSTR], UserToolWnd, 0L,
						  GTST_String, &Ptr, TAG_END );
	if( strcmp( CurUser->us_UserName, Ptr )) {
		GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
						  GTLV_Labels, ~0, TAG_DONE );
		strcpy( CurUser->us_UserName, Ptr );
		GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
						  GTLV_Labels, Users, TAG_DONE );
		PasswdFileDirty = 1;
	}
	
	return 1;
}

int USERSClicked( void )
{
	UpdateGadgets( UserToolMsg.Code );
	
	return 1;
}

int CHANGEPASSClicked( void )
{
	LONG CPTags[] = { RT_Window, 0L, RT_LockWindow, TRUE, RTGS_Invisible,
						TRUE, RTGS_TextFmt, 0L, RTGS_Flags, GSREQF_CENTERTEXT,
						TAG_END };
	UBYTE *PassBuf;
	LONG ListPos;
	
	if( PasswdFileDirty ) {
		Tags[7] = ( LONG )"Password File Information";
		if( rtEZRequest( "All changes to the password file must\n"
						"be flushed before a password can be changed.\n"
						"Shall I save the changes now?", "_Ok|_Cancel", 0L,
						( struct TagItem * )Tags )) {
			WritePasswdFile( 0L );
			PasswdFileDirty = 0;
		} else
			return 1;
	}
		
	if( PassBuf = AllocVec( sizeof( UBYTE ) * 64, MEMF_CLEAR )) {
		CPTags[1] = ( LONG )UserToolWnd;
		CPTags[7] = ( LONG )"Please enter the new password.";
		
		if( rtGetStringA( PassBuf, 64, "Changing Password", 0L,
						 ( struct TagItem * )CPTags )) {
			LONG LoginTags[] = { muT_Task, 0L, muT_UserID, 0L, muT_Password,
									 ( LONG )"", TAG_END };
			LoginTags[1] = ( LONG )FindTask( 0L );
			LoginTags[3] = ( LONG )CurUser->us_UserName;
			WritePasswdFile( CurUser );
			if( muLoginA(( struct TagItem * )LoginTags )) {
				LONG LogoutTags[] = { muT_Quiet, TRUE, TAG_END };
				Tags[7] = ( LONG )"Password Information";
				if( muPasswd( "", PassBuf ))
					rtEZRequest( "Password succesfully changed.", "_Ok",
								0L, ( struct TagItem * )Tags );
				else
					rtEZRequest( "Password change failed.", "_Ok",
								0L, ( struct TagItem * )Tags );
				muLogoutA(( struct TagItem * )LogoutTags );
			}
		}
		FreeVec( PassBuf );
	}

	return 1;
}

int NEWClicked( void )
{
	UserStruct *NewUser;
	LONG ListPos;
	
	if( NewUser = AllocVec( sizeof( UserStruct ), MEMF_CLEAR )) {
		GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
						  GTLV_Labels, ~0, TAG_DONE );
		NewUser->us_UserID = GetNextUID();
		strcpy( NewUser->us_UserName, "(new)" );
		strcpy( NewUser->us_Port, "cli" );
		GetVar( "DEFHOMEDIR", NewUser->us_HomeDir, muHOMEDIRSIZE, 0L );
		NewUser->us_Node.ln_Name = NewUser->us_UserName;
		NewList( &NewUser->us_Groups );
		Insert( Users, ( struct Node * )NewUser, ( struct Node * )CurUser );
		GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
						  GTLV_Labels, Users, TAG_DONE );
		CurUser = NewUser;
		ListPos = NodePos( Users, ( struct Node * )CurUser );
		GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
						  GTLV_Selected, ListPos, TAG_DONE );
		UpdateGadgets( ListPos );
		ActivateGadget( UserToolGadgets[GD_USERSSTR], UserToolWnd, 0L );
		PasswdFileDirty = 1;
	}

	return 1;
}

int DELETEClicked( void )
{
	UserStruct *OldUser = CurUser;

	if( CurUser->us_UserID == 65535 ) {
		Tags[7] = ( LONG )"Access Information";
		rtEZRequest( "That user is root. You cannot delete root.", "_Ok", 0L,
					( struct TagItem * )Tags );
		return 1;
	}

	if( CurUser->us_Node.ln_Succ != ( struct Node * )&( Users->lh_Tail ))
		CurUser = ( UserStruct * )CurUser->us_Node.ln_Succ;
	else if( CurUser->us_Node.ln_Pred != ( struct Node * )Users )
		CurUser = ( UserStruct * )CurUser->us_Node.ln_Pred;
	else {
		Tags[7] = ( LONG )"Password File Information";
		rtEZRequest( "You must have at least one user the password file.",
					"_Ok", 0L, ( struct TagItem * )Tags );
		return 1;
	}
	
	GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
					  GTLV_Labels, ~0, TAG_DONE );
	Remove(( struct Node * )OldUser );
	FreeVec( OldUser );
	GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
					  GTLV_Selected, UserToolMsg.Code, TAG_DONE );
	GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
					  GTLV_Labels, Users, TAG_DONE );
	UpdateGadgets( NodePos( Users, ( struct Node * )CurUser ));
	
	return PasswdFileDirty = 1;
}

int GROUPSTRClicked( void )
{
	if( ExecBase->LibNode.lib_Version < 39 )
		Ptr = (( struct StringInfo * )
			   UserToolGadgets[GD_GROUPSTR]->SpecialInfo )->Buffer;
	else
		GT_GetGadgetAttrs( UserToolGadgets[GD_GROUPSTR], UserToolWnd, 0L,
						  GTST_String, &Ptr, TAG_END );
	if( strcmp( CurGroup->gs_GroupID, Ptr )) {
		GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
						  GTLV_Labels, ~0, TAG_DONE );
		strcpy( CurGroup->gs_GroupID, Ptr );
		GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
						  GTLV_Labels, Groups, TAG_DONE );
		GroupFileDirty = 1;
	}
	
	return 1;
}

int GROUPSClicked( void )
{
	UpdateGroups( UserToolMsg.Code );
	
	return 1;
}

int NEWGROUPClicked( void )
{
	GroupStruct *NewGroup;
	ULONG ListPos, GID;
	LONG NMTags[] = { RT_Window, 0L, RT_LockWindow, TRUE, RTGS_TextFmt, 0L,
						   RTGS_Flags, GSREQF_CENTERTEXT, TAG_END };
	LONG IDTags[] = { RT_Window, 0L, RT_LockWindow, TRUE, RTGL_TextFmt, 0L,
						  RTGL_ShowDefault, TRUE, TAG_END };
	UBYTE NameBuf[muGROUPNAMESIZE];

	NameBuf[0] = '\0';
	NMTags[1] = IDTags[1] = ( LONG )UserToolWnd;
	NMTags[5] = ( LONG )"Please enter the name for this new group.";
	if(!( rtGetStringA( NameBuf, 64, "New Group Name", 0L,
					   ( struct TagItem * )NMTags )))
		return 1;

	GID = GetNextGID();
	IDTags[5] = ( LONG )"Please enter the ID for this new group.";
	if(!( rtGetLongA( &GID, "New Group ID", 0L, ( struct TagItem * )IDTags )))
		return 1;
	
	if( NewGroup = AllocVec( sizeof( GroupStruct ), MEMF_CLEAR )) {
		GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
						  GTLV_Labels, ~0, TAG_DONE );
		strcpy( NewGroup->gs_GroupID, "(new)" );
		NewGroup->gs_GID = GID;
		NewGroup->gs_MgrID = CurUser->us_UserID;
		strcpy( NewGroup->gs_Name, NameBuf );
		NewGroup->gs_Node.ln_Name = NewGroup->gs_GroupID;
		Insert( Groups, ( struct Node * )NewGroup, ( struct Node * )CurGroup );
		GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
						  GTLV_Labels, Groups, TAG_DONE );
		CurGroup = NewGroup;
		ListPos = NodePos( Groups, ( struct Node * )CurGroup );
		GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
						  GTLV_Selected, ListPos, TAG_DONE );
		UpdateMember();
		ActivateGadget( UserToolGadgets[GD_GROUPSTR], UserToolWnd, 0L );
		GroupFileDirty = 1;
	}

	return 1;
}

int DELETEGROUPClicked( void )
{
	GroupStruct *OldGroup = CurGroup;
	UserStruct *TmpUser;
	
	if( CurGroup->gs_Node.ln_Succ != ( struct Node * )&( Groups->lh_Tail ))
		CurGroup = ( GroupStruct * )CurGroup->gs_Node.ln_Succ;
	else if( CurGroup->gs_Node.ln_Pred != ( struct Node * )Groups )
		CurGroup = ( GroupStruct * )CurGroup->gs_Node.ln_Pred;
	else {
		Tags[7] = ( LONG )"Group File Information";
		rtEZRequest( "You must have at least one group the group file.",
					"_Ok", 0L, ( struct TagItem * )Tags );
		return 1;
	}
	
	GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
					  GTLV_Labels, ~0, TAG_DONE );
	for( TmpUser = ( UserStruct * )Users->lh_Head; TmpUser->us_Node.ln_Succ;
		TmpUser = ( UserStruct * )TmpUser->us_Node.ln_Succ )
		RemoveGroupFromUser( TmpUser->us_UserID, OldGroup->gs_GID );
	Remove(( struct Node * )OldGroup );
	FreeVec( OldGroup );
	GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
					  GTLV_Selected, UserToolMsg.Code, TAG_DONE );
	GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
					  GTLV_Labels, Groups, TAG_DONE );
	UpdateMember();
	
	return GroupFileDirty = 1;
}

void DoMEMBER( LONG Selection )
{
	UserStruct *User;

	if( CurUser->us_UserID == CurGroup->gs_MgrID ) {
		Tags[7] = ( LONG )"Group File Information";
		rtEZRequest( "You cannot remove the manager of a group.\nYou must"
					" select the new manager and the old one will\n"
					" automatically be removed from the status of manager.",
					"_Ok", 0L, ( struct TagItem * )Tags );
		GT_SetGadgetAttrs( UserToolGadgets[GD_MEMBER], UserToolWnd, 0l,
						  GTMX_Active, 2, TAG_DONE );
		return;
	}

	switch( Selection ) {
	case 0:
		RemoveGroupFromUser( CurUser->us_UserID, CurGroup->gs_GID );
		break;
	case 1:
		AddGroupToUser( CurUser->us_UserID, CurGroup->gs_GID );
		break;
	case 2:
		Tags[7] = ( LONG )"Group File Information";
		User = UserWithID( CurGroup->gs_MgrID );
		if( rtEZRequest( "%s is currently manager of that group.\n"
						"Make %s the new manager?", "_Ok|_Cancel", 0L,
						( struct TagItem * )Tags, User ? User->us_UserName :
						( UBYTE * )"<error>", CurUser->us_UserName )) {
			CurGroup->gs_MgrID = CurUser->us_UserID;
		} else {
			UpdateMember();
			return;
		}
		break;
	}
	GroupFileDirty = 1;
}

int MEMBERClicked( void )
{
	DoMEMBER( UserToolMsg.Code );

	return 1;
}

int UserToolSAVE( void )
{
	if(!( PasswdFileDirty || GroupFileDirty )) {
		Tags[7] = ( LONG )"UserTool Information";
		rtEZRequest( "There are no changes to be saved.", "_Ok", 0L,
					( struct TagItem * )Tags );
	}
	
	if( PasswdFileDirty ) {
		WritePasswdFile( 0L );
		PasswdFileDirty = 0;
	}

	if( GroupFileDirty ) {
		WriteGroupFile();
		GroupFileDirty = 0;
	}

	return 1;
}

int UserToolABOUT( void )
{
	Tags[7] = ( LONG )"UserTool Information";
	rtEZRequest( VERS" ("DATE")\nby Michael D. Bayne\n\nbaynemd@nextwork."
				"rose-hulman.edu", "_Ok", 0L, ( struct TagItem * )Tags );
	
	return 1;
}

int UserToolQUIT( void )
{
	UBYTE *String;

	if( PasswdFileDirty || GroupFileDirty ) {
		if( PasswdFileDirty && GroupFileDirty )
			String = "The password and group files have not been saved.\nSave"
				" them before quitting?";
		else if( PasswdFileDirty )
			String = "The password file has not been saved.\nSave it before"
				" quitting?";
		else
			String = "The group file has not been saved.\nSave it before"
				" quitting?";
		Tags[7] = ( LONG )"File Request";
		switch( rtEZRequest( String, "_Yes|_No|_Don't Quit", 0L,
							( struct TagItem * )Tags )) {
		case 1:
			UserToolSAVE();
			break;
		case 2:
			break;
		case 0:
			return 1;
		default:
			break;
		}
	}
	
	return 0;
}

int UserToolCloseWindow( void )
{
	return UserToolQUIT();
}

int UserToolVanillaKey( void )
{
	LONG Selection;

	switch( UserToolMsg.Code ) {
	case 'U':	
		if( CurUser->us_Node.ln_Pred != ( struct Node * )Users ) {
			Selection = NodePos( Users, ( struct Node * )CurUser );
			GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
							  GTLV_Selected, Selection - 1, TAG_DONE );
			UpdateGadgets( Selection - 1 );
		}
		break;
	case 'u':
		if( CurUser->us_Node.ln_Succ != ( struct Node * )&Users->lh_Tail ) {
			Selection = NodePos( Users, ( struct Node * )CurUser );
			GT_SetGadgetAttrs( UserToolGadgets[GD_USERS], UserToolWnd, 0l,
							  GTLV_Selected, Selection + 1, TAG_DONE );
			UpdateGadgets( Selection + 1 );
		}
		break;
	case 'n':
		return NEWClicked();
	case 'd':
		return DELETEClicked();
	case '\t':
	case 'i':
		ActivateGadget( UserToolGadgets[GD_USERID], UserToolWnd, 0L );
		break;
	case 'h':
		ActivateGadget( UserToolGadgets[GD_HOMEDIR], UserToolWnd, 0L );
		break;
	case 'r':
		ActivateGadget( UserToolGadgets[GD_REALNAME], UserToolWnd, 0L );
		break;
	case 'p':
		ActivateGadget( UserToolGadgets[GD_PORT], UserToolWnd, 0L );
		break;
	case 'c':
		return CHANGEPASSClicked();
	case 'G':
		if( CurGroup->gs_Node.ln_Pred != ( struct Node * )Groups ) {
			Selection = NodePos( Groups, ( struct Node * )CurGroup );
			GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
							  GTLV_Selected, Selection - 1, TAG_DONE );
			UpdateGroups( Selection - 1 );
		}
		break;
	case 'g':
		if( CurGroup->gs_Node.ln_Succ != ( struct Node * )&Groups->lh_Tail ) {
			Selection = NodePos( Groups, ( struct Node * )CurGroup );
			GT_SetGadgetAttrs( UserToolGadgets[GD_GROUPS], UserToolWnd, 0l,
							  GTLV_Selected, Selection + 1, TAG_DONE );
			UpdateGroups( Selection + 1 );
		}
		break;
	case 'o':
		GT_SetGadgetAttrs( UserToolGadgets[GD_MEMBER], UserToolWnd, 0l,
						  GTMX_Active, 0, TAG_DONE );
		DoMEMBER( 0 );
		break;
	case 'm':
		GT_SetGadgetAttrs( UserToolGadgets[GD_MEMBER], UserToolWnd, 0l,
						  GTMX_Active, 1, TAG_DONE );
		DoMEMBER( 1 );
		break;
	case 'a':
		GT_SetGadgetAttrs( UserToolGadgets[GD_MEMBER], UserToolWnd, 0l,
						  GTMX_Active, 2, TAG_DONE );
		DoMEMBER( 2 );
		break;
	case 'e':
		NEWGROUPClicked();
		break;
	case 'l':
		DELETEGROUPClicked();
	default:
		break;
	}

	return 1;
}
