macos installer pane warning fix
[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, \"abc.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