{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\fswiss Helvetica;}
\paperw11760
\paperh7800
\margl120
\margr120
{\colortbl;\red0\green0\blue0;}
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b\i0\ulnone\fs24\fc1\cf1 #import "ArchieApp.h"\
#import "FTPObject.h"\
#import "MyBrowserCell.h"\
#import "NetrcEntry.h"\
#import "PasswordField.h"\
#import "Preferences.h"\
\
#import <appkit/appkit.h>\
\
@implementation ArchieApp(FtpHosts)\
\
- ftpHosts: sender\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker231 \markername ftpHosts:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul\fc1\cf1 ReturnValue:
\i\ulnone\fc0\cf0  self if the panel is displayed, nil if it is not;\
	
\i0\ul\fc1\cf1 Description:
\i\ulnone\fc0\cf0  Brings up a panel that will display a user's FTP hosts\
		by loading the FtpHosts.nib section;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0  \
		sender: the Matrix associated with the FTP submenu;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\i0\fc1\cf1 NXBrowser *browser;\
	if( ftpHostsPanelID == nil )\
	\{	// Load the panel nib\
		[NXApp loadNibSection: "FtpHosts.nib" owner: self withNames: YES];\
		if( ftpHostsPanelID == nil )\
		\{	// Not a fatal error, just an inconvience\
			[self error: INTERNAL_SORRY method:_cmd key:\
				FTP_HOSTS_PANEL_FAILED];\
			return nil;\
		\}\
		browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
		[browser setCellClass: [MyBrowserCell class]];\
	\}\
	[ftpHostsPanelID makeKeyAndOrderFront: self];\
	[self clearFields];\
	browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
	[browser loadColumnZero];\
\
	return self;\
\} 
\b0\i // End ftpHosts:
\b\i0 \
\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 - (int) browser: sender fillMatrix: matrix inColumn:(int) column\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker1189 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The number of cells loaded in the column;\
	
\i0\ul Description:
\i\ulnone  This is normal delegate method is responsible for\
		loading the entries in the given column
\fc1\cf1 . This version only\
		displays the hosts in column0.;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		sender: The NXBrowser we are the delegate for;\
		matrix: The Matrix for the column;\
		column: The column number we should load;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 ObjectList *netrcList;\
int count, index;\
NetrcEntry *entry;\
MyBrowserCell *cell;\
\
	netrcList = [NetrcEntry userNetrcEntries];\
	if( netrcList == 0 )\
		return 0;\
	count = [netrcList count];\
	for(index = 0; index < count; index ++)\
	\{\
		entry = [netrcList objectAt: index];\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 		[matrix addRow];\
		cell = [matrix cellAt: index : 0];\
		[cell setStringValue: [entry displayName]];\
		[cell setLoaded:YES];\
		[cell setLeaf: YES];\
		[cell setTag: entry];\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1 	\}\
\
	return count;\
\} 
\b0\i // End browser:fillMatrix:inColumn:
\b\i0 \
\
- newEntry: sender\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker2093 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 clears the entry fields Form & reloads\
		the host browser to deselect any item;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		sender: The "Clear" button in the FTP Hosts panel;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 NXBrowser *browser;\
\
	browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
	[self clearFields];\
	[browser loadColumnZero];\
\
	return self;\
\} 
\b0\i // End newEntry:
\b\i0 \
\
- updateEntry: sender\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker2500 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if both the hostname & password fields are\
		non-null, nil if one or both are. A nil value is also returned\
		if cancels an update.;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 updates the current entry if the Host\
		and Login file correspond to a current entry or adds a new one\
		if they do not.  In the event of an update the user is prompted\
		to for verification of the update.;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		sender: The "Add" or "Update" button in the FTP Hosts panel;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 Form *entryFields;\
TextField *passwdField;\
NetrcEntry *entry;\
NXBrowser *browser;\
const char *hostname, *username, *password;\
\
	browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
	entryFields = NXGetNamedObject("EntryFields", ftpHostsPanelID);\
	passwdField = NXGetNamedObject("PasswordField", ftpHostsPanelID);\
	[ftpHostsPanelID endEditingFor: nil];\
	hostname = [entryFields stringValueAt: 0];\
	username = [entryFields stringValueAt: 1];\
	password = [passwdField stringValue];\
	entry = [(MyBrowserCell *)[browser selectedCell] tag];\
\
	if( hostname == 0 || username == 0 )\
	\{	// Invalid entry\
		NXBeep();\
		return nil;\
	\}\
