Developer Area

root/apps/iphone/superbook/trunk/DotTel_SDK/Classes/TelDomain.m @ 720

Revision 720, 10.9 kB (checked in by henri, 4 years ago)

Refactored .tel data into a new class

Line 
1//
2//  TelDomain.m
3//  DotTel SDK
4//
5//  Created by Henri Asseily on 3/17/10.
6//  Copyright 2010 Telnic Limited. All rights reserved.
7/*
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10 
11 Redistributions of source code must retain the above copyright notice, this list of conditions
12 and the following disclaimer. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the documentation and/or other
14 materials provided with the distribution.
15 Neither the name of the Telnic Ltd. nor the names of its contributors may be used to endorse or
16 promote products derived from this software without specific prior written permission.
17 THIS DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
18 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26//
27
28#import "TelDomain.h"
29
30@implementation TelDomain
31
32@synthesize telName = _telName;
33@synthesize cleanTelName = _cleanTelName;
34@synthesize displayName;
35@synthesize headerText;
36@synthesize logoUrl = _logoUrl;
37@synthesize naptrArray;
38@synthesize txtArray;
39@synthesize allTxtArray;
40@synthesize locArray;
41@synthesize country;
42@synthesize timeZone;
43@synthesize geoLocDidFinish;
44@synthesize delegate;
45
46#pragma mark -
47#pragma mark Initializers
48
49// Don't allow init
50- (id)init {
51        return nil;
52}
53
54// Canonical initializer
55- (id)initWithTelName:(NSString *)aTelName delegate:(id<TelDomainDelegate>)aDelegate {
56        if ((aTelName == nil) || (aDelegate == nil))
57                return nil;
58        self = [super init];
59        self.delegate = aDelegate;
60        _telName = [[self telFromQueryString:aTelName] retain];
61        _cleanTelName = [[_telName stringByReplacingOccurrencesOfString:@"-"
62                                                                                                         withString:@" "
63                                                                                                                options:NSLiteralSearch
64                                                                                                                  range:NSMakeRange(0, [_telName length])] retain];
65        self.displayName = _cleanTelName;
66        _logoUrl = nil;
67        geoLocDidFinish = NO;
68        self.naptrArray = [NSMutableArray arrayWithCapacity:10];
69        self.txtArray = [NSMutableArray arrayWithCapacity:10];
70        self.allTxtArray = [NSMutableArray arrayWithCapacity:20];
71        self.locArray = [NSMutableArray arrayWithCapacity:1];   
72        return self;
73}
74
75- (void)dealloc {
76        [_telName release];
77        [_cleanTelName release];
78        if (_logoUrl)
79                [_logoUrl release];
80        [super dealloc];
81}
82
83#pragma mark -
84#pragma mark Data Methods
85
86- (NSError *)getNaptr {
87        NSError *error = nil;
88        [[NetworkUtility sharedInstance] networkwillActivate:YES];
89        DnsResolver *res = [[DnsResolver alloc] init];
90        NSUInteger naptrCount = [res getNAPTRForTel:self.telName inArray:self.naptrArray withError:&error];
91        [res release];
92        if (naptrCount == 0) {
93#ifdef DEBUG
94                NSLog(@"Warning: Error or No NAPTR records in domain %@", telName);
95#endif
96        }
97        // extract the logo (take the first one and leave the others as links)
98        RecordNaptr *theRec;
99        for (int i = 0; i < [naptrArray count]; i++) {
100                theRec = [naptrArray objectAtIndex:i];
101                if (([theRec.serviceTypeArray count] > 0) && [[theRec.serviceTypeArray objectAtIndex:0] hasPrefix:@"x-photo:http"]) {
102                        if (theRec.uriContent)
103                                _logoUrl = [[NSURL URLWithString:theRec.uriContent] retain];
104                        [naptrArray removeObjectAtIndex:i];
105                        break;
106                }
107        }
108        [[NetworkUtility sharedInstance] networkwillActivate:NO];
109        if ([self.delegate respondsToSelector:@selector(didFinishGettingNaptrWithError:)]) {
110                [self.delegate didFinishGettingNaptrWithError:error];
111        }
112        return error;
113}
114
115- (NSError *)getTxt {
116        NSError *error = nil;
117        [[NetworkUtility sharedInstance] networkwillActivate:YES];
118        DnsResolver *res = [[DnsResolver alloc] init];
119        NSUInteger txtCount = [res getTXTForTel:self.telName inArray:allTxtArray withError:&error];
120        if (txtCount == 0) {
121#ifdef DEBUG
122                NSLog(@"Warning: Error or No TXT records in domain %@", telName);
123#endif
124        }
125        [[NetworkUtility sharedInstance] networkwillActivate:NO];
126        [res release];
127        // Now build out the keywords txtArray and extract the header, display string and other stuff
128        RecordTxt *theRec;
129        NSMutableString *_headerText = nil;
130        for (theRec in allTxtArray) {
131                if (theRec.subType == RecordTxtSubTypeKeyword) {
132                        // It's a keyword, let's add it to the array in the txt section
133                        [self.txtArray addObject:theRec];
134                } else if (theRec.subType == RecordTxtSubTypeString) {
135                        // simple string, currently a header
136                        // Merge all simple strings into a header
137                        if (!_headerText) {
138                                _headerText = [NSMutableString stringWithString:theRec.textValue];
139                        } else {
140                                //NSLog(theRec.textValue);
141                                [_headerText appendFormat:@"\n%@", theRec.textValue];
142                        }
143                } else if (theRec.subType == RecordTxtSubTypeDDS) {
144                        // domain display string
145                        self.displayName = theRec.textValue;
146                } else {
147                        // do nothing with the other records such as ads, just discard them
148                }
149        }
150        if (_headerText)
151                self.headerText = _headerText;
152        else
153                self.headerText = self.displayName;
154        if ([self.delegate respondsToSelector:@selector(didFinishGettingTxtWithError:)]) {
155                [self.delegate didFinishGettingTxtWithError:error];
156        }
157        return error;
158}
159
160- (NSError *)getLocWithReverseGeo:(BOOL)revGeo {
161        NSError *error = nil;
162        [[NetworkUtility sharedInstance] networkwillActivate:YES];
163        DnsResolver *res = [[DnsResolver alloc] init];
164        geoLocDidFinish = NO;
165        NSUInteger locCount = [res getLOCForTel:self.telName inArray:self.locArray withError:&error];
166        [res release];
167        [[NetworkUtility sharedInstance] networkwillActivate:NO];
168        if (locCount > 1) {
169                //NSLog(@"Warning: %d LOC records in domain %@", locCount, telName);
170        }
171        if (locCount > 0) {
172                if (revGeo) {
173                        // and now look up the timezone and other goodies that take a while because they use the web
174                        [[NetworkUtility sharedInstance] networkwillActivate:YES];
175                        [self getCountryAndTimeZoneForLoc:(RecordLoc *)[self.locArray objectAtIndex:0]];
176                        [[NetworkUtility sharedInstance] networkwillActivate:NO];
177                }
178        }
179        if ([self.delegate respondsToSelector:@selector(didFinishGettingLocWithError:)]) {
180                [self.delegate didFinishGettingLocWithError:error];
181        }
182        return error;
183}
184
185- (void)getNaptrAndTxtInBackground {
186        if ([NSThread isMainThread]) {
187                [self performSelectorInBackground:_cmd withObject:nil];
188                return;
189        }
190        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
191        NSError *errorTxt = [self getTxt];
192        NSError *errorNaptr = [self getNaptr];
193        // merge the txt labels into the naptrs
194        DnsResolver *res = [[DnsResolver alloc] init];
195        [res updateNaptrArray:self.naptrArray withTxtArray:self.allTxtArray];
196        [res release];
197        if ([self.delegate respondsToSelector:@selector(didFinishGettingNaptrAndTxtWithError:)]) {
198                if (errorNaptr != nil) {
199                        [self.delegate didFinishGettingNaptrAndTxtWithError:errorNaptr];
200                } else {
201                        [self.delegate didFinishGettingNaptrAndTxtWithError:errorTxt];
202                }
203        }
204        [pool release];
205}
206
207- (void)getLocAndReverseGeoInBackground{
208        if ([NSThread isMainThread]) {
209                [self performSelectorInBackground:_cmd withObject:nil];
210                return;
211        }
212        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
213        [self getLocWithReverseGeo:YES];
214        [pool release];
215}
216
217- (void)getLocInBackground{
218        if ([NSThread isMainThread]) {
219                [self performSelectorInBackground:_cmd withObject:nil];
220                return;
221        }
222        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
223        [self getLocWithReverseGeo:NO];
224        [pool release];
225}
226
227- (void)getCountryAndTimeZoneForLoc:(CLLocation *)aLoc {
228        // Get country and timezone
229        // Don't get current time because the url may be cached. Use the timezone to regenerate the current time
230        NSString *uS = [NSString stringWithFormat:@"http://ws.geonames.org/timezone?lat=%f&lng=%f",
231                                        aLoc.coordinate.latitude, aLoc.coordinate.longitude];
232        NSURL *url = [NSURL URLWithString:uS];
233        NSURLRequest *urlReq = [NSURLRequest requestWithURL:url
234                                                                                        cachePolicy:NSURLRequestReturnCacheDataElseLoad
235                                                                                timeoutInterval:60.0];
236        NSHTTPURLResponse *response = [[[NSHTTPURLResponse alloc]
237                                                                        initWithURL:url
238                                                                        MIMEType:@"text/xml"
239                                                                        expectedContentLength:1024
240                                                                        textEncodingName:nil] autorelease];
241        NSError *error;
242        NSData *tzData = [NSURLConnection sendSynchronousRequest:urlReq
243                                                                                   returningResponse:&response
244                                                                                                           error:&error];
245        if (tzData) {
246                // Got data
247                NSString *sData = [[NSString alloc] initWithData:tzData encoding:NSUTF8StringEncoding];
248                // Now get country
249                NSRange rC1 = [sData rangeOfString:@"<countryName>"];
250                if (rC1.location != NSNotFound) {
251                        NSRange rC2 = [sData rangeOfString:@"</countryName>"];
252                        if (rC2.location != NSNotFound) {
253                                NSRange rC = NSMakeRange(rC1.location+rC1.length, rC2.location - (rC1.location+rC1.length));
254                                self.country = [sData substringWithRange:rC];
255                        }
256                }
257                // And get timezone
258                NSRange rTZ1 = [sData rangeOfString:@"<timezoneId>"];
259                if (rTZ1.location != NSNotFound) {
260                        NSRange rTZ2 = [sData rangeOfString:@"</timezoneId>"];
261                        if (rTZ2.location != NSNotFound) {
262                                NSRange rTZ = NSMakeRange(rTZ1.location+rTZ1.length, rTZ2.location - (rTZ1.location+rTZ1.length));
263                                self.timeZone = [NSTimeZone timeZoneWithName:[sData substringWithRange:rTZ]];
264                        }
265                }
266                [sData release];
267        }
268        geoLocDidFinish = YES;
269}
270
271
272#pragma mark -
273#pragma mark Utility Methods
274
275- (NSString *)telFromQueryString:(NSString *)query {
276        if (!query)
277                return nil;
278        NSMutableString *qry = [NSMutableString stringWithString:query];
279        if ([qry length] == 0)
280                return nil;
281        if ([qry hasPrefix:@"http://"]) {
282                [qry deleteCharactersInRange:NSMakeRange(0, [@"http://" length])];
283        } else if ([qry hasPrefix:@"https://"]) {
284                [qry deleteCharactersInRange:NSMakeRange(0, [@"https://" length])];
285        }
286        if ([qry hasPrefix:@"www."]) {
287                [qry deleteCharactersInRange:NSMakeRange(0, [@"www." length])];
288        }
289        if ([qry hasPrefix:@"+"]) {
290                // Check if it's a phone number, try the sip version
291                BOOL isValidNumber = YES;
292                NSMutableString *enumStr = [NSMutableString stringWithCapacity:30];
293                NSRange prefixR = NSMakeRange(0, 0);
294                for (int i = 1; i < [qry length]; i++) {
295                        unichar aChar = [qry characterAtIndex:i];
296                        if ((aChar < 47) || (aChar > 58)) {     // Not in range of Unicode digits 0-9
297                                isValidNumber = NO;
298                                break;
299                        }
300                        [enumStr replaceCharactersInRange:prefixR withString:[NSString stringWithFormat:@"%c.", aChar]];
301                }
302                if (isValidNumber) {
303                        [enumStr appendString:@"e164.arpa"];
304                        qry = enumStr;
305                }
306        } else if ([qry hasSuffix:@".tel"]) {
307                // .tel domain, do nothing
308        } else if ([qry hasSuffix:@".e164.arpa"]) {
309                // ENUM domain, let's add support for it, why not!
310                // Superbook will be the best ENUM client too! :)
311        } else {
312                qry = [NSString stringWithFormat:@"%@.tel", qry];
313        }
314        return qry;
315}
316
317@end
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us