home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1991 by the University of Washington
- *
- * For copying and distribution information, please see the file
- * <uw-copyright.h>.
- *
- * Written by Clifford Neuman (bcn@isi.edu) with changes by
- * Brendan Kehoe (brendan@cs.widener.edu) and
- * George Ferguson (ferguson@cs.rochester.edu).
- */
- #include <uw-copyright.h>
-
- #import "ArchieServer.h"
- #import "MyBrowserCell.h"
- #import "ProsperoVLINK.h"
- #import <ClockView.h>
- #import <CalendarView.h>
- #import <FTPManager.h>
-
- #import <objc/HashTable.h>
- #import <objc/List.h>
- #import <objc/NXStringTable.h>
- #import <objc/Storage.h>
- #import <appkit/Application.h>
- #import <appkit/ButtonCell.h>
- #import <appkit/Matrix.h>
- #import <appkit/NXBrowser.h>
- #import <appkit/SavePanel.h>
- #import <appkit/appkit.h>
- #import <NXCType.h>
- #import <defaults.h>
- #import <stdio.h>
- #import <sys/time.h>
- #import <perrno.h>
- #import <rdgram.h>
- #import <archie.h>
- #import <mach.h>
- #import <fcntl.h>
- #import <signal.h>
-
- /* Import the error message NXStringTable keys */
- #import "errMessages.keys"
-
- /* The Prospero debugging level */
- int pfs_debug;
-
- /* Globals defined in dirsend2.c used to communicate the query status */
- extern char dirsendStatusBuffer[128];
- char statusBuffer[128];
-
- #define QUERY_ABORT 1
- int queryActiveFlag; // A flag used to indicate that the query thread is active
- void QueryThreadProc(ArchieServer *self);
-
- /* The query string sent to the query_archie() procedure */
- const char *searchString;
-
- /* Sort enums */
- enum {ByName,ByDate,NoSort};
- /* Niceness level enums */
- enum {MinNice = 0,LowNice = 500,HighNice = 10000,MaxNice = 32765};
-
- /* Defaults stuff */
- /* The owner of the application defaults */
- const char *NeXTArchieOwner = "NeXTArchie_SMS";
- enum {QueryType,MaxReplies,Offset,SortType,
- ExactFlag,NiceLevel,Hostname,HostTag,DebugLevel,FtpDebugLevel};
- /* A stringification macro */
- #define DefaultString(STR) #STR
- /* A macro for retriveing default values */
- #define GetDefault(STR) NXGetDefaultValue(NeXTArchieOwner, #STR)
- /* A flag indicating if the pref panel widgets are in sync with the defaults */
- BOOL resetPrefPanel;
- /* The virgin defaults */
- static struct _NXDefault *NextArchieDefaults;
- #define _QueryType "C"
- #define _MaxReplies "100"
- #define _Offset "0"
- #define _SortType "0"
- #define _ExactFlag "YES"
- #define _NiceLevel "0"
- #define _Hostname "archie.mcgill.ca"
- #define _HostTag "0"
- #define _DebugLevel "2"
- #define _FtpDebugLevel "0"
-
- /* The title for the custom host radio button */
- #define CUSTOM_TITLE "Custom host"
- #define CUSTOM_TAG 7
-
- @implementation ArchieServer
-
- /* Initialization */
- + initialize
- {
- int i;
- /* Register the defaults for the preference items */
- NextArchieDefaults = (struct _NXDefault *) malloc(11*sizeof(struct _NXDefault));
- for(i = 0; i < 10; i ++)
- {
- NextArchieDefaults[i].name = (char *) malloc(16);
- NextArchieDefaults[i].value = (char *) malloc(32);
- }
- NextArchieDefaults[10].name = NULL;
- NextArchieDefaults[10].value = NULL;
- strcpy(NextArchieDefaults[QueryType].name, DefaultString(QueryType));
- strcpy(NextArchieDefaults[MaxReplies].name, DefaultString(MaxReplies));
- strcpy(NextArchieDefaults[Offset].name, DefaultString(Offset));
- strcpy(NextArchieDefaults[SortType].name, DefaultString(SortType));
- strcpy(NextArchieDefaults[ExactFlag].name, DefaultString(ExactFlag));
- strcpy(NextArchieDefaults[NiceLevel].name, DefaultString(NiceLevel));
- strcpy(NextArchieDefaults[Hostname].name, DefaultString(Hostname));
- strcpy(NextArchieDefaults[HostTag].name, DefaultString(HostTag));
- strcpy(NextArchieDefaults[DebugLevel].name, DefaultString(DebugLevel));
- strcpy(NextArchieDefaults[FtpDebugLevel].name, DefaultString(FtpDebugLevel));
- strcpy(NextArchieDefaults[QueryType].value, _QueryType);
- strcpy(NextArchieDefaults[MaxReplies].value, _MaxReplies);
- strcpy(NextArchieDefaults[Offset].value, _Offset);
- strcpy(NextArchieDefaults[SortType].value, _SortType);
- strcpy(NextArchieDefaults[ExactFlag].value, _ExactFlag);
- strcpy(NextArchieDefaults[NiceLevel].value, _NiceLevel);
- strcpy(NextArchieDefaults[Hostname].value, _Hostname);
- strcpy(NextArchieDefaults[HostTag].value, _HostTag);
- strcpy(NextArchieDefaults[DebugLevel].value, _DebugLevel);
- strcpy(NextArchieDefaults[FtpDebugLevel].value, _FtpDebugLevel);
-
- NXRegisterDefaults(NeXTArchieOwner, NextArchieDefaults);
-
- return self;
- }
-
- - init
- {
- const char *defString;
-
- [super init];
-
- /* Initialize the host keyed hashtable */
- hostHashTable = [[HashTable alloc] initKeyDesc: "*"];
- if(hostHashTable == nil)
- return [self error: SEVERE key: HOSTHASHTABLE_ALLOC_FAILED];
- hostList = [[List alloc] initCount: 0];
- if(hostList == nil)
- return [self error: SEVERE key: HOSTLIST_ALLOC_FAILED];
-
- /* Load the default values for the archie options */
- defString = GetDefault(QueryType);
- queryType = defString[0];
- maxReplies = atoi(GetDefault(MaxReplies));
- offset = atoi(GetDefault(Offset));
- sortType = atoi(GetDefault(SortType));
- cmpProc = (sortType == ByName ? AQ_DEFCMP: AQ_INVDATECMP);
- defString = GetDefault(ExactFlag);
- exactFlag = (defString[0] == 'Y' ? YES: NO);
- defString = GetDefault(NiceLevel);
- niceLevel = atoi(defString);
- hostname = GetDefault(Hostname);
- if(hostname == NULL)
- hostname = ARCHIE_HOST;
- hostTag= atoi(GetDefault(HostTag));
- defString = GetDefault(DebugLevel);
- pfs_debug = debugLevel = atoi(defString);
- resetPrefPanel = YES;
-
- return self;
- }
-
- - archieRequest: sender
- {
- int threadExitStatus,modalStatus;
- char messageBuffer[128];
- NXModalSession theSession;
- /* Prototypes taken from pfs/perrmesg.c */
- int spwarnmesg(char *buf,char *prefix,int no,char *text);
- int sperrmesg(char *buf,char *prefix,int no,char *text);
-
- /* Get the search string from the interface and query the Archie server */
- searchString = [sender stringValue];
-
- /* Begin a modal session which gives the user the opportunity to
- abort the query */
- [NXApp beginModalSession: &theSession for: queryPanelID];
- [hostnameID setStringValue: hostname];
- strcpy(statusBuffer,"Querying Archie Server...");
- strcpy(dirsendStatusBuffer,"Querying Archie Server...");
- [statusID setStringValue: statusBuffer];
- [queryTimerID startMinSecTimer: self];
- [queryPanelID display];
-
- /* Create a thread to query the Archie server */
- queryActiveFlag = 1;
- queryThread = cthread_fork((cthread_fn_t) QueryThreadProc,(any_t) self);
-
- while ( queryActiveFlag )
- {
- modalStatus = [NXApp runModalSession:&theSession];
- if ( modalStatus != NX_RUNCONTINUES )
- break;
- /* Display the current query status */
- if( strcmp(statusBuffer,dirsendStatusBuffer) )
- {
- [statusID setStringValue: dirsendStatusBuffer];
- strcpy(statusBuffer,dirsendStatusBuffer);
- }
- cthread_yield();
- }
- [queryPanelID orderOut: self];
- [NXApp endModalSession: &theSession];
-
- /* Check result status */
- if(queryActiveFlag)
- // Query was aborted
- thread_resume(cthread_thread(queryThread));
-
- threadExitStatus = (int) cthread_join(queryThread);
- if(modalStatus != QUERY_ABORT && threadExitStatus > 0)
- {
- if(perrno == 0)
- strcpy(messageBuffer,"No matches found");
- else
- sperrmesg(messageBuffer,"Propsero Error Message:\n",0,NULL);
- NXBeep();
- NXRunAlertPanel(NULL, messageBuffer,NULL,NULL,NULL);
- return nil;
- }
- else if(modalStatus == QUERY_ABORT)
- return nil;
-
- if(pwarn)
- {
- spwarnmesg(messageBuffer,"Propsero Warning Message:\n",0,NULL);
- NXBeep();
- NXRunAlertPanel(NULL, messageBuffer,NULL,NULL,NULL);
- }
-
- /* Parse the Archie response for display in the browser */
- if(threadExitStatus == 0)
- if( [self parseResponse: archieRslt] != nil)
- {
- /* Set the fileBrowserID cells class to MyBrowserCell */
- [fileBrowserID setCellClass: [MyBrowserCell class]];
- [fileBrowserID setPathSeparator: ':']; // Not used presently
- [fileBrowserID loadColumnZero];
- }
-
- return self;
- }
-
- - parseResponse: (VLINK) response
- {
- ProsperoVLINK *v;
- List *hostFiles;
- const char *host_name;
-
- [hostHashTable freeObjects];
- [hostList freeObjects];
- while(response)
- { /* Step 1 - Create a ProsperoVLINK object this VLINK */
- v = [[ProsperoVLINK alloc] initVLINK: response];
- if(v == nil)
- { // Error
- return [self error: ALERT key: VLINK_ALLOC_FAILED];
- }
- /* Step 2 - See if the hostname has been entered as a key in the hostHashTable */
- host_name = [v hostname];
- if( [hostHashTable isKey: host_name] == YES)
- { // Then get the List of files for this host
- hostFiles = (List *) [hostHashTable valueForKey: host_name];
- if(hostFiles == nil)
- { // Error
- return [self error: ALERT key: VALID_KEY_NIL_ENTRY];
- }
- // Add this file to the host list
- [hostFiles addObject: v];
- }
- else
- { // Create a new List for this host and add it to the
- // hostHashTable for fast acces and to the hostList to maintain
- // the requested order
- hostFiles = [[List alloc] initCount: 0];
- if(hostFiles == nil)
- return [self error: SEVERE key: HOSTFILES_ALLOC_FAILED];
- [hostFiles addObject: v];
- [hostHashTable insertKey: host_name value: hostFiles];
- [hostList addObject: v];
- }
- response = response->next;
- }
- return self;
- }
-
- /* Interrupt the request */
- - interruptRequest: sender
- {
- /* Suspend and abort the query thread */
- thread_suspend(cthread_thread(queryThread));
- cthread_abort(queryThread);
-
- /* Stop the modal loop */
- [NXApp stopModal: QUERY_ABORT];
-
- return self;
- }
-
- /* A simple wrapper function that is passed to cthread_fork(). The thread that
- calls this function simply invokes the archie_query() function and sets the
- archieRslt instance variable to its reslt.
- It returns 0 on sucess and nonzero if an error occurs.
- */
- void QueryThreadProc(ArchieServer *self)
- {
- int queryFlags;
-
- if(self->sortType == NoSort)
- queryFlags = AQ_NOSORT;
- else
- queryFlags = 0;
- if(self->exactFlag == YES)
- self->queryType = NXToLower(self->queryType);
-
- /* Initialize the Prospero error variables */
- perrno = 0; *p_err_string = '\0';
- pwarn = 0; *p_warn_string = '\0';
-
- self->archieRslt = archie_query(self->hostname,searchString,self->maxReplies,
- self->offset,self->queryType,self->cmpProc,queryFlags);
-
- queryActiveFlag = 0;
- if(self->archieRslt == NULL)
- cthread_exit( (any_t)1 ); // No matches found, query aborted, or Prospero error
-
- cthread_exit( (any_t)0 ); // Successful query
- }
-
- /* Bring up the info panel */
- - infoPanel: sender
- {
- if(infoPanelID == nil)
- {
- [NXApp loadNibSection: "Info.nib" owner: self withNames: NO];
- if(infoPanelID == nil)
- return [self error: SORRY key: INFO_PANEL_FAILED];
- }
- [infoPanelID makeKeyAndOrderFront: self];
- return self;
- }
-
- /* Display the query options panel */
- - preferences: sender
- {
- if(prefPanelID == nil)
- {
- [NXApp loadNibSection: "Preferences.nib" owner: self withNames: NO];
- if(prefPanelID == nil)
- return [self error: SORRY key: PREF_PANEL_FAILED];
- }
- if(resetPrefPanel == YES)
- {
- int nice,query;
- [ hostMatrixID selectCellWithTag: hostTag];
- if(hostTag == CUSTOM_TAG)
- [customHostID setStringValue: hostname];
- [ sortMatrixID selectCellAt: sortType: 0];
- switch(queryType)
- {
- case 'C' :
- query = 0;
- break;
- case 'S' :
- query = 1;
- break;
- case 'R' :
- query = 2;
- break;
- case '=' :
- query = 3;
- break;
- default :
- query = 0;
- break;
- }
- [ patternMatrixID selectCellAt: query: 0];
- [ exactBtnID setState: exactFlag];
- switch(niceLevel)
- {
- case MinNice :
- nice = 0;
- break;
- case LowNice :
- nice = 1;
- break;
- case HighNice :
- nice = 2;
- break;
- case MaxNice :
- nice = 3;
- break;
- default :
- nice = 0;
- break;
- }
- [ niceMatrixID selectCellAt: 0 : nice];
- [ hitsFormID setIntValue: maxReplies];
- [ debugMatrixID selectCellAt: 0 : debugLevel];
- }
-
- [[prefPanelID orderFront: self] display];
- return self;
- }
-
- /* Methods which set the query options */
- - setQueryType: sender
- {
- switch([sender selectedRow])
- {
- case 0 :
- queryType = 'C';
- break;
- case 1 :
- queryType = 'S';
- break;
- case 2 :
- queryType = 'R';
- break;
- case 3 :
- default:
- queryType = '=';
- break;
- }
- return self;
- }
- - setExactMode: sender
- {
- exactFlag = [sender state];
- return self;
- }
- - setMaxReplies: sender
- {
- maxReplies = [sender intValue];
- return self;
- }
- - setOffset: sender
- {
- offset = [sender intValue];
- return self;
- }
- - setSortType: sender
- {
- sortType = [sender selectedRow];
- switch(sortType)
- {
- case 0 :
- cmpProc = AQ_DEFCMP;
- break;
- case 1 :
- cmpProc = AQ_INVDATECMP;
- break;
- case 2 :
- cmpProc = NULL;
- break;
- default :
- cmpProc = AQ_DEFCMP;
- break;
- }
- return self;
- }
- - setNiceLevel: sender
- {
- switch([sender selectedCol])
- {
- case 0 :
- niceLevel = MinNice;
- break;
- case 1 :
- niceLevel = LowNice;
- break;
- case 2 :
- niceLevel = HighNice;
- break;
- case 3 :
- niceLevel = MaxNice;
- break;
- default :
- niceLevel = MinNice;
- break;
- }
- return self;
- }
- - setHostname: sender
- {
- /* See if this is a custom host request */
- if( strcmp([[sender selectedCell] title],CUSTOM_TITLE) == 0 )
- hostname = [customHostID stringValue];
- else
- hostname = (char *) [[sender selectedCell] title];
- hostTag= [[sender selectedCell] tag];
- return self;
- }
- /* The target of the ``Custom hostname'' TextField */
- - setCustomHost: sender
- {
- hostname = [sender stringValue];
- hostTag = CUSTOM_TAG;
- [hostMatrixID selectCellWithTag: hostTag];
- return self;
- }
- - setDebugLevel: sender
- {
- ButtonCell *cell;
- cell = [sender selectedCell];
- pfs_debug = debugLevel = [cell tag];
- return self;
- }
-
- /* Ftp methods */
- - retrieveFile: sender
- {
- const char *remoteHost,*remoteFile;
- BOOL binaryMode;
- int selectedColumn;
-
- if(ftpObject == nil)
- {
- ftpObject = [[FTPManager alloc] init];
- if(ftpObject == nil)
- return [self error: ALERT key: FTPOBJECT_ALLOC_FAILED];
- }
- remoteHost = [selectedFile hostname];
- remoteFile = [selectedFile filePath];
- if([modeMatrixID selectedRow] == 0)
- binaryMode = NO;
- else
- binaryMode = YES;
- /* Activate the FTPManager for the transfer */
- if([selectedFile isDirectory] == NO)
- [ftpObject runModal: remoteHost get: remoteFile anon: YES
- write: NO binary: binaryMode vlink: nil];
- else
- {
- [ftpObject runModal: remoteHost get: remoteFile anon: YES
- write: NO binary: NO vlink: selectedFile];
- selectedColumn = [fileBrowserID selectedColumn];
- [fileBrowserID reloadColumn: selectedColumn+1];
- }
- return self;
- }
-
- - setTransferDir : sender
- {
- if(ftpObject == nil)
- {
- ftpObject = [[FTPManager alloc] init];
- if(ftpObject == nil)
- return [self error: ALERT key: FTPOBJECT_ALLOC_FAILED];
- }
- [ftpObject setLocalDir: self];
-
- return self;
- }
-
- /* Read/Restore default preferences */
- - saveDefaults: sender
- {
- /* An updateable defaults vector */
- int i;
- struct _NXDefault *_NextArchieDefaults;
- _NextArchieDefaults = (struct _NXDefault *) malloc(10*sizeof(struct _NXDefault));
- if(_NextArchieDefaults == NULL)
- return [self error: ALERT key: NXDEFAULTS_ALLOC_FAILED];
-
- for(i = 0; i < 9; i ++)
- {
- _NextArchieDefaults[i].name = (char *) malloc(16);
- _NextArchieDefaults[i].value = (char *) malloc(32);
- if(_NextArchieDefaults[i].name == NULL ||
- _NextArchieDefaults[i].value == NULL)
- return [self error: ALERT key: NXDEFAULTS_ITEM_ALLOC_FAILED];
- }
- _NextArchieDefaults[9].name = NULL;
- _NextArchieDefaults[9].value = NULL;
-
- strcpy(_NextArchieDefaults[QueryType].name, DefaultString(QueryType));
- strcpy(_NextArchieDefaults[MaxReplies].name, DefaultString(MaxReplies));
- strcpy(_NextArchieDefaults[Offset].name, DefaultString(Offset));
- strcpy(_NextArchieDefaults[SortType].name, DefaultString(SortType));
- strcpy(_NextArchieDefaults[ExactFlag].name, DefaultString(ExactFlag));
- strcpy(_NextArchieDefaults[NiceLevel].name, DefaultString(NiceLevel));
- strcpy(_NextArchieDefaults[Hostname].name, DefaultString(Hostname));
- strcpy(_NextArchieDefaults[HostTag].name, DefaultString(HostTag));
- strcpy(_NextArchieDefaults[DebugLevel].name, DefaultString(DebugLevel));
- sprintf(_NextArchieDefaults[QueryType].value,"%c",queryType);
- sprintf(_NextArchieDefaults[MaxReplies].value,"%d",maxReplies);
- sprintf(_NextArchieDefaults[Offset].value,"%d",offset);
- sprintf(_NextArchieDefaults[SortType].value,"%d",sortType);
- sprintf(_NextArchieDefaults[ExactFlag].value,"%s",(exactFlag == YES ? "YES" : "NO"));
- sprintf(_NextArchieDefaults[NiceLevel].value,"%d",niceLevel);
- sprintf(_NextArchieDefaults[Hostname].value,"%s",hostname);
- sprintf(_NextArchieDefaults[HostTag].value,"%d",hostTag);
- sprintf(_NextArchieDefaults[DebugLevel].value,"%d",debugLevel);
-
- NXWriteDefaults(NeXTArchieOwner, _NextArchieDefaults);
-
- for(i = 0; i < 9; i ++)
- {
- free(_NextArchieDefaults[i].name);
- free(_NextArchieDefaults[i].value);
- }
- free(_NextArchieDefaults);
-
- return self;
- }
-
- - restoreDefaults: sender
- {
- /* Restore the virgin defaults */
- NXWriteDefaults(NeXTArchieOwner, NextArchieDefaults);
- NXUpdateDefaults();
-
- /* Reset the preferences panel objects */
- resetPrefPanel = YES;
- [self preferences: self];
-
- return self;
- }
-
- /* Browser delegate method which fills the browser with the last
- query result. This version displays the hosts in column0, the full pathanme
- in column1 and the lowest file in the path in column2. */
- - (int)browser: sender fillMatrix: matrix inColumn:(int) column
- {
- const char *host_name;
- int row,rows,depth;
- id hostFileList,link,dirListing;
- MyBrowserCell *cell;
-
- /* Column zero */
- if(column == 0)
- { // Load the host names
-
- rows = [hostList count];
- for(row = 0; row < rows; row ++)
- {
- host_name = [[hostList objectAt: row] hostname];
- [matrix addRow];
- cell = [matrix cellAt: row : 0];
- [cell setStringValue: host_name];
- [cell setLoaded:YES];
- [cell setLeaf: NO];
- }
- }
- else if(column == 1)
- { // Loop through the host's files and display the pathnames
-
- /* Get the file list for the selected host */
- host_name = [[[sender matrixInColumn: 0] selectedCell] stringValue];
- hostFileList = (List *) [hostHashTable valueForKey: host_name];
-
- rows = [hostFileList count];
- for(row = 0; row < rows; row ++)
- {
- link = (ProsperoVLINK *) [hostFileList objectAt: row];
- [matrix addRow];
- depth = [link fileDepth];
- cell = [matrix cellAt: row : 0];
- [cell setStringValue: [link filePath]];
- [cell setLoaded:YES];
- if(depth > column)
- {
- [cell setLeaf: NO];
- [cell setTag: nil];
- }
- else
- { // This is the file's level
- if([link isDirectory] == NO)
- [cell setLeaf: YES];
- else
- [cell setLeaf: NO];
- [cell setTag: link];
- }
- }
- }
- else if(column == 2)
- { // Load one cell and display the end item of the selected path
-
- /* Get the file list for the selected host */
- host_name = [[[sender matrixInColumn: 0] selectedCell] stringValue];
- hostFileList = (List *) [hostHashTable valueForKey: host_name];
- rows = 1;
- row = [[sender matrixInColumn: 1] selectedRow];
- link = (ProsperoVLINK *) [hostFileList objectAt: row];
- [matrix addRow];
- cell = [matrix cellAt: 0 : 0];
- [cell setStringValue: [link fileName]];
- [cell setLoaded:YES];
- [cell setTag: link];
- if( [link isDirectory] == NO)
- [cell setLeaf: YES];
- else
- [cell setLeaf: NO];
- }
- else
- {
- // The directory vlink in the previous column
- cell = [[sender matrixInColumn: column - 1] selectedCell] ;
- link = [cell tag];
- dirListing = [link listing];
- rows = [dirListing count];
- for(row = 0; row < rows; row ++)
- {
- link = [dirListing objectAt: row];
- [matrix addRow];
- cell = [matrix cellAt: row : 0];
- [cell setStringValue: [link fileName]];
- [cell setLoaded:YES];
- [cell setTag: link];
- [cell setEnabled: YES];
- if( [link isDirectory] == NO)
- [cell setLeaf: YES];
- else
- [cell setLeaf: NO];
- }
- if(rows <= 0)
- {
- rows = 1;
- [matrix addRow];
- cell = [matrix cellAt: row : 0];
- if(dirListing == nil)
- [cell setStringValue: "Directory not loaded"];
- else
- [cell setStringValue: "No files"];
- [cell setLoaded:YES];
- [cell setTag: nil];
- [cell setLeaf: YES];
- [cell setEnabled: NO];
- }
- }
- return rows;
- }
-
- #define Read 4
- #define Write 2
- #define Exec 1
- #define Owner 448
- #define Group 56
- #define Other 7
-
- - fileAttributes: sender
- {
- ProsperoVLINK *link;
- short hr,min,sec;
- short day,month,year;
- int owner,group,other,mode;
- int row,col;
- MyBrowserCell *cell;
-
- col = [sender selectedColumn];
- if(col == 0)
- { // Clear the info display
- [self clearFields];
- [retrieveBtnID setEnabled: NO];
- selectedFile = nil;
- return self;
- }
-
- row = [[sender matrixInColumn: col] selectedRow];
- cell = [sender getLoadedCellAtRow: row inColumn: col];
-
- /* The id value of the selected cell is the cell's tag value */
- link = (ProsperoVLINK *) [cell tag];
- selectedFile = link;
-
- /* Don't display any info for non directories */
- if([cell isLeaf] == NO && col == 1)
- {
- [self clearFields];
- [retrieveBtnID setEnabled: NO];
- selectedFile = nil;
- return self;
- }
-
- /* Enable ftp transfer if the item is not a directory, listing if it is */ [retrieveBtnID setEnabled: YES];
- if([selectedFile isDirectory] == NO)
- [retrieveBtnID setTitle: "Retrieve..."];
- else
- [retrieveBtnID setTitle: "Listing..."];
-
- /* Set the modification time and date */
- [link time: &hr : &min : &sec];
- [clockID setTime: hr : min : sec];
- day = [link day];
- month = [link month]; // Runs from 0-11
- year = [link year];
- // Expects month to run from 1-12 for consistency with string dates
- [calendarID setDate: day : month+1 : year];
-
- /* Set the file info Form */
- [fileInfoID setStringValue: [link hostname] at: 0];
- [fileInfoID setStringValue: [link filePath] at: 1];
- [fileInfoID setStringValue: [link fileName] at: 2];
- [fileInfoID setIntValue: [link fileSize] at: 3];
- [fileInfoID setStringValue: ([link isDirectory] == YES ? "Directory" : "File") at: 4];
-
- /* Set the file permissions */
- mode = [link mode];
- owner = (mode & Owner) >> 6;
- group = (mode & Group) >> 3;
- other = mode & Other;
- if(owner & Read)
- [readMatrixID setState: YES at: 0 : 0];
- else
- [readMatrixID setState: NO at: 0 : 0];
- if(group & Read)
- [readMatrixID setState: YES at: 0 : 1];
- else
- [readMatrixID setState: NO at: 0 : 1];
- if(other & Read)
- [readMatrixID setState: YES at: 0 : 2];
- else
- [readMatrixID setState: NO at: 0 : 2];
-
- if(owner & Write)
- [writeMatrixID setState: YES at: 0 : 0];
- else
- [writeMatrixID setState: NO at: 0 : 0];
- if(group & Write)
- [writeMatrixID setState: YES at: 0 : 1];
- else
- [writeMatrixID setState: NO at: 0 : 1];
- if(other & Write)
- [writeMatrixID setState: YES at: 0 : 2];
- else
- [writeMatrixID setState: NO at: 0 : 2];
-
- if(owner & Exec)
- [execMatrixID setState: YES at: 0 : 0];
- else
- [execMatrixID setState: NO at: 0 : 0];
- if(group & Exec)
- [execMatrixID setState: YES at: 0 : 1];
- else
- [execMatrixID setState: NO at: 0 : 1];
- if(other & Exec)
- [execMatrixID setState: YES at: 0 : 2];
- else
- [execMatrixID setState: NO at: 0 : 2];
-
- return self;
- }
-
- - clearFields
- {
- /* Reset date to now */
- [clockID now];
- [calendarID today];
-
- /* Reset the file info Form */
- [fileInfoID setStringValue: NULL at: 0];
- [fileInfoID setStringValue: NULL at: 1];
- [fileInfoID setStringValue: NULL at: 2];
- [fileInfoID setStringValue: NULL at: 3];
- [fileInfoID setStringValue: NULL at: 4];
-
- /* Rest permissions */
- [readMatrixID setState: YES at: 0 : 0];
- [readMatrixID setState: YES at: 0 : 1];
- [readMatrixID setState: YES at: 0 : 2];
- [writeMatrixID setState: YES at: 0 : 0];
- [writeMatrixID setState: YES at: 0 : 1];
- [writeMatrixID setState: YES at: 0 : 2];
- [execMatrixID setState: YES at: 0 : 0];
- [execMatrixID setState: YES at: 0 : 1];
- [execMatrixID setState: YES at: 0 : 2];
-
- return self;
- }
-
- /* Report the error associated with the keyString and depending on
- the continue depending on the severity */
- - error:(int) severity key:(const char *) keyString
- {
- const char *errMessage;
- const char *replyRequest;
-
- int alertResult;
-
- errMessage = [errStringTable valueForStringKey: keyString];
- switch(severity)
- {
- case SORRY :
- replyRequest = [errStringTable valueForStringKey: REPLY_REQUEST2];
- break;
- case ALERT :
- replyRequest = [errStringTable valueForStringKey: REPLY_REQUEST1];
- break;
- case SEVERE :
- default:
- replyRequest = [errStringTable valueForStringKey: REPLY_REQUEST0];
- break;
- }
-
- if(severity >= SEVERE)
- alertResult = NXRunAlertPanel("Error","%s\n\t%s","Quit",NULL,NULL,
- errMessage,replyRequest);
- else
- alertResult = NXRunAlertPanel("Error","%s\n\t%s","Ok","Quit",NULL,
- errMessage,replyRequest);
- if(severity >= SEVERE || alertResult == NX_ALERTALTERNATE)
- [NXApp terminate: self];
-
- return self;
- }
-
- @end
-