/[gnustep]/gnustep/usr-apps/gworkspace/GWRemote/gwsd/gwsd.m
ViewVC logotype

Contents of /gnustep/usr-apps/gworkspace/GWRemote/gwsd/gwsd.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations) (download)
Sun Sep 28 10:40:21 2003 UTC (20 years, 7 months ago) by esersale
Branch: MAIN
Changes since 1.3: +3 -3 lines
*** empty log message ***

1 /* gwsd.m
2 *
3 * Copyright (C) 2003 Free Software Foundation, Inc.
4 *
5 * Author: Enrico Sersale <enrico@imago.ro>
6 * Date: August 2001
7 *
8 * This file is part of the GNUstep gwsd tool
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25 #include <AppKit/AppKit.h>
26 #include "gwsd.h"
27 #include "FileOp.h"
28 #include "externs.h"
29 #include "Functions.h"
30 #include "GNUstep.h"
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <limits.h>
34 #include <pwd.h>
35
36 #ifndef LONG_DELAY
37 #define LONG_DELAY 86400.0
38 #endif
39
40 #define byname 0
41 #define bykind 1
42 #define bydate 2
43 #define bysize 3
44 #define byowner 4
45
46 #define MAX_FILE_SIZE 41200
47
48 #ifndef CACHED_MAX
49 #define CACHED_MAX 20;
50 #endif
51
52 static GWSd *shared = nil;
53
54 @implementation GWSd
55
56 + (void)initialize
57 {
58 /* */
59 /* only the thread that sends the first message to the class */
60 /* will execute the initialize method. */
61 /* */
62
63 if ([self class] == [GWSd class]) {
64 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
65 id entry = [defaults objectForKey: @"cachedmax"];
66 if (entry) {
67 cachedMax = [entry intValue];
68 } else {
69 cachedMax = CACHED_MAX;
70 }
71
72 cachedContents = [NSMutableDictionary new];
73 gwsdLock = [NSRecursiveLock new];
74
75 [GWSd sharedGWSd];
76 }
77 }
78
79 + (GWSd *)sharedGWSd
80 {
81 /* */
82 /* we use this shared istance for notifications that must */
83 /* be received by all the others. */
84 /* */
85
86 if (shared == nil) {
87 shared = [[GWSd alloc] init];
88 }
89 return shared;
90 }
91
92 - (id)initWithRemote:(id)remote
93 connection:(NSConnection *)aConnection
94 {
95 self = [super init];
96
97 if(self) {
98 NSUserDefaults *defaults;
99 id entry;
100
101 defaults = [NSUserDefaults standardUserDefaults];
102
103 entry = [defaults objectForKey: @"defaultsorttype"];
104 if (entry == nil) {
105 [defaults setObject: @"0" forKey: @"defaultsorttype"];
106 defSortType = byname;
107 } else {
108 defSortType = [entry intValue];
109 }
110
111 entry = [defaults objectForKey: @"GSFileBrowserHideDotFiles"];
112 if (entry) {
113 hideSysFiles = [entry boolValue];
114 } else {
115 NSDictionary *domain = [defaults persistentDomainForName: NSGlobalDomain];
116
117 entry = [domain objectForKey: @"GSFileBrowserHideDotFiles"];
118 if (entry) {
119 hideSysFiles = [entry boolValue];
120 } else {
121 hideSysFiles = NO;
122 }
123 }
124
125 entry = [defaults objectForKey: @"shellCommand"];
126 if (entry == nil) {
127 NSLog(@"no shell defined.\nYou must set the default shell:");
128 NSLog(@"\"defaults write gwsd shellCommand \"/bin/bash\"\", for example.");
129 exit(0);
130 }
131 ASSIGN (shellCommand, entry);
132
133 gwsdClient = nil;
134
135 if (remote) {
136 /* */
137 /* We get here when a new GWSd istance is created for a new thread */
138 /* */
139
140 watchers = [NSMutableArray new];
141 watchTimers = [NSMutableArray new];
142
143 operations = [NSMutableArray new];
144 oprefnum = 0;
145
146 shellTasks = [NSMutableArray new];
147
148 nc = [NSNotificationCenter defaultCenter];
149 dnc = [NSDistributedNotificationCenter defaultCenter];
150 fm = [NSFileManager defaultManager];
151 ws = [NSWorkspace sharedWorkspace];
152
153 sharedIstance = [GWSd sharedGWSd];
154
155 [dnc addObserver: self
156 selector: @selector(fileSystemDidChange:)
157 name: GWFileSystemDidChangeNotification
158 object: nil];
159
160 conn = RETAIN (aConnection);
161 [conn setIndependentConversationQueueing: YES];
162 [conn setRootObject: self];
163 [conn setDelegate: self];
164
165 [nc addObserver: self
166 selector: @selector(connectionDidDie:)
167 name: NSConnectionDidDieNotification
168 object: conn];
169
170 [remote setProtocolForProxy: @protocol(GWSdClientProtocol)];
171 gwsdClient = (id <GWSdClientProtocol>)remote;
172
173 clientLock = [NSRecursiveLock new];
174 } else {
175 /* */
176 /* Here, only in the main thread, we create the connection that */
177 /* will be used by our clients to connect. */
178 /* This connection will be substitudted with a not named connection, */
179 /* that is, a new connection for each thread/client, */
180 /* in +newThreadWithRemote: */
181 /* */
182
183 NSProcessInfo *proc = [NSProcessInfo processInfo];
184 NSArray *args = [proc arguments];
185 NSString *passwd;
186
187 if ([args count] < 2) {
188 NSLog(@"Missing password\nUsage: gwsd PASSWORD");
189 exit(0);
190 }
191
192 passwd = [args objectAtIndex: 1];
193
194 if ([passwd cStringLength] < 8) {
195 NSLog(@"Invalid password\nThe password must have altmost 8 characters");
196 exit(0);
197 }
198
199 ASSIGN (userPassword, passwd);
200 ASSIGN (userName, NSUserName());
201
202 firstConn = [[NSConnection alloc] initWithReceivePort: [NSSocketPort port]
203 sendPort: nil];
204 [firstConn enableMultipleThreads];
205 [firstConn setRootObject: self];
206 [firstConn registerName: @"gwsd"];
207 [firstConn setRequestTimeout: LONG_DELAY];
208 [firstConn setReplyTimeout: LONG_DELAY];
209 [firstConn setDelegate: self];
210
211 [[NSNotificationCenter defaultCenter] addObserver: self
212 selector: @selector(connectionDidDie:)
213 name: NSConnectionDidDieNotification
214 object: firstConn];
215 }
216 }
217
218 return self;
219 }
220
221 + (void)newThreadWithRemote:(id<GWSdClientProtocol>)remote
222 {
223 /* */
224 /* Here, for each new client, we create a new connection and */
225 /* a new GWSd istance. */
226 /* After calling -setServerConnection: on the client, we can release */
227 /* both the GWSd object and the NSConnection, because they ere retained */
228 /* by the client. */
229 /* This means that, when the client exits, these objects are released */
230 /* and the thread exits (I hope...). */
231 /* */
232
233 NSAutoreleasePool *pool;
234 NSConnection *connection;
235 GWSd *gwsd;
236
237 pool = [[NSAutoreleasePool alloc] init];
238
239 connection = [[NSConnection alloc] initWithReceivePort: [NSSocketPort port]
240 sendPort: [NSSocketPort port]];
241
242 gwsd = [[GWSd alloc] initWithRemote: remote connection: connection];
243
244 [remote setServerConnection: connection];
245
246 RELEASE (gwsd);
247 RELEASE (connection);
248
249 [[NSRunLoop currentRunLoop] run];
250 [pool release];
251 }
252
253 - (void)_registerRemoteClient:(id<GWSdClientProtocol>)remote
254 {
255 /* */
256 /* This method is called, in the main thread, by each client that */
257 /* wants to connect. */
258 /* A new thread is detached for each client. */
259 /* */
260
261 if (([userName isEqual: [remote userName]] == NO)
262 || ([userPassword isEqual: [remote userPassword]] == NO)) {
263 [remote connectionRefused];
264 return;
265 }
266
267 NS_DURING
268 {
269 [NSThread detachNewThreadSelector: @selector(newThreadWithRemote:)
270 toTarget: [self class]
271 withObject: remote];
272 }
273 NS_HANDLER
274 {
275 NSLog(@"Error! A fatal error occured while detaching the thread.\nRecompile your runtime with threads support.");
276 }
277 NS_ENDHANDLER
278 }
279
280 - (id<GWSdClientProtocol>)gwsdClient
281 {
282 return gwsdClient;
283 }
284
285 - (NSRecursiveLock *)clientLock
286 {
287 return clientLock;
288 }
289
290 - (void)connectionDidDie:(NSNotification *)notification
291 {
292 id diedconn = [notification object];
293
294 [[NSNotificationCenter defaultCenter] removeObserver: self
295 name: NSConnectionDidDieNotification object: diedconn];
296
297 if (diedconn == firstConn) {
298 NSLog(@"argh - gwsd server root connection has been destroyed.");
299 exit(1);
300 } else if (diedconn == conn) {
301
302
303 }
304 }
305
306
307 //
308 // Private methods
309 //
310 - (NSMutableDictionary *)cachedRepresentationForPath:(NSString *)path
311 {
312 NSMutableDictionary *contents = [cachedContents objectForKey: path];
313
314 if (contents) {
315 NSDate *modDate = [contents objectForKey: @"moddate"];
316 NSDate *date = [self modificationDateForPath: path];
317
318 if ([modDate isEqualToDate: date]) {
319 return contents;
320 } else {
321 [cachedContents removeObjectForKey: path];
322 }
323 }
324
325 return nil;
326 }
327
328 - (void)removeCachedRepresentation
329 {
330 NSArray *keys = [cachedContents allKeys];
331
332 if ([keys count]) {
333 [cachedContents removeObjectForKey: [keys objectAtIndex: 0]];
334 }
335 }
336
337 - (BOOL)hideSysFiles
338 {
339 return hideSysFiles;
340 }
341
342 - (NSArray *)checkHiddenFiles:(NSArray *)files atPath:(NSString *)path
343 {
344 NSArray *checkedFiles;
345 NSArray *hiddenFiles;
346 NSString *h;
347
348 h = [path stringByAppendingPathComponent: @".hidden"];
349 if ([fm fileExistsAtPath: h]) {
350 h = [NSString stringWithContentsOfFile: h];
351 hiddenFiles = [h componentsSeparatedByString: @"\n"];
352 } else {
353 hiddenFiles = nil;
354 }
355
356 if (hiddenFiles != nil || hideSysFiles) {
357 NSMutableArray *mutableFiles = AUTORELEASE ([files mutableCopy]);
358
359 if (hiddenFiles != nil) {
360 [mutableFiles removeObjectsInArray: hiddenFiles];
361 }
362
363 if (hideSysFiles) {
364 int j = [mutableFiles count] - 1;
365
366 while (j >= 0) {
367 NSString *file = (NSString *)[mutableFiles objectAtIndex: j];
368
369 if ([file hasPrefix: @"."]) {
370 [mutableFiles removeObjectAtIndex: j];
371 }
372 j--;
373 }
374 }
375
376 checkedFiles = mutableFiles;
377
378 } else {
379 checkedFiles = files;
380 }
381
382 return checkedFiles;
383 }
384
385 - (BOOL)verifyFileAtPath:(NSString *)path
386 {
387 if ([fm fileExistsAtPath: path] == NO) {
388 NSString *fileName = [path lastPathComponent];
389 NSString *message = [NSString stringWithFormat: @"%@: no such file or directory!", fileName];
390
391 [gwsdClient showErrorAlertWithMessage: message];
392
393 return NO;
394 }
395
396 return YES;
397 }
398
399 - (void)dealloc
400 {
401 [nc removeObserver: self];
402 [dnc removeObserver: self];
403
404 TEST_RELEASE (userName);
405 TEST_RELEASE (userPassword);
406
407 TEST_RELEASE (watchers);
408 TEST_RELEASE (watchTimers);
409
410 TEST_RELEASE (operations);
411
412 TEST_RELEASE (shellCommand);
413 TEST_RELEASE (shellTasks);
414
415 TEST_RELEASE (clientLock);
416
417 DESTROY (firstConn);
418 DESTROY (conn);
419
420 [super dealloc];
421 }
422
423
424 //
425 // GWSDProtocol
426 //
427 - (void)registerRemoteClient:(id<GWSdClientProtocol>)remote
428 {
429 return [self _registerRemoteClient: remote];
430 }
431
432 - (NSString *)homeDirectory
433 {
434 return NSHomeDirectory();
435 }
436
437 - (BOOL)existsFileAtPath:(NSString *)path
438 {
439 return [fm fileExistsAtPath: path];
440 }
441
442 - (BOOL)existsAndIsDirectoryFileAtPath:(NSString *)path
443 {
444 BOOL isDir;
445 return ([fm fileExistsAtPath: path isDirectory: &isDir] && isDir);
446 }
447
448 - (NSString *)typeOfFileAt:(NSString *)path
449 {
450 NSString *defApp, *type;
451
452 [ws getInfoForFile: path application: &defApp type: &type];
453
454 return type;
455 }
456
457 - (BOOL)isPakageAtPath:(NSString *)path
458 {
459 NSString *defApp, *type;
460
461 [ws getInfoForFile: path application: &defApp type: &type];
462
463 if (type == NSApplicationFileType) {
464 return YES;
465 } else if (type == NSPlainFileType) {
466 return [self existsAndIsDirectoryFileAtPath: path];
467 }
468
469 return NO;
470 }
471
472 - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)path
473 {
474 return [fm fileSystemAttributesAtPath: path];
475 }
476
477 - (BOOL)isWritableFileAtPath:(NSString *)path
478 {
479 return [fm isWritableFileAtPath: path];
480 }
481
482 - (NSDate *)modificationDateForPath:(NSString *)path
483 {
484 NSDictionary *attributes = [fm fileAttributesAtPath: path traverseLink: YES];
485
486 return [attributes fileModificationDate];
487 }
488
489 - (int)sortTypeForDirectoryAtPath:(NSString *)aPath
490 {
491 if ([fm isWritableFileAtPath: aPath]) {
492 NSString *dictPath = [aPath stringByAppendingPathComponent: @".gwsort"];
493
494 if ([fm fileExistsAtPath: dictPath]) {
495 NSDictionary *sortDict = [NSDictionary dictionaryWithContentsOfFile: dictPath];
496
497 if (sortDict) {
498 return [[sortDict objectForKey: @"sort"] intValue];
499 }
500 }
501 }
502
503 return defSortType;
504 }
505
506 - (void)setSortType:(int)type forDirectoryAtPath:(NSString *)aPath
507 {
508 if ([fm isWritableFileAtPath: aPath]) {
509 NSString *sortstr = [NSString stringWithFormat: @"%i", type];
510 NSDictionary *dict = [NSDictionary dictionaryWithObject: sortstr
511 forKey: @"sort"];
512 [dict writeToFile: [aPath stringByAppendingPathComponent: @".gwsort"]
513 atomically: YES];
514 }
515
516 // [[NSNotificationCenter defaultCenter]
517 // postNotificationName: GWSortTypeDidChangeNotification
518 // object: (id)aPath];
519 }
520
521 - (NSDictionary *)directoryContentsAtPath:(NSString *)path
522 {
523 NSMutableDictionary *contentsDict;
524 NSArray *files;
525 NSMutableArray *sortfiles;
526 NSMutableArray *paths;
527 NSString *s;
528 int i, count;
529 int stype;
530
531 if ([self existsAndIsDirectoryFileAtPath: path] == NO) {
532 return nil;
533 }
534
535 [gwsdLock lock];
536 contentsDict = [self cachedRepresentationForPath: path];
537 [gwsdLock unlock];
538 if (contentsDict) {
539 return contentsDict;
540 }
541
542 files = [self checkHiddenFiles: [fm directoryContentsAtPath: path]
543 atPath: path];
544
545 count = [files count];
546 if (count == 0) {
547 return nil;
548 }
549
550 paths = [NSMutableArray arrayWithCapacity: count];
551
552 for (i = 0; i < count; ++i) {
553 s = [path stringByAppendingPathComponent: [files objectAtIndex: i]];
554 [paths addObject: s];
555 }
556
557 stype = [self sortTypeForDirectoryAtPath: path];
558
559 paths = AUTORELEASE ([[paths sortedArrayUsingFunction: (int (*)(id, id, void*))comparePaths
560 context: (void *)stype] mutableCopy]);
561
562 sortfiles = [NSMutableArray arrayWithCapacity: 1];
563 for (i = 0; i < count; ++i) {
564 [sortfiles addObject: [[paths objectAtIndex: i] lastPathComponent]];
565 }
566
567 contentsDict = [NSMutableDictionary dictionary];
568 [contentsDict setObject: [NSDate date] forKey: @"datestamp"];
569 [contentsDict setObject: [self modificationDateForPath: path] forKey: @"moddate"];
570 [contentsDict setObject: sortfiles forKey: @"files"];
571
572 [gwsdLock lock];
573 if ([cachedContents count] <= cachedMax) {
574 [self removeCachedRepresentation];
575 }
576
577 [cachedContents setObject: contentsDict forKey: path];
578 [gwsdLock unlock];
579
580 return contentsDict;
581 }
582
583 - (NSString *)contentsOfFileAt:(NSString *)path
584 {
585 NSDictionary *attributes = [fm fileAttributesAtPath: path traverseLink: YES];
586 long fsize = [[attributes objectForKey: @"NSFileSize"] longValue];
587
588 if (fsize >= MAX_FILE_SIZE) {
589 return nil;
590 } else {
591 return [NSString stringWithContentsOfFile: path];
592 }
593 }
594
595 - (BOOL)saveString:(NSString *)str atPath:(NSString *)path
596 {
597 NSDictionary *attributes = [fm fileAttributesAtPath: path traverseLink: YES];
598
599 if ([str writeToFile: path atomically: YES]) {
600 if (attributes) {
601 [fm changeFileAttributes: attributes atPath: path];
602 }
603 return YES;
604 }
605
606 return NO;
607 }
608
609 - (void)addWatcherForPath:(NSString *)path
610 {
611 [self _addWatcherForPath: path];
612 }
613
614 - (void)removeWatcherForPath:(NSString *)path
615 {
616 [self _removeWatcherForPath: path];
617 }
618
619 - (oneway void)performLocalFileOperationWithDictionary:(id)opdict
620 {
621 LocalFileOp *op = [[LocalFileOp alloc] initWithOperationDescription: opdict
622 forGWSd: self withClient: gwsdClient];
623 [operations addObject: op];
624 RELEASE (op);
625 }
626
627 - (BOOL)pauseFileOpeRationWithRef:(int)ref
628 {
629 LocalFileOp *op = [self fileOpWithRef: ref];
630 return (op && [op pauseOperation]);
631 }
632
633 - (BOOL)continueFileOpeRationWithRef:(int)ref
634 {
635 LocalFileOp *op = [self fileOpWithRef: ref];
636 return (op && [op continueOperation]);
637 }
638
639 - (BOOL)stopFileOpeRationWithRef:(int)ref
640 {
641 LocalFileOp *op = [self fileOpWithRef: ref];
642 return (op && [op stopOperation]);
643 }
644
645 - (oneway void)renamePath:(NSString *)oldname toNewName:(NSString *)newname
646 {
647 NSString *basepath = [oldname stringByDeletingLastPathComponent];
648 NSMutableDictionary *dict = [NSMutableDictionary dictionary];
649 NSString *message;
650
651 if ([fm isWritableFileAtPath: oldname] == NO) {
652 message = [NSString stringWithFormat:
653 @"You have not write permission\nfor \"%@\"!",
654 [oldname lastPathComponent]];
655 [gwsdClient showErrorAlertWithMessage: message];
656 return;
657
658 } else if ([fm isWritableFileAtPath: basepath] == NO) {
659 message = [NSString stringWithFormat:
660 @"You have not write permission\nfor \"%@\"!",
661 [basepath lastPathComponent]];
662 [gwsdClient showErrorAlertWithMessage: message];
663 return;
664
665 } else {
666 NSCharacterSet *notAllowSet = [NSCharacterSet characterSetWithCharactersInString: @"/\\*$|~\'\"`^!?"];
667 NSRange range = [[newname lastPathComponent] rangeOfCharacterFromSet: notAllowSet];
668 NSArray *dirContents = [fm directoryContentsAtPath: basepath];
669
670 if (range.length > 0) {
671 [gwsdClient showErrorAlertWithMessage: @"Invalid char in name"];
672 return;
673 }
674
675 if ([dirContents containsObject: newname]) {
676 if ([newname isEqualToString: oldname]) {
677 return;
678 } else {
679 message = [NSString stringWithFormat:
680 @"The name %@ is already in use!", [newname lastPathComponent]];
681 [gwsdClient showErrorAlertWithMessage: message];
682 return;
683 }
684 }
685
686 [self suspendWatchingForPath: basepath];
687
688 [fm movePath: oldname toPath: newname handler: self];
689
690 [dict setObject: basepath forKey: @"path"];
691 [dict setObject: GWFileDeletedInWatchedDirectory forKey: @"event"];
692 [dict setObject: [NSArray arrayWithObject: [oldname lastPathComponent]]
693 forKey: @"files"];
694
695 [gwsdClient server: self fileSystemDidChange: dict];
696
697 [[NSRunLoop currentRunLoop]
698 runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.5]];
699
700 [dict setObject: basepath forKey: @"path"];
701 [dict setObject: GWFileCreatedInWatchedDirectory forKey: @"event"];
702 [dict setObject: [NSArray arrayWithObject: [newname lastPathComponent]]
703 forKey: @"files"];
704
705 [self restartWatchingForPath: basepath];
706 }
707 }
708
709 - (oneway void)newObjectAtPath:(NSString *)basePath isDirectory:(BOOL)directory
710 {
711 NSString *fullPath;
712 NSString *fileName;
713 NSMutableDictionary *dict;
714 int suff;
715
716 if ([self verifyFileAtPath: basePath] == NO) {
717 return;
718 }
719
720 if ([fm isWritableFileAtPath: basePath] == NO) {
721 NSString *message = [NSString stringWithFormat:
722 @"You have not write permission for %@!", basePath];
723
724 [gwsdClient showErrorAlertWithMessage: message];
725 return;
726 }
727
728 if (directory == YES) {
729 fileName = @"NewFolder";
730 } else {
731 fileName = @"NewFile";
732 }
733
734 fullPath = [basePath stringByAppendingPathComponent: fileName];
735
736 if ([fm fileExistsAtPath: fullPath] == YES) {
737 suff = 1;
738 while (1) {
739 NSString *s = [fileName stringByAppendingFormat: @"%i", suff];
740 fullPath = [basePath stringByAppendingPathComponent: s];
741 if ([fm fileExistsAtPath: fullPath] == NO) {
742 fileName = [NSString stringWithString: s];
743 break;
744 }
745 suff++;
746 }
747 }
748
749 [self suspendWatchingForPath: basePath];
750
751 if (directory == YES) {
752 [fm createDirectoryAtPath: fullPath attributes: nil];
753 } else {
754 [fm createFileAtPath: fullPath contents: nil attributes: nil];
755 }
756
757 dict = [NSMutableDictionary dictionary];
758 [dict setObject: basePath forKey: @"path"];
759 [dict setObject: GWFileCreatedInWatchedDirectory forKey: @"event"];
760 [dict setObject: [NSArray arrayWithObject: [fullPath lastPathComponent]]
761 forKey: @"files"];
762
763 [gwsdClient server: self fileSystemDidChange: dict];
764
765 [self restartWatchingForPath: basePath];
766 }
767
768 - (oneway void)duplicateFiles:(NSArray *)files inDirectory:(NSString *)basePath
769 {
770 NSMutableDictionary *opDict = [NSMutableDictionary dictionary];
771
772 if ([fm isWritableFileAtPath: basePath] == NO) {
773 NSString *message = [NSString stringWithFormat:
774 @"You have not write permission for %@!", basePath];
775
776 [gwsdClient showErrorAlertWithMessage: message];
777 return;
778 }
779
780 [opDict setObject: NSWorkspaceDuplicateOperation forKey: @"operation"];
781 [opDict setObject: basePath forKey: @"source"];
782 [opDict setObject: basePath forKey: @"destination"];
783 [opDict setObject: files forKey: @"files"];
784
785 [self performLocalFileOperationWithDictionary: opDict];
786 }
787
788 - (oneway void)deleteFiles:(NSArray *)files inDirectory:(NSString *)basePath
789 {
790 NSMutableDictionary *opDict = [NSMutableDictionary dictionary];
791
792 if ([fm isWritableFileAtPath: basePath] == NO) {
793 NSString *message = [NSString stringWithFormat:
794 @"You have not write permission for %@!", basePath];
795
796 [gwsdClient showErrorAlertWithMessage: message];
797 return;
798 }
799
800 [opDict setObject: NSWorkspaceDestroyOperation forKey: @"operation"];
801 [opDict setObject: basePath forKey: @"source"];
802 [opDict setObject: basePath forKey: @"destination"];
803 [opDict setObject: files forKey: @"files"];
804
805 [self performLocalFileOperationWithDictionary: opDict];
806 }
807
808 - (BOOL)fileManager:(NSFileManager *)manager
809 shouldProceedAfterError:(NSDictionary *)errorDict
810 {
811 NSString *path = [errorDict objectForKey: @"Path"];
812 NSString *msg = [NSString stringWithFormat:
813 @"File operation error: %@\nwith file: %@\n",
814 [errorDict objectForKey: @"Error"], path];
815
816 return [gwsdClient requestUserConfirmationWithMessage: msg
817 title: @"error"];
818 }
819
820 - (void)fileManager:(NSFileManager *)manager willProcessPath:(NSString *)path
821 {
822 }
823
824 - (oneway void)openShellOnPath:(NSString *)path refNumber:(NSNumber *)ref
825 {
826 [self _openShellOnPath: path refNumber: ref];
827 }
828
829 - (oneway void)remoteShellWithRef:(NSNumber *)ref
830 newCommandLine:(NSString *)line
831 {
832 [self _remoteShellWithRef: ref newCommandLine: line];
833 }
834
835 - (oneway void)closedRemoteTerminalWithRefNumber:(NSNumber *)ref
836 {
837 [self _closedRemoteTerminalWithRefNumber: ref];
838 }
839
840 @end
841
842
843 int main(int argc, char** argv)
844 {
845 GWSd *gwsd;
846
847 switch (fork()) {
848 case -1:
849 fprintf(stderr, "gwsd - fork failed - bye.\n");
850 exit(1);
851
852 case 0:
853 setsid();
854 break;
855
856 default:
857 exit(0);
858 }
859
860 CREATE_AUTORELEASE_POOL (pool);
861 gwsd = [[GWSd alloc] initWithRemote: nil connection: nil];
862
863 RELEASE (pool);
864
865 if (gwsd != nil) {
866 CREATE_AUTORELEASE_POOL (pool);
867 [[NSRunLoop currentRunLoop] run];
868 RELEASE (pool);
869 }
870
871 exit(0);
872 }
873

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26