\
	if( entry == nil )\
	\{	
\b0\i // A new entry\

\b\i0 		entry = [[NetrcEntry alloc] init: hostname login: username\
			passwd: password setDotEntry: NO];\
		[NetrcEntry addEntry: entry];\
		[browser loadColumnZero];\
		[browser setPath: [entry displayName]];\
		[sender setTitle: "Update"];\
		return self;\
	\}\
	
\b0\i // Update the entry fields
\b\i0 \
	switch( [self askYesNo: "Modify exiting entry?" cancel: NO] )\
	\{\
		case NX_ALERTOTHER:\
			return nil;\
		default:\
		break;\
	\}\
	[entry update: hostname login: username passwd: password];\
	[browser setPath: [entry displayName]];\
\
	return self;\
\} 
\b0\i // End updateEntry:
\b\i0 \
\

\b0\i // Remove the current entry
\b\i0 \
- removeEntry: sender\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker4251 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if an item in the browser is selected, nil\
		otherwise;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 removes the current browser selection from\
		the NetrcEntry class's list. If there is no browser selection\
		nil is returned. If an item is removed the entry fields are\
		cleared and the browser reloaded to clear the selection.;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		sender: The "Remove" button in the FTP Hosts panel;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 NetrcEntry *entry;\
NXBrowser *browser;\
\
	browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
	entry = [(MyBrowserCell *)[browser selectedCell] tag];\
	if( entry == nil )\
		return nil;\
\
	[NetrcEntry removeEntry: entry];\
	[browser loadColumnZero];\
	[self clearFields];\
\
	return self;\
\} 
\b0\i // End removeEntry:
\b\i0 \
\
- doFTPLogin: sender\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker5009 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if both the hostname & password fields are\
		non-null, nil if one or both are. A nil value will also be\
		returned in password is null and login is not anonymous.;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 initiates an interactive ftp session\
		using the login fields information. Both the host and login\
		fields must be non-null in order to the login to proceed.\
		If the login field is "anonymous" and passwd is null the\
		preferences anon-password is used. Else a general login\
		is performed provided passwd is not null.;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		sender: The "Login" button in the FTP Hosts panel;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 FTPObject *ftpSession;\
NetrcEntry *entry;\
NXBrowser *browser;\
Form *entryFields;\
TextField *passwdField;\
const char *hostname, *username, *passwd;\
BOOL userIsAnonymous;\
\
	browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
	entry = [(MyBrowserCell *)[browser selectedCell] tag];\
	entryFields = NXGetNamedObject("EntryFields", ftpHostsPanelID);\
	passwdField = NXGetNamedObject("PasswordField", ftpHostsPanelID);\
	[NetrcEntry saveNetrcEntries];\
	hostname = 
\fc0\cf0 [
\fc1\cf1 entryFields
\fc0\cf0  stringValueAt: 0]
\fc1\cf1 ;\
	username = 
\fc0\cf0 [
\fc1\cf1 entryFields
\fc0\cf0  stringValueAt: 1]
\fc1\cf1 ;\
	passwd = 
\fc0\cf0 [
\fc1\cf1 passwdField
\fc0\cf0  stringValue]
\fc1\cf1 ;\
	if( hostname == 0 || username == 0 )\
	\{	// Invalid entry\
		NXBeep();\
		return nil;\
	\}\
\
	ftpSession = [[FTPObject alloc] init];\
	userIsAnonymous = [FTPObject userIsAnonymous: username];\
	if( userIsAnonymous == YES && passwd == 0 )\
		[ftpSession login: hostname 
\fc0\cf0 interactive: YES initialPath: 0];\
	else if( *passwd != 0 )
\fc1\cf1 \
		[ftpSession log
\fc0\cf0 in: hostname user: username passwd: 
\fc1\cf1 passwd
\fc0\cf0 \
			interactive: YES initialPath: 0];\
	else\

\fc1\cf1 	\{	// Invalid passwd\
		NXBeep();\
		return nil;\
	\}\
	[ftpHostsPanelID close];\
\
	return self;\
\} 
\b0\i // doFTPLogin:
\b\i0 \
\

\b0\i // The target of the host browser
\b\i0 \
- selectEntry: sender\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker6797 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 is the target of the FTP Hosts browser.\
		It displays the host, login and password fields of the current\
		selection in the login fields. The password is set to non-visible.;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		sender: The FTP Hosts browser;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 Button *visible, *addBtn;\
