Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / platform / DARWIN / afscell / afscellPane.m
1 //
2 // afscellPane.m
3 // afscell
4 //
5 // Created by David Botsch on 10/23/07.
6 // Further developed by Toby Blake, April-May 2008
7 //
8
9 #import "afscellPane.h"
10
11 @implementation afscellPane
12
13 #pragma mark string constants
14 NSString *fileReadThisCell=@"/private/var/db/openafs/etc/ThisCell";
15 NSString *fileReadCellAlias=@"/private/var/db/openafs/etc/CellAlias";
16 NSString *fileWriteThisCell=@"/private/tmp/org.OpenAFS.Install.ThisCell";
17 NSString *fileWriteCellAlias=@"/private/tmp/org.OpenAFS.Install.CellAlias";
18
19 #pragma mark private methods
20 /* check line of CellAlias provided for Cell name, if matches, returns alias in third parameter */
21 - (BOOL)_cellInCellAliasLine:(NSString *)line cellName:(NSString *)cell intoAlias:(NSString **)alias
22 {
23 NSMutableCharacterSet *alphaNum = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
24 [alphaNum addCharactersInString:@"-"];
25
26 NSScanner *cellScanner = [NSScanner scannerWithString:line];
27 if (![cellScanner scanUpToString:cell intoString:nil])
28 {
29 [cellScanner scanString:cell intoString:nil];
30 /* need to make sure cell name is followed by whitespace */
31 if (![cellScanner scanUpToCharactersFromSet:alphaNum intoString:nil])
32 {
33 /* we have a match */
34 /* get rest of string */
35 [cellScanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:alias];
36 return YES;
37 }
38 }
39 return NO;
40 }
41
42 /* writes supplied line (plus newline) to string */
43 - (void)_appendCellAliasLine:(NSString *)line toString:(NSMutableString *)outString
44 {
45 [outString appendString:line];
46 [outString appendFormat:@"\n"];
47 }
48
49 /* writes supplied cell and alias, separated by space (plus newline at end) to string */
50 - (void)_appendNewCellAliasLine:(NSString *)cell aliasName:(NSString *)alias toString:(NSMutableString *)outString
51 {
52 [outString appendString:cell];
53 [outString appendFormat:@" "];
54 [outString appendString:alias];
55 [outString appendFormat:@"\n"];
56 }
57
58 /* displays (slightly) customisable alert */
59 /* we don't use this method any more, but I'll leave it in just in case */
60 - (BOOL) _continueAlert:(NSString *)message cancel:(BOOL)cancelButton
61 {
62 BOOL returnValue = NO;
63 NSAlert *alert = [[NSAlert alloc] init];
64 [alert addButtonWithTitle:@"OK"];
65 (cancelButton) && [alert addButtonWithTitle:@"Cancel"];
66 [alert setMessageText:message];
67 [alert setAlertStyle:NSWarningAlertStyle];
68
69 if ([alert runModal] == NSAlertFirstButtonReturn)
70 {
71 returnValue= YES;
72 }
73 [alert release];
74 return returnValue;
75 }
76
77 /* displays (slightly) customisable alert as a more attractive panel than _continueAlert above*/
78 - (BOOL) _continueAlertPanel:(NSString *)message titleText:(NSString *)title firstButtonText:(NSString *)button1 secondButtonText:(NSString *)button2
79 {
80 if (NSRunInformationalAlertPanel(title, message, button1, button2, nil)
81 == NSAlertDefaultReturn)
82 {
83 return YES;
84 }
85 return NO;
86 }
87
88 - (BOOL) _validateStringWord:(NSString *)aString
89 {
90 /* basic string validation to check it's got something in it, doesn't have whitespace or newline */
91 if (aString == nil || [aString length] == 0)
92 {
93 return NO;
94 }
95
96 if (([aString rangeOfString:@"\n"].location != NSNotFound) ||
97 ([aString rangeOfString:@"\t"].location != NSNotFound) ||
98 ([aString rangeOfString:@" "].location != NSNotFound))
99 {
100 return NO;
101 }
102 return YES;
103 }
104
105 - (BOOL) _validateCellString:(NSString *)cellString
106 {
107 if (![self _validateStringWord:cellString])
108 {
109 return NO;
110 }
111
112 /* make sure it's in internet domain style, i.e. alphanum.alphanum */
113 NSMutableCharacterSet *alphaNum = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
114 [alphaNum addCharactersInString:@"-"];
115 NSScanner *cellScanner = [NSScanner scannerWithString:cellString];
116
117 /* first 'word' */
118 if (![cellScanner scanCharactersFromSet:alphaNum intoString:nil])
119 {
120 return NO;
121 }
122
123 /* anything that follows must be iteration of '.word' */
124 while (![cellScanner isAtEnd])
125 {
126 if (![cellScanner scanString:@"." intoString:nil])
127 {
128 return NO;
129 }
130 if (![cellScanner scanCharactersFromSet:alphaNum intoString:nil])
131 {
132 return NO;
133 }
134 }
135
136 return YES;
137 }
138
139 - (BOOL) _validateAliasString:(NSString *)aliasString
140 {
141 if (![self _validateStringWord:aliasString])
142 {
143 return NO;
144 }
145
146 /* make sure it's alpha-numeric */
147 NSMutableCharacterSet *alphaNum = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
148 [alphaNum addCharactersInString:@"-"];
149 NSScanner *aliasScanner = [NSScanner scannerWithString:aliasString];
150
151 if (![aliasScanner scanCharactersFromSet:alphaNum intoString:nil])
152 {
153 return NO;
154 }
155 /* if there's nothing but alpha-numeric, we should be at end */
156 if (![aliasScanner isAtEnd])
157 {
158 return NO;
159 }
160
161 return YES;
162 }
163
164 #pragma mark InstallerPane overrides
165 - (NSString *)title
166 {
167 return [[NSBundle bundleForClass:[self class]] localizedStringForKey:@"PaneTitle" value:nil table:nil];
168 }
169
170
171 /* called when user enters pane */
172 - (void)didEnterPane:(InstallerSectionDirection)dir
173 {
174 /* get any existing values from ThisCell and CellAlias files */
175 NSString *readStrCellFile = [NSString stringWithContentsOfFile:fileReadThisCell encoding:NSASCIIStringEncoding error:nil];
176 NSString *readStrAliasFile = [NSString stringWithContentsOfFile:fileReadCellAlias encoding:NSASCIIStringEncoding error:nil];
177
178 /* drop out now if no ThisCell */
179 if (readStrCellFile == nil)
180 {
181 return;
182 }
183
184 NSString *cellString = @"";
185 NSString *aliasString = @"";
186
187 /* we only want the first line from ThisCell */
188 NSScanner *cellFileScanner = [NSScanner scannerWithString:readStrCellFile];
189
190 /* get value, removing any trailing whitespace */
191 [cellFileScanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:&cellString];
192
193 /* set Cell value in pane */
194 [ThisCell setStringValue:cellString];
195
196 /* drop out now if no CellAlias file */
197 if (readStrAliasFile == nil)
198 {
199 return;
200 }
201
202 /* now find our local cell in the alias file */
203 NSScanner *lineScanner = [NSScanner scannerWithString:readStrAliasFile];
204 NSString *line;
205
206 /* get a line at a time, and check for Cell name */
207 while([lineScanner scanUpToString:@"\n" intoString:&line])
208 {
209 [self _cellInCellAliasLine:line cellName:cellString intoAlias:&aliasString];
210 [lineScanner scanString:@"\n" intoString:nil];
211 }
212
213 /* set Alias value in pane */
214 [CellAlias setStringValue:aliasString];
215
216 return;
217 }
218
219 /* called when user clicks "Continue" -- return value indicates if application should exit pane */
220 - (BOOL)shouldExitPane:(InstallerSectionDirection)dir
221 {
222 if(InstallerDirectionForward == dir)
223 {
224 NSString * userName = NSUserName();
225
226 /* Update ThisCell and CellAlias files with input */
227 NSString * newStrCell = [ThisCell stringValue];
228 NSString * newStrAlias = [CellAlias stringValue];
229
230 if ([newStrCell length] == 0)
231 {
232 return [self _continueAlertPanel:@"No local cell value specified. Proceed with empty value?" titleText:@"No Local Cell" firstButtonText:@"Continue" secondButtonText:@"Cancel"];
233 }
234
235 /* do some validation on cell string */
236 if (![self _validateCellString:newStrCell])
237 {
238 [self _continueAlertPanel:@"Invalid local cell name: value should be a complete Internet domain-style name (for example, \"example.com\")" titleText:@"Invalid Cell Name" firstButtonText:@"OK" secondButtonText:nil];
239 return NO;
240 }
241
242 /* write value to ThisCell file */
243
244 /* add username to file name */
245 NSMutableString * fileWriteThisCellUname = [NSMutableString stringWithCapacity:0];
246 [fileWriteThisCellUname appendString:fileWriteThisCell];
247 [fileWriteThisCellUname appendFormat:@"."];
248 [fileWriteThisCellUname appendString:userName];
249
250 NSMutableString * errorString = [NSMutableString stringWithCapacity:0];
251
252 NSMutableString * cellString = [NSMutableString stringWithCapacity:0];
253 [cellString appendString:newStrCell];
254 [cellString appendFormat:@"\n"];
255 if (![cellString writeToFile:fileWriteThisCellUname atomically:YES encoding:NSASCIIStringEncoding error:nil])
256 {
257 [errorString setString:@"Could not write file: "];
258 [errorString appendString:fileWriteThisCellUname];
259 [errorString appendFormat:@" Continue?"];
260 if (![self _continueAlertPanel:errorString titleText:@"File Error" firstButtonText:@"Continue" secondButtonText:@"Cancel"])
261 {
262 return NO;
263 }
264 }
265
266 if ([newStrAlias length] != 0)
267 {
268 /* do some validation on alias string */
269 if (![self _validateAliasString:newStrAlias])
270 {
271 [self _continueAlertPanel:@"Invalid alias: value should be alpha-numeric string" titleText:@"Invalid Alias" firstButtonText:@"OK" secondButtonText:nil];
272 return NO;
273 }
274
275 BOOL processedAlias = NO;
276
277 /* read in alias file */
278 NSString *readStrAliasFile = [NSString stringWithContentsOfFile:fileReadCellAlias encoding:NSASCIIStringEncoding error:nil];
279
280 /* string to build up for writing out to file */
281 NSMutableString * aliasString = [NSMutableString stringWithCapacity:0];
282
283 if (readStrAliasFile != nil)
284 {
285 /* read in a line at a time */
286 NSScanner *lineScanner = [NSScanner scannerWithString:readStrAliasFile];
287 NSString *line;
288 NSString *alias = @"";
289
290 while([lineScanner scanUpToString:@"\n" intoString:&line])
291 {
292 /* check to see if we already have an alias for local cell */
293 if ([self _cellInCellAliasLine:line cellName:newStrCell intoAlias:&alias])
294 {
295 /* we have a match */
296 if ([alias isEqualToString:newStrAlias])
297 {
298 /* write line as-is */
299 [self _appendCellAliasLine:line toString:aliasString];
300 }
301 else
302 {
303 /* write new cell-alias entry in place */
304 [self _appendNewCellAliasLine:newStrCell aliasName:newStrAlias toString:aliasString];
305 }
306 processedAlias = YES;
307 }
308 else
309 {
310 /* write line as-is */
311 [self _appendCellAliasLine:line toString:aliasString];
312 }
313 [lineScanner scanString:@"\n" intoString:nil];
314 }
315 }
316 if (!processedAlias)
317 {
318 /* if we haven't written our line yet, append to end */
319 [self _appendNewCellAliasLine:newStrCell aliasName:newStrAlias toString:aliasString];
320 }
321
322 /* add username to file name */
323 NSMutableString * fileWriteCellAliasUname = [NSMutableString stringWithCapacity:0];
324 [fileWriteCellAliasUname appendString:fileWriteCellAlias];
325 [fileWriteCellAliasUname appendFormat:@"."];
326 [fileWriteCellAliasUname appendString:userName];
327
328 if (![aliasString writeToFile:fileWriteCellAliasUname atomically:YES encoding:NSASCIIStringEncoding error:nil])
329 {
330 [errorString setString:@"Could not write file: "];
331 [errorString appendString:fileWriteCellAliasUname];
332 [errorString appendFormat:@" Continue?"];
333 if (![self _continueAlertPanel:errorString titleText:@"File Error" firstButtonText:@"Continue" secondButtonText:@"Cancel"])
334
335 {
336 return NO;
337 }
338 }
339 }
340 }
341 return YES;
342 }
343
344 @end
345