1/* 2 Project: FTP 3 4 Copyright (C) 2005-2016 Riccardo Mottola 5 6 Author: Riccardo Mottola 7 8 Created: 2005-03-30 9 10 Application Controller 11 12 This application is free software; you can redistribute it and/or 13 modify it under the terms of the GNU General Public 14 License as published by the Free Software Foundation; either 15 version 2 of the License, or (at your option) any later version. 16 17 This application is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Library General Public License for more details. 21 22 You should have received a copy of the GNU General Public 23 License along with this library; if not, write to the Free 24 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25*/ 26 27#import "AppController.h" 28#import "fileElement.h" 29#import "GetNameController.h" 30 31@implementation fileTransmitParms 32@end 33 34@implementation AppController 35 36 37 38- (id)init 39{ 40 NSFont *font; 41 42 if ((self = [super init])) 43 { 44 connMode = defaultMode; 45 46 threadRunning = NO; 47 48 font = [NSFont userFixedPitchFontOfSize: 0]; 49 textAttributes = [NSMutableDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; 50 [textAttributes retain]; 51 } 52 return self; 53} 54 55- (void)dealloc 56{ 57 [doConnection invalidate]; 58 59 [doConnection release]; 60 [textAttributes release]; 61 [super dealloc]; 62} 63 64- (void)awakeFromNib 65{ 66 NSMenu *menu; 67 NSMenuItem *mi; 68 69 /* connection panel */ 70 [connServerBox setTitle:NSLocalizedString(@"Server Address and Port", @"Server Address and Port")]; 71 [connAccountBox setTitle:NSLocalizedString(@"Account", @"Account")]; 72 [connectPanel setTitle:NSLocalizedString(@"Connect", @"Connect")]; 73 [connAnon setTitle:NSLocalizedString(@"Anonymous", @"Anonymous connection")]; 74 [connCancelButt setTitle:NSLocalizedString(@"Cancel", @"Cancel")]; 75 [connConnectButt setTitle:NSLocalizedString(@"Connect (action)", @"Connect (action)")]; 76 77 /* main window */ 78 [[localPath itemAtIndex:0] setTitle:NSLocalizedString(@"local view", @"local view")]; 79 [[remotePath itemAtIndex:0] setTitle:NSLocalizedString(@"remote view", @"remote view")]; 80 [[[localView tableColumnWithIdentifier:@"filename"] headerCell] setStringValue:NSLocalizedString(@"Name", @"filename table")]; 81 [[[remoteView tableColumnWithIdentifier:@"filename"] headerCell] setStringValue:NSLocalizedString(@"Name", @"filename table")]; 82 83 /* menus */ 84 mi = [mainMenu itemWithTitle:@"Local"]; 85 menu = [mi submenu]; 86 [menu setTitle:NSLocalizedString(@"Local", @"Local")]; 87 mi = [menu itemWithTag:1]; 88 [mi setTitle:NSLocalizedString(@"Rename...", @"Rename...")]; 89 mi = [menu itemWithTag:2]; 90 [mi setTitle:NSLocalizedString(@"New Folder...", @"New Folder....")]; 91 mi = [menu itemWithTag:3]; 92 [mi setTitle:NSLocalizedString(@"Delete", @"Delete")]; 93 mi = [menu itemWithTag:4]; 94 [mi setTitle:NSLocalizedString(@"Refresh", @"Refresh")]; 95 96 mi = [mainMenu itemWithTitle:@"Remote"]; 97 menu = [mi submenu]; 98 [menu setTitle:NSLocalizedString(@"Remote", @"Remote")]; 99 mi = [menu itemWithTag:1]; 100 [mi setTitle:NSLocalizedString(@"Rename...", @"Rename...")]; 101 mi = [menu itemWithTag:2]; 102 [mi setTitle:NSLocalizedString(@"New Folder...", @"New Folder....")]; 103 mi = [menu itemWithTag:3]; 104 [mi setTitle:NSLocalizedString(@"Delete", @"Delete")]; 105 mi = [menu itemWithTag:4]; 106 [mi setTitle:NSLocalizedString(@"Refresh", @"Refresh")]; 107 108 /* log */ 109 [logWin setTitle:NSLocalizedString(@"Connection Log", @"Connection Log")]; 110 111 [logTextField setSelectable:YES]; 112 [logTextField setEditable:NO]; 113} 114 115- (void)applicationDidFinishLaunching:(NSNotification *)aNotif 116{ 117 NSArray *dirList; 118 NSUserDefaults *defaults; 119 NSString *readValue; 120 NSPort *port1; 121 NSPort *port2; 122 NSArray *portArray; 123 124 /* read the user preferences */ 125 defaults = [NSUserDefaults standardUserDefaults]; 126 readValue = [defaults stringForKey:connectionModeKey]; 127 128 /* if no value was set for the key we set passive as mode */ 129 if ([readValue isEqualToString:@"default"]) 130 connMode = defaultMode; 131 else if ([readValue isEqualToString:@"port"] ) 132 connMode = portMode; 133 else if ([readValue isEqualToString:@"passive"] || readValue == nil) 134 connMode = passiveMode; 135 else 136 NSLog(@"Unrecognized value in user preferences for %@: %@", connectionModeKey, readValue); 137 138 /* set double actions for tables */ 139 [localView setTarget:self]; 140 [localView setDoubleAction:@selector(listDoubleClick:)]; 141 [remoteView setTarget:self]; 142 [remoteView setDoubleAction:@selector(listDoubleClick:)]; 143 144 /* initialize drag-n-drop code */ 145 [localView registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; 146 [remoteView registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; 147 148 /* startup code */ 149 local = [[LocalClient alloc] init]; 150 [local setWorkingDir:[local homeDir]]; 151 dirList = [local dirContents]; 152 [progBar setDoubleValue:0.0]; // reset the progress bar 153 154 /* we create a data source and set the tableviews */ 155 localTableData = [[FileTable alloc] init]; 156 [localTableData initData:dirList]; 157 [localView setDataSource:localTableData]; 158 159 remoteTableData = [[FileTable alloc] init]; 160 [remoteView setDataSource:remoteTableData]; 161 162 /* we update the path menu */ 163 [self updatePath :localPath :[local workDirSplit]]; 164 // #### and a release of this array ?!? 165 166 // we set up distributed objects 167 port1 = [NSPort port]; 168 port2 = [NSPort port]; 169 doConnection = [[NSConnection alloc] initWithReceivePort:port1 170 sendPort:port2]; 171 [doConnection setRootObject:self]; 172 173 /* Ports switched here. */ 174 portArray = [NSArray arrayWithObjects:port2, port1, nil]; 175 [NSThread detachNewThreadSelector: @selector(connectWithPorts:) 176 toTarget: [FtpClient class] 177 withObject: portArray]; 178 179 /* show the connection panel */ 180 [connectPanel makeKeyAndOrderFront:self]; 181 return; 182} 183 184- (NSApplicationTerminateReply)applicationShouldTerminate:(id)sender 185{ 186 return NSTerminateNow; 187} 188 189- (void)applicationWillTerminate:(NSNotification *)aNotif 190{ 191} 192 193- (BOOL)application:(NSApplication *)application openFile:(NSString *)fileName 194{ 195 return NO; 196} 197 198/** update the pop-up menu with a new path */ 199- (void)updatePath :(NSPopUpButton *)path :(NSArray *)pathArray 200{ 201 [path removeAllItems]; 202 [path addItemsWithTitles:pathArray]; 203} 204 205/** reads directory contents and reads refreshes the table */ 206- (void)readDirWith:(Client *)client toTable:(FileTable *)t andView:(NSTableView*)tv 207{ 208 NSArray *dirList; 209 210 if ((dirList = [client dirContents]) == nil) 211 return; 212 [t initData:dirList]; 213 [tv deselectAll:self]; 214 [tv reloadData]; 215} 216 217/** performs the action of the path pull-down menu 218 it navigates upwards the tree 219 and works for both the local and remote path */ 220- (IBAction)changePathFromMenu:(id)sender 221{ 222 Client *theClient; 223 NSTableView *theView; 224 FileTable *theTable; 225 NSString *thePath; 226 NSArray *items; 227 int selectedIndex; 228 unsigned i; 229 230 if (sender == localPath) 231 { 232 theClient = local; 233 theView = localView; 234 theTable = localTableData; 235 } 236 else 237 { 238 theClient = ftp; 239 theView = remoteView; 240 theTable = remoteTableData; 241 } 242 thePath = [NSString string]; 243 selectedIndex = [sender indexOfItem:[sender selectedItem]]; 244 items = [sender itemTitles]; 245 for (i = [items count] - 1; i >= selectedIndex; i--) 246 thePath = [thePath stringByAppendingPathComponent: [items objectAtIndex:i]]; 247 248 [theClient changeWorkingDir:thePath]; 249 [self readDirWith:theClient toTable:theTable andView:theView]; 250 251 [self updatePath :sender :[theClient workDirSplit]]; 252} 253 254/* perform the action of a double click in a table element 255 a directory should be opened, a file down or uploaded 256 The same method works for local and remote, detecting them */ 257- (IBAction)listDoubleClick:(id)sender 258{ 259 Client *theClient; 260 NSTableView *theView; 261 FileTable *theTable; 262 int elementIndex; 263 FileElement *fileEl; 264 NSString *thePath; 265 NSPopUpButton *thePathMenu; 266 267 if (threadRunning) 268 { 269 NSLog(@"thread was still running"); 270 return; 271 } 272 273 theView = sender; 274 if (theView == localView) 275 { 276 theClient = local; 277 theTable = localTableData; 278 thePathMenu = localPath; 279 } else 280 { 281 theClient = ftp; 282 theTable = remoteTableData; 283 thePathMenu = remotePath; 284 } 285 286 elementIndex = [sender selectedRow]; 287 if (elementIndex < 0) 288 { 289 NSLog(@"error: double click with nothing selected"); 290 return; 291 } 292 fileEl = [theTable elementAtIndex:elementIndex]; 293 NSLog(@"element: %@ %d", [fileEl name], [fileEl isDir]); 294 thePath = [NSString stringWithString:[theClient workingDir]]; 295 thePath = [thePath stringByAppendingPathComponent: [fileEl name]]; 296 if ([fileEl isDir]) 297 { 298 [theClient changeWorkingDir:thePath]; 299 [self readDirWith:theClient toTable:theTable andView:theView]; 300 [self updatePath :thePathMenu :[theClient workDirSplit]]; 301 } 302 else 303 { 304 if (theView == localView) 305 { 306 [self performStoreFile]; 307 } 308 else 309 { 310 [self performRetrieveFile]; 311 } 312 } 313} 314 315- (BOOL)dropValidate:(id)sender paths:(NSArray *)paths 316{ 317 if (threadRunning) 318 { 319 NSLog(@"thread was still running"); 320 return NO; 321 } 322 323 if (sender == localTableData) 324 { 325 /* the local view opens the file or the directory, it can be just one */ 326 if ([paths count] != 1) 327 return NO; 328 } 329 330 return YES; 331} 332 333- (void)dropAction:(id)sender paths:(NSArray *)paths 334{ 335 NSUInteger i; 336 NSFileManager *fm; 337 NSMutableArray *arr; 338 339 arr = [[NSMutableArray alloc] initWithCapacity:[paths count]]; 340 fm = [NSFileManager defaultManager]; 341 for (i = 0; i < [paths count]; i++) 342 { 343 NSDictionary *attr; 344 NSString *path; 345 FileElement *fEl; 346 347 path = [paths objectAtIndex:i]; 348 attr = [fm fileAttributesAtPath:path traverseLink:YES]; 349 fEl = [[FileElement alloc] initWithPath:path andAttributes:attr]; 350 [arr addObject:fEl]; 351 [fEl release]; 352 } 353 354 /* locally, we accept only a directory and change to it 355 remotely, we store everything */ 356 if (sender == localTableData) 357 { 358 NSString *fileOrPath; 359 NSString *thePath; 360 NSFileManager *fm; 361 BOOL isDir; 362 363 fileOrPath = [paths objectAtIndex:0]; 364 fm = [NSFileManager defaultManager]; 365 366 if ([fm fileExistsAtPath:fileOrPath isDirectory:&isDir] == NO) 367 { 368 [arr release]; 369 return; 370 } 371 372 if (!isDir) 373 thePath = [fileOrPath stringByDeletingLastPathComponent]; 374 else 375 thePath = fileOrPath; 376 NSLog(@"trimmed path to: %@", thePath); 377 [local changeWorkingDir:thePath]; 378 [self readDirWith:local toTable:localTableData andView:localView]; 379 380 [self updatePath :localPath :[local workDirSplit]]; 381 } 382 else if (sender == remoteTableData) 383 { 384 NSLog(@"will upload: %@", arr); 385 [self storeFiles]; 386 } 387 [arr release]; 388} 389 390- (void)tableView:(NSTableView *)tableView didClickTableColumn:(NSTableColumn *)tableColumn 391{ 392 if (tableView == localView) 393 { 394 [localTableData sortByIdent: [tableColumn identifier]]; 395 [localView reloadData]; 396 } 397 else 398 { 399 [remoteTableData sortByIdent: [tableColumn identifier]]; 400 [remoteView reloadData]; 401 } 402} 403 404- (void)setInterfaceEnabled:(BOOL)flag 405{ 406 [localView setEnabled:flag]; 407 [remoteView setEnabled:flag]; 408 [localPath setEnabled:flag]; 409 [remotePath setEnabled:flag]; 410 [buttUpload setEnabled:flag]; 411 [buttDownload setEnabled:flag]; 412} 413 414- (void)setThreadRunningState:(BOOL)flag 415{ 416 threadRunning = flag; 417 [self setInterfaceEnabled:!flag]; 418} 419 420/** retrieves using selection, by constructing an array and calling retrieveFiles */ 421- (void)performRetrieveFile 422{ 423 NSEnumerator *elemEnum; 424 FileElement *fileEl; 425 id currEl; 426 427 /* make a copy of the selection */ 428 [filesInProcess release]; 429 filesInProcess = [[NSMutableArray alloc] init]; 430 elemEnum = [remoteView selectedRowEnumerator]; 431 432 while ((currEl = [elemEnum nextObject]) != nil) 433 { 434 fileEl = [remoteTableData elementAtIndex:[currEl intValue]]; 435 [filesInProcess addObject:fileEl]; 436 } 437 438 [self retrieveFiles]; 439} 440 441/** stores using selection, by constructing an array and calling storeFiles */ 442- (void)performStoreFile 443{ 444 NSEnumerator *elemEnum; 445 FileElement *fileEl; 446 id currEl; 447 448 /* make a copy of the selection */ 449 [filesInProcess release]; 450 filesInProcess = [[NSMutableArray alloc] init]; 451 elemEnum = [localView selectedRowEnumerator]; 452 453 while ((currEl = [elemEnum nextObject]) != nil) 454 { 455 fileEl = [localTableData elementAtIndex:[currEl intValue]]; 456 [filesInProcess addObject:fileEl]; 457 } 458 [self storeFiles]; 459} 460 461/** Retrieves Array of FileElements */ 462- (void)retrieveFiles 463{ 464 if([filesInProcess count] > 0) 465 { 466 FileElement *fEl; 467 468 [self setThreadRunningState:YES]; 469 fEl = [filesInProcess objectAtIndex:0]; 470 NSLog(@"should download (performRETRIEVE): %@", [fEl name]); 471 [ftp retrieveFile:fEl to:local]; 472 } 473} 474 475/* called by the worker thread when the element got processed */ 476- (oneway void)fileRetrieved:(BOOL)success 477{ 478 FileElement *fEl; 479 480 fEl = [filesInProcess objectAtIndex:0]; 481 if (success) 482 { 483 if (![localTableData containsFileName:[fEl name]]) 484 { 485 FileElement *fEl2; 486 487 fEl2 = [[FileElement alloc] initWithPath:[[local workingDir] stringByAppendingPathComponent:[fEl name]] andAttributes:[fEl attributes]]; 488 [localTableData addObject:fEl2]; 489 [fEl2 release]; 490 } 491 } 492 [filesInProcess removeObjectAtIndex:0]; 493 if ([filesInProcess count] > 0) 494 { 495 [self retrieveFiles]; 496 } 497 else 498 { 499 [localView deselectAll:self]; 500 [localView reloadData]; 501 [self setThreadRunningState:NO]; 502 [filesInProcess release]; 503 filesInProcess = nil; 504 } 505} 506 507/** Stores Array of FileElements */ 508- (void)storeFiles 509{ 510 if([filesInProcess count] > 0) 511 { 512 FileElement *fEl; 513 514 [self setThreadRunningState:YES]; 515 fEl = [filesInProcess objectAtIndex:0]; 516 NSLog(@"should download (performStore): %@", [fEl name]); 517 [ftp storeFile:fEl from:local]; 518 } 519} 520 521/* called by the worker thread when the element got processed */ 522- (oneway void)fileStored:(BOOL)success 523{ 524 FileElement *fEl; 525 526 fEl = [filesInProcess objectAtIndex:0]; 527 if (success) 528 { 529 if (![remoteTableData containsFileName:[fEl name]]) 530 { 531 FileElement *fEl2; 532 533 fEl2 = [[FileElement alloc] initWithPath:[[ftp workingDir] stringByAppendingPathComponent:[fEl name]] andAttributes:[fEl attributes]]; 534 [remoteTableData addObject:fEl2]; 535 [fEl2 release]; 536 } 537 } 538 [filesInProcess removeObjectAtIndex:0]; 539 if ([filesInProcess count] > 0) 540 { 541 [self storeFiles]; 542 } 543 else 544 { 545 [remoteView deselectAll:self]; 546 [remoteView reloadData]; 547 [self setThreadRunningState:NO]; 548 [filesInProcess release]; 549 filesInProcess = nil; 550 } 551} 552 553 554- (IBAction)downloadButton:(id)sender 555{ 556 if (threadRunning) 557 { 558 NSLog(@"thread was still running"); 559 return; 560 } 561 562 [self performRetrieveFile]; 563} 564 565- (IBAction)uploadButton:(id)sender 566{ 567 if (threadRunning) 568 { 569 NSLog(@"thread was still running"); 570 return; 571 } 572 573 [self performStoreFile]; 574} 575 576- (IBAction)localDelete:(id)sender 577{ 578 NSEnumerator *elemEnum; 579 FileElement *fileEl; 580 id currEl; 581 NSMutableArray *selArray; 582 NSUInteger i; 583 584 /* make a copy of the selection */ 585 selArray = [[NSMutableArray alloc] init]; 586 elemEnum = [localView selectedRowEnumerator]; 587 while ((currEl = [elemEnum nextObject]) != nil) 588 { 589 fileEl = [localTableData elementAtIndex:[currEl intValue]]; 590 [selArray addObject:fileEl]; 591 } 592 593 /* perform deletes */ 594 for (i = 0; i < [selArray count]; i++) 595 { 596 fileEl = [selArray objectAtIndex:i]; 597 if([local deleteFile:fileEl beingAt:0]) 598 [localTableData removeObject:fileEl]; 599 } 600 [localView deselectAll:self]; 601 [localView reloadData]; 602 [selArray release]; 603} 604 605- (IBAction)remoteDelete:(id)sender 606{ 607 NSEnumerator *elemEnum; 608 FileElement *fileEl; 609 id currEl; 610 NSMutableArray *selArray; 611 NSUInteger i; 612 613 /* make a copy of the selection */ 614 selArray = [[NSMutableArray alloc] init]; 615 elemEnum = [remoteView selectedRowEnumerator]; 616 while ((currEl = [elemEnum nextObject]) != nil) 617 { 618 fileEl = [remoteTableData elementAtIndex:[currEl intValue]]; 619 [selArray addObject:fileEl]; 620 } 621 622 /* perform deletes */ 623 for (i = 0; i < [selArray count]; i++) 624 { 625 fileEl = [selArray objectAtIndex:i]; 626 if ([ftp deleteFile:fileEl beingAt:0]) 627 [remoteTableData removeObject:fileEl]; 628 } 629 [remoteView deselectAll:self]; 630 [remoteView reloadData]; 631 [selArray release]; 632} 633 634- (IBAction)localRename:(id)sender 635{ 636 GetNameController *nameGetter; 637 NSInteger alertReturn; 638 NSEnumerator *elemEnum; 639 FileElement *fileEl; 640 id currEl; 641 642 elemEnum = [localView selectedRowEnumerator]; 643 644 while ((currEl = [elemEnum nextObject]) != nil) 645 { 646 fileEl = [localTableData elementAtIndex:[currEl intValue]]; 647 648 nameGetter = [[GetNameController alloc] init]; 649 [nameGetter setName:[fileEl name]]; 650 [nameGetter setTitle:@"Rename"]; 651 [nameGetter setMessage:@"Rename"]; 652 653 alertReturn = [nameGetter runAsModal]; 654 if (alertReturn == NSAlertDefaultReturn) 655 { 656 NSString *name; 657 658 name = [nameGetter name]; 659 NSLog(@"New name: %@", name); 660 [local renameFile:fileEl to:name]; 661 } 662 [nameGetter release]; 663 } 664 [localView reloadData]; 665} 666 667- (IBAction)remoteRename:(id)sender 668{ 669 GetNameController *nameGetter; 670 NSInteger alertReturn; 671 NSEnumerator *elemEnum; 672 FileElement *fileEl; 673 id currEl; 674 675 elemEnum = [remoteView selectedRowEnumerator]; 676 677 while ((currEl = [elemEnum nextObject]) != nil) 678 { 679 fileEl = [remoteTableData elementAtIndex:[currEl intValue]]; 680 681 nameGetter = [[GetNameController alloc] init]; 682 [nameGetter setName:[fileEl name]]; 683 [nameGetter setTitle:@"Rename"]; 684 [nameGetter setMessage:@"Rename"]; 685 686 alertReturn = [nameGetter runAsModal]; 687 if (alertReturn == NSAlertDefaultReturn) 688 { 689 NSString *name; 690 691 name = [nameGetter name]; 692 NSLog(@"New name: %@", name); 693 [ftp renameFile:fileEl to:name]; 694 } 695 [nameGetter release]; 696 } 697 [remoteView reloadData]; 698} 699 700- (IBAction)localNewFolder:(id)sender 701{ 702 GetNameController *nameGetter; 703 NSInteger alertReturn; 704 705 nameGetter = [[GetNameController alloc] init]; 706 [nameGetter setName:@"New Folder"]; 707 [nameGetter setTitle:@"New Folder"]; 708 [nameGetter setMessage:@"New Folder"]; 709 710 alertReturn = [nameGetter runAsModal]; 711 if (alertReturn == NSAlertDefaultReturn) 712 { 713 NSString *name; 714 NSString *fullPath; 715 716 name = [nameGetter name]; 717 fullPath = [[local workingDir] stringByAppendingPathComponent:name]; 718 if ([local createNewDir:fullPath]) 719 { 720 FileElement *fileEl; 721 NSDictionary *attrs; 722 723 attrs = [NSDictionary dictionaryWithObjectsAndKeys: 724 NSFileTypeDirectory, NSFileType, 725 NULL]; 726 fileEl = [[FileElement alloc] initWithPath:fullPath andAttributes:attrs]; 727 [localTableData addObject:fileEl]; 728 [fileEl release]; 729 [localView reloadData]; 730 } 731 } 732 [nameGetter release]; 733} 734 735- (IBAction)remoteNewFolder:(id)sender 736{ 737 GetNameController *nameGetter; 738 NSInteger alertReturn; 739 740 nameGetter = [[GetNameController alloc] init]; 741 [nameGetter setName:@"New Folder"]; 742 [nameGetter setTitle:@"New Folder"]; 743 [nameGetter setMessage:@"New Folder"]; 744 745 alertReturn = [nameGetter runAsModal]; 746 if (alertReturn == NSAlertDefaultReturn) 747 { 748 NSString *name; 749 NSString *fullPath; 750 751 name = [nameGetter name]; 752 fullPath = [[ftp workingDir] stringByAppendingPathComponent:name]; 753 if ([ftp createNewDir:fullPath]) 754 { 755 FileElement *fileEl; 756 NSDictionary *attrs; 757 758 attrs = [NSDictionary dictionaryWithObjectsAndKeys: 759 NSFileTypeDirectory, NSFileType, 760 NULL]; 761 fileEl = [[FileElement alloc] initWithPath:fullPath andAttributes:attrs]; 762 [remoteTableData addObject:fileEl]; 763 [fileEl release]; 764 [remoteView reloadData]; 765 } 766 } 767 [nameGetter release]; 768} 769 770- (IBAction)localRefresh:(id)sender 771{ 772 [self readDirWith:local toTable:localTableData andView:localView]; 773} 774 775- (IBAction)remoteRefresh:(id)sender 776{ 777 [self readDirWith:ftp toTable:remoteTableData andView:remoteView]; 778} 779 780- (oneway void)setTransferBegin:(in bycopy NSString *)name :(unsigned long long)size 781{ 782 [infoMessage setStringValue:name]; 783 [progBar setDoubleValue:0]; 784 beginTimeVal = [NSDate timeIntervalSinceReferenceDate]; 785 transferSize = size; 786 NSLog(@"begin transfer size: %llu", transferSize); 787 if (transferSize == 0) 788 { 789 [progBar setIndeterminate:YES]; 790 [progBar startAnimation:nil]; 791 } 792 [mainWin displayIfNeeded]; 793} 794 795- (oneway void)setTransferProgress:(in bycopy NSNumber *)bytesTransferred 796{ 797 NSTimeInterval currTimeVal; 798 float speed; 799 NSString *speedStr; 800 NSString *sizeStr; 801 double percent; 802 unsigned long long bytes; 803 804 bytes = [bytesTransferred unsignedLongLongValue]; 805 currTimeVal = [NSDate timeIntervalSinceReferenceDate]; 806 speed = (float)((double)bytes / (double)(currTimeVal - beginTimeVal)); 807 808 if (transferSize > 0) 809 { 810 percent = ((double)bytes / (double)transferSize) * 100; 811 [progBar setDoubleValue:percent]; 812 } 813 814 speedStr = [NSString alloc]; 815 if (speed < 1024) 816 speedStr = [speedStr initWithFormat:@"%3.2fB/s", speed]; 817 else if (speed < 1024*1024) 818 speedStr = [speedStr initWithFormat:@"%3.2fKB/s", speed/1024]; 819 else 820 speedStr = [speedStr initWithFormat:@"%3.2fMB/s", speed/(1024*1024)]; 821 [infoSpeed setStringValue:speedStr]; 822 [speedStr release]; 823 824 sizeStr = [NSString alloc]; 825 826 if (transferSize < 1024 && transferSize != 0) /* except 0, which means unknown */ 827 sizeStr = [sizeStr initWithFormat:@"%3.2f : %3.2f B", (float)bytes, (float)transferSize]; 828 else if (transferSize < 1024*1024) 829 sizeStr = [sizeStr initWithFormat:@"%3.2f : %3.2f KB", (double)bytes/1024, (double)transferSize/1024]; 830 else 831 sizeStr = [sizeStr initWithFormat:@"%3.2f : %3.2f MB", (double)bytes/(1024*1024), (double)transferSize/(1024*1024)]; 832 [infoSize setStringValue:sizeStr]; 833 [sizeStr release]; 834} 835 836- (oneway void)setTransferEnd:(in bycopy NSNumber *)bytesTransferred 837{ 838 NSTimeInterval currTimeVal; 839 NSTimeInterval deltaT; 840 float speed; 841 NSString *speedStr; 842 NSString *sizeStr; 843 double percent; 844 unsigned long long bytes; 845 846 bytes = [bytesTransferred unsignedLongLongValue]; 847 currTimeVal = [NSDate timeIntervalSinceReferenceDate]; 848 deltaT = (currTimeVal - beginTimeVal); 849 speed = (float)((double)bytes / deltaT); 850 NSLog(@"Elapsed time: %f", (float)deltaT); 851 percent = ((double)bytes / (double)transferSize) * 100; 852 speedStr = [NSString alloc]; 853 if (speed < 1024) 854 speedStr = [speedStr initWithFormat:@"%3.2fB/s", speed]; 855 else if (speed < 1024*1024) 856 speedStr = [speedStr initWithFormat:@"%3.2fKB/s", speed/1024]; 857 else 858 speedStr = [speedStr initWithFormat:@"%3.2fMB/s", speed/(1024*1024)]; 859 [infoSpeed setStringValue:speedStr]; 860 [speedStr release]; 861 862 sizeStr = [NSString alloc]; 863 if (transferSize < 1024) 864 sizeStr = [sizeStr initWithFormat:@"%3.2f : %3.2f B", (float)bytes, (float)transferSize]; 865 else if (transferSize < 1024*1024) 866 sizeStr = [sizeStr initWithFormat:@"%3.2f : %3.2f KB", (double)bytes/1024, (double)transferSize/1024]; 867 else 868 sizeStr = [sizeStr initWithFormat:@"%3.2f : %3.2f MB", (double)bytes/(1024*1024), (double)transferSize/(1024*1024)]; 869 [infoSize setStringValue:sizeStr]; 870 [sizeStr release]; 871 872 if ([progBar isIndeterminate]) 873 { 874 [progBar stopAnimation:nil]; 875 [progBar setIndeterminate:NO]; 876 } 877 [progBar setDoubleValue:percent]; 878 [mainWin displayIfNeeded]; 879} 880 881- (IBAction)disconnect:(id)sender 882{ 883 [ftp disconnect]; 884 [mainWin setTitle:@"FTP"]; 885 [remotePath removeAllItems]; 886 [remotePath addItemWithTitle:@"Remote View"]; 887 [remoteTableData clear]; 888 [remoteView reloadData]; 889 [self setThreadRunningState:NO]; 890} 891 892- (IBAction)showPrefPanel:(id)sender 893{ 894 [prefPanel makeKeyAndOrderFront:self]; 895 switch (connMode) 896 { 897 case defaultMode: 898 [portType selectCellWithTag:0]; 899 break; 900 case portMode: 901 [portType selectCellWithTag:1]; 902 break; 903 case passiveMode: 904 [portType selectCellWithTag:2]; 905 break; 906 default: 907 NSLog(@"Unexpected mode on pref pane setup."); 908 } 909} 910 911- (IBAction)prefSave:(id)sender 912{ 913 NSUserDefaults *defaults; 914 915 defaults = [NSUserDefaults standardUserDefaults]; 916 917 918 switch ([[portType selectedCell] tag]) 919 { 920 case 0: 921 //default 922 NSLog(@"default"); 923 connMode = defaultMode; 924 [ftp setPortDefault]; 925 [defaults setObject:@"default" forKey:connectionModeKey]; 926 break; 927 case 1: 928 //port 929 NSLog(@"port"); 930 connMode = portMode; 931 [ftp setPortPort]; 932 [defaults setObject:@"port" forKey:connectionModeKey]; 933 break; 934 case 2: 935 // passive 936 NSLog(@"passive"); 937 connMode = passiveMode; 938 [ftp setPortPassive]; 939 [defaults setObject:@"passive" forKey:connectionModeKey]; 940 break; 941 default: 942 NSLog(@"unexpected selection"); 943 } 944 [prefPanel performClose:nil]; 945} 946 947- (IBAction)prefCancel:(id)sender 948{ 949 [prefPanel performClose:nil]; 950} 951 952- (IBAction)showFtpLog:(id)sender 953{ 954 [logWin makeKeyAndOrderFront:self]; 955} 956 957/** 958 Called by the server object to register itself. 959 */ 960- (void)setServer:(id)anObject 961{ 962 ftp = (FtpClient*)[anObject retain]; 963} 964 965- (oneway void)appendTextToLog:(NSString *)textChunk 966{ 967 NSAttributedString *attrStr; 968 969 attrStr = [[NSAttributedString alloc] initWithString: textChunk 970 attributes: textAttributes]; 971 972 /* add the textChunk to the NSTextView's backing store as an attributed string */ 973 [[logTextField textStorage] appendAttributedString: attrStr]; 974 975 976 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantPast]]; 977 [logTextField scrollRangeToVisible:NSMakeRange([[logTextField string] length], 0)]; 978 979 [attrStr autorelease]; 980} 981 982 983/* --- connection panel methods --- */ 984- (IBAction)showConnPanel:(id)sender 985{ 986 [connectPanel makeKeyAndOrderFront:self]; 987} 988 989- (IBAction)connectConn:(id)sender 990{ 991 NSArray *dirList; 992 char tempStr[1024]; 993 NSString *u; 994 NSString *p; 995 996 [connectPanel performClose:nil]; 997 [mainWin makeKeyAndOrderFront:self]; 998 999 ftp = [ftp initWithController:self :connMode]; 1000 [[connAddress stringValue] getCString:tempStr]; 1001 if ([ftp connect:[connPort intValue] :tempStr] < 0) 1002 { 1003 NSRunAlertPanel(@"Error", @"Connection failed.\nCheck that you typed the host name correctly.", @"Ok", nil, nil); 1004 NSLog(@"connection failed in connectConn"); 1005 return; 1006 } 1007 if ([connAnon state] == NSOnState) 1008 { 1009 u = @"anonymous"; 1010 p = @"user@myhost.com"; 1011 } 1012 else 1013 { 1014 u = [connUser stringValue]; 1015 p = [connPass stringValue]; 1016 } 1017 if ([ftp authenticate:u :p] < 0) 1018 { 1019 NSRunAlertPanel(@"Error", @"Authentication failed.\nCheck that your username and password are correct.", @"Ok", nil, nil); 1020 NSLog(@"authentication failed."); 1021 return; 1022 } 1023 else 1024 { 1025 [ftp setWorkingDir:[ftp homeDir]]; 1026 if ((dirList = [ftp dirContents]) == nil) 1027 return; 1028 [remoteTableData initData:dirList]; 1029 [remoteView reloadData]; 1030 1031 /* update the path menu */ 1032 [self updatePath :remotePath :[ftp workDirSplit]]; 1033 1034 /* set the window title */ 1035 [mainWin setTitle:[connAddress stringValue]]; 1036 } 1037} 1038 1039- (IBAction)cancelConn:(id)sender 1040{ 1041 [connectPanel performClose:nil]; 1042} 1043 1044- (IBAction)anonymousConn:(id)sender 1045{ 1046 if ([connAnon state] == NSOnState) 1047 { 1048 [connUser setEnabled:NO]; 1049 [connPass setEnabled:NO]; 1050 } 1051 else 1052 { 1053 [connUser setEnabled:YES]; 1054 [connPass setEnabled:YES]; 1055 } 1056} 1057 1058 1059- (void)showAlertDialog:(NSString *)message 1060{ 1061 [message retain]; 1062 NSRunAlertPanel(@"Attention", message, @"Ok", nil, nil); 1063 [message release]; 1064} 1065 1066- (connectionModes)connectionMode 1067{ 1068 return connMode; 1069} 1070 1071@end 1072