Form *entryFields;\
NetrcEntry *entry;\
PasswordField *passwdField;\
\
	[ftpHostsPanelID makeFirstResponder: ftpHostsPanelID];\
	[ftpHostsPanelID endEditingFor: nil];\
	visible = NXGetNamedObject("VisiblePasswd", ftpHostsPanelID);\
	entry = [(MyBrowserCell *)[sender selectedCell] tag];\
	entryFields = NXGetNamedObject("EntryFields", ftpHostsPanelID);\
	passwdField = NXGetNamedObject("PasswordField", ftpHostsPanelID);\
	addBtn = NXGetNamedObject("AddButton", ftpHostsPanelID);\
	[addBtn setTitle: "Update"];\
	[visible setState: NO];\
	[entryFields setStringValue: [entry hostname] at: 0];\
	[entryFields setStringValue: [entry username] at: 1];\
	[passwdField setStringValue: [entry passwd] visible: NO];\
\
	return self;\
\} 
\b0\i // selectEntry:
\b\i0 \
\
- clearFields\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker7857 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 clears the login fields and resets the\
		add button's title to "Add";
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 Button *addBtn;\
Form *entryFields;\
PasswordField *passwdField;\
\
	entryFields = NXGetNamedObject("EntryFields", ftpHostsPanelID);\
	passwdField = NXGetNamedObject("PasswordField", ftpHostsPanelID);\
	[ftpHostsPanelID makeFirstResponder: ftpHostsPanelID];\
	[ftpHostsPanelID endEditingFor: nil];\
	[entryFields setStringValue: 0 at: 0];\
	[entryFields setStringValue: 0 at: 1];\
	[passwdField setStringValue: 0];\
	addBtn = NXGetNamedObject("AddButton", ftpHostsPanelID);\
	[addBtn setTitle: "Add"];\
\
	return self;\
\}\
\
// Form text delegate method\
- (BOOL) textWillEnd: textObject\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker8581 \markername browser:fillMatrix:inColumn:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  NO to allow end of editing;\
	
\i0\ul Description:
\i\ulnone  This method 
\fc1\cf1 is invoked when ends an editing session\
		in either the host or login fields. It attempts to select an\
		entry of the form hostname:username in the browser. The title\
		of the add button is updated to reflect the success of the search.\
		If the passwd field is empty and the login field has a username of\
		"anonymous" the password field is loaded with the preferences\
		anon-password.;
\fc0\cf0 \
	
\i0\ul Args:
\i\ulnone \
		textObject: The panel Text object field editor;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc1\cf1 Button *visible, *addBtn;\
Form *entryFields;\
PasswordField *passwdField;\
NXBrowser *browser;\
NetrcEntry *entry;\
BOOL setUpdateMode, userIsAnonymous = NO;\
const char *hostname, *username, *passwd;\
char entryPath[64];\
\
	visible = NXGetNamedObject("VisiblePasswd", ftpHostsPanelID);\
	entryFields = NXGetNamedObject("EntryFields", ftpHostsPanelID);\
	browser = NXGetNamedObject("FtpHostBrowser", ftpHostsPanelID);\
	passwdField = NXGetNamedObject("PasswordField", ftpHostsPanelID);\
	hostname = 
\fc0\cf0 [
\fc1\cf1 entryFields
\fc0\cf0  stringValueAt: 0]
\fc1\cf1 ;\
	username = 
\fc0\cf0 [
\fc1\cf1 entryFields
\fc0\cf0  stringValueAt: 1]
\fc1\cf1 ;\
	if( username != 0 )\
		userIsAnonymous = [FTPObject userIsAnonymous: username];\
	passwd = 
\fc0\cf0 [
\fc1\cf1 passwdField stringValue];\
	setUpdateMode = NO;\
	sprintf(entryPath, "%s:%s", hostname, username);\
	if( [browser setPath: entryPath] != nil )\
		setUpdateMode = YES;\
	if( [entryFields selectedRow] == 1 )\
	\{\
		if( setUpdateMode == YES )\
		\{	// Selected a browser entry\
			entry = [(MyBrowserCell *)[browser selectedCell] tag];\
			if( passwd == 0 )\
			\{	// If there is no password use the stored value\
				passwd = [entry passwd];\
				[visible setState: NO];\
				[passwdField setStringValue: passwd visible: NO];\
			\}\
		\}\
		else if( passwd == 0 && userIsAnonymous == YES )\
		\{	// Set passwd to preferences anon-password\

\fc0\cf0 			passwd = [[NXApp preferences] anonPasswd];\

\fc1\cf1 			[visible setState: YES];\

\fc0\cf0 			[
\fc1\cf1 passwdField setStringValue: passwd visible: YES];\
		\}
\fc0\cf0 \

\fc1\cf1 	\}\
\
	addBtn = NXGetNamedObject("AddButton", ftpHostsPanelID);\
	[addBtn setTitle: (setUpdateMode ? "Update" : "Add")];\
	return NO;\
\}\
\
@end\

}
