Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 234 lines (187 sloc) 7.623 kb
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
1 //
2 // KSURLFormatter.m
3 //
863123f Dan Wood update copyrights
danwood authored
4 // Copyright (c) 2008-2011, Mike Abdullah and Karelia Software
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
19 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26
27
28 #import "KSURLFormatter.h"
29
30 #import "KSURLUtilities.h"
31
32
33 @implementation KSURLFormatter
34
35 #pragma mark Class Methods
36
37 + (NSURL *)URLFromString:(NSString *)string;
38 {
39 // Encode the URL string
40 CFStringEncoding encoding = CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding);
41 CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(NULL,
42 (CFStringRef)string,
43 (CFStringRef)@"%+#",
44 NULL,
45 encoding);
46
47
48 // If we're still left with a valid string, turn it into a URL
49 NSURL *result = nil;
50 if (escapedString)
51 {
63b5b9a Mike Abdullah Actually use the escaped string for creating URL, silly me
mikeabdullah authored
52 result = [NSURL URLWithString:(NSString *)escapedString];
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
53 CFRelease(escapedString);
54 }
55
56 return result;
57 }
58
83c7536 Mike Abdullah +isValidEmailAddress:
mikeabdullah authored
59 + (BOOL)isValidEmailAddress:(NSString *)address;
60 {
61 // for now, just validate that syntactically it it at least _@_.__
62 // though we are not checking actual other characters.
63 // we can refine this over time
64 NSRange whereAt = [address rangeOfString:@"@"];
65 BOOL OK = (whereAt.location != NSNotFound && whereAt.location >= 1); // make sure there is an @ and it's not the first character
66 if (OK)
67 {
68 NSInteger len = [address length] - whereAt.location;
69 NSRange whereDot = [address rangeOfString:@"." options:0 range:NSMakeRange(whereAt.location, len)];
70 OK = (whereDot.location != NSNotFound);
71 if (OK)
72 {
73 // make sure there is room between the @ and the .
74 OK = (whereDot.location - whereAt.location >= 2) && ([address length] - whereDot.location >= 3);
75 }
76 }
77 return OK;
78 }
79
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
80 #pragma mark Init & Dealloc
81
82 - (id)init
83 {
84 [super init];
85 _fallbackTopLevelDomain = [@"com" retain];
86 return self;
87 }
88
89 - (void)dealloc
90 {
91 [_fallbackTopLevelDomain release];
92 [super dealloc];
93 }
94
95 #pragma mark Managing Behaviour
96
97 @synthesize useDisplayNameForFileURLs = _useDisplayNameForFileURLs;
98 @synthesize fallbackTopLevelDomain = _fallbackTopLevelDomain;
99
100 #pragma mark Textual Representation of Cell Content
101
102 - (NSString *)stringForObjectValue:(id)anObject
103 {
387441e Mike Abdullah Be more forgiving of non-URL objects
mikeabdullah authored
104 if (!anObject) return nil;
105 if (![anObject isKindOfClass:[NSURL class]]) return [anObject description];
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
106
387441e Mike Abdullah Be more forgiving of non-URL objects
mikeabdullah authored
107
108 NSURL *URL = anObject;
109
110 NSString *result;
111 if ([self useDisplayNameForFileURLs] && [anObject isFileURL])
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
112 {
387441e Mike Abdullah Be more forgiving of non-URL objects
mikeabdullah authored
113 result = [[NSFileManager defaultManager] displayNameAtPath:[URL path]];
114 }
115 else
116 {
117 result = [URL absoluteString];
118
119 // Append trailing slash if needed
120 if ([URL ks_hasNetworkLocation] && [[URL path] isEqualToString:@""])
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
121 {
387441e Mike Abdullah Be more forgiving of non-URL objects
mikeabdullah authored
122 result = [result stringByAppendingString:@"/"];
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
123 }
124 }
125
126 return result;
127 }
128
129 #pragma mark Object Equivalent to Textual Representation
130
131 + (NSURL *)URLFromString:(NSString *)string fallbackScheme:(NSString *)fallbackScheme;
132 {
133 // Tries to interpret the string as a complete URL. If there is no scheme specified, try it as an email address. If that doesn't seem reasonable, combine with fallbackScheme
134
135
136 NSURL *result = [self URLFromString:string];
137
9de9b7d Mike Abdullah Treat hostless URLs (e.g. example.com:8888) like schemeless URLs (e.g. e...
mikeabdullah authored
138 // This is probably a really naive check
139 if ((![result scheme] && ![string hasPrefix:@"/"]) || // e.g. foo
140 (![result host])) // e.g. foo.com:8888
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
141 {
142 // if it looks like an email address, use mailto:
83c7536 Mike Abdullah +isValidEmailAddress:
mikeabdullah authored
143 if ([self isValidEmailAddress:string])
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
144 {
145 result = [NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@", string]];
146 }
147 else
148 {
149 result = [self URLFromString:[NSString stringWithFormat:
150 @"%@://%@",
151 fallbackScheme,
152 string]];
153 }
154 }
5cd1d9b Mike Abdullah Correct URLs to have a trailing slash if needed
mikeabdullah authored
155
156
157 // Append a trailing slash if needed
158 if ([result ks_hasNetworkLocation] && [[result path] isEqualToString:@""])
159 {
160 result = [[NSURL URLWithString:@"/" relativeToURL:result] absoluteURL];
161 }
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
162
163 return result;
164 }
165
166 - (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
167 {
168 BOOL result = YES;
169 NSURL *URL = nil;
170
171 if ([string length] > 0)
172 {
173 URL = [KSURLFormatter URLFromString:string fallbackScheme:@"http"];
174
175
176 // Does the URL have no useful resource specified? If so, generate nil URL
56b5693 Mike Abdullah mailto: URLs are valid
mikeabdullah authored
177 if (URL && ![[URL scheme] isEqualToString:@"mailto"])
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
178 {
179 NSString *resource = [URL resourceSpecifier];
180 if ([resource length] == 0 ||
181 [resource isEqualToString:@"/"] ||
182 [resource isEqualToString:@"//"])
183 {
184 URL = nil;
185 }
56b5693 Mike Abdullah mailto: URLs are valid
mikeabdullah authored
186
187
188
189 // URLs should also really have a host and a path
190 if (URL)
191 {
192 NSString *host = [URL host];
193 NSString *path = [URL path];
194 if (!host && !path)
195 {
196 URL = nil;
197 }
08c3984 Mike Abdullah KSURLFormatter.
mikeabdullah authored
198 }
199 }
200
201
202 // Did the user not enter a top-level domain? We'll guess for them
203 if (URL && [self fallbackTopLevelDomain])
204 {
205 if ([[URL ks_domains] count] == 1)
206 {
207 NSString *urlString = [NSString stringWithFormat:
208 @"%@://%@.%@/",
209 [URL scheme],
210 [URL host],
211 [self fallbackTopLevelDomain]];
212 URL = [NSURL URLWithString:urlString];
213 }
214 }
215 }
216
217
218 // Finish up
219 if (result && anObject) *anObject = URL;
220 return result;
221 }
222
223 - (NSURL *)URLFromString:(NSString *)string;
224 {
225 NSURL *result = nil;
226
227 NSURL *URL;
228 if ([self getObjectValue:&URL forString:string errorDescription:NULL]) result = URL;
229
230 return result;
231 }
232
233 @end
Something went wrong with that request. Please try again.