You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ia...@apache.org on 2013/07/23 17:47:39 UTC
[1/2] ios commit: [CB-4281] Remove Echo files from XCode project
Updated Branches:
refs/heads/master 52d42b73b -> 6ded3e8db
[CB-4281] Remove Echo files from XCode project
Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/e2e0f4a9
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/e2e0f4a9
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/e2e0f4a9
Branch: refs/heads/master
Commit: e2e0f4a94cd80515c114c931b5fd191b66620c86
Parents: 52d42b7
Author: Ian Clelland <ic...@chromium.org>
Authored: Tue Jul 23 11:44:10 2013 -0400
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Jul 23 11:47:01 2013 -0400
----------------------------------------------------------------------
CordovaLib/CordovaLib.xcodeproj/project.pbxproj | 8 --------
1 file changed, 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/e2e0f4a9/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
index 06f19de..3b13731 100644
--- a/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
+++ b/CordovaLib/CordovaLib.xcodeproj/project.pbxproj
@@ -44,8 +44,6 @@
EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */; };
EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */; settings = {ATTRIBUTES = (Public, ); }; };
EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */; };
- EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */ = {isa = PBXBuildFile; fileRef = EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */; settings = {ATTRIBUTES = (Public, ); }; };
- EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */ = {isa = PBXBuildFile; fileRef = EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */; };
EB96673B16A8970A00D86CDF /* CDVUserAgentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = EB96673916A8970900D86CDF /* CDVUserAgentUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
EB96673C16A8970A00D86CDF /* CDVUserAgentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = EB96673A16A8970900D86CDF /* CDVUserAgentUtil.m */; };
EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */ = {isa = PBXBuildFile; fileRef = EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -109,8 +107,6 @@
EB3B3546161CB44D003DBE7D /* CDVCommandQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandQueue.m; path = Classes/CDVCommandQueue.m; sourceTree = "<group>"; };
EB3B357A161F2A44003DBE7D /* CDVCommandDelegateImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVCommandDelegateImpl.h; path = Classes/CDVCommandDelegateImpl.h; sourceTree = "<group>"; };
EB3B357B161F2A45003DBE7D /* CDVCommandDelegateImpl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVCommandDelegateImpl.m; path = Classes/CDVCommandDelegateImpl.m; sourceTree = "<group>"; };
- EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVEcho.h; path = Classes/CDVEcho.h; sourceTree = "<group>"; };
- EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVEcho.m; path = Classes/CDVEcho.m; sourceTree = "<group>"; };
EB96673916A8970900D86CDF /* CDVUserAgentUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVUserAgentUtil.h; path = Classes/CDVUserAgentUtil.h; sourceTree = "<group>"; };
EB96673A16A8970900D86CDF /* CDVUserAgentUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVUserAgentUtil.m; path = Classes/CDVUserAgentUtil.m; sourceTree = "<group>"; };
EBA3557115ABD38C00F4DE24 /* NSArray+Comparisons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+Comparisons.h"; path = "Classes/NSArray+Comparisons.h"; sourceTree = "<group>"; };
@@ -214,8 +210,6 @@
30E33AF113A7E24B00594D64 /* CDVPlugin.m */,
1F92F49E1314023E0046367C /* CDVPluginResult.h */,
1F92F49F1314023E0046367C /* CDVPluginResult.m */,
- EB80C2AA15DEA63D004D9E7B /* CDVEcho.h */,
- EB80C2AB15DEA63D004D9E7B /* CDVEcho.m */,
8887FD341090FBE7009987E8 /* CDVInvokedUrlCommand.h */,
8887FD351090FBE7009987E8 /* CDVInvokedUrlCommand.m */,
3073E9EC1656D51200957977 /* CDVScreenOrientationDelegate.h */,
@@ -280,7 +274,6 @@
3034979C1513D56A0090E688 /* CDVLocalStorage.h in Headers */,
3062D120151D0EDB000D9128 /* UIDevice+Extensions.h in Headers */,
EBA3557315ABD38C00F4DE24 /* NSArray+Comparisons.h in Headers */,
- EB80C2AC15DEA63D004D9E7B /* CDVEcho.h in Headers */,
EB3B3547161CB44D003DBE7D /* CDVCommandQueue.h in Headers */,
EB3B357C161F2A45003DBE7D /* CDVCommandDelegateImpl.h in Headers */,
1B701028177A61CF00AE11F4 /* CDVShared.h in Headers */,
@@ -359,7 +352,6 @@
3034979E1513D56A0090E688 /* CDVLocalStorage.m in Sources */,
3062D122151D0EDB000D9128 /* UIDevice+Extensions.m in Sources */,
EBA3557515ABD38C00F4DE24 /* NSArray+Comparisons.m in Sources */,
- EB80C2AD15DEA63D004D9E7B /* CDVEcho.m in Sources */,
EB3B3548161CB44D003DBE7D /* CDVCommandQueue.m in Sources */,
EB3B357D161F2A45003DBE7D /* CDVCommandDelegateImpl.m in Sources */,
F858FBC7166009A8007DA594 /* CDVConfigParser.m in Sources */,
[2/2] ios commit: [CB-4095] Unify whitelist implementations
Posted by ia...@apache.org.
[CB-4095] Unify whitelist implementations
Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/6ded3e8d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/6ded3e8d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/6ded3e8d
Branch: refs/heads/master
Commit: 6ded3e8db441d9ebb5137d889b4f2849fc5b2e5d
Parents: e2e0f4a
Author: Ian Clelland <ic...@chromium.org>
Authored: Wed Jul 17 09:17:50 2013 -0400
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Jul 23 11:47:21 2013 -0400
----------------------------------------------------------------------
CordovaLib/Classes/CDVConfigParser.m | 3 +
CordovaLib/Classes/CDVWhitelist.m | 249 +++++++++++++++++-------------
2 files changed, 146 insertions(+), 106 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/6ded3e8d/CordovaLib/Classes/CDVConfigParser.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVConfigParser.m b/CordovaLib/Classes/CDVConfigParser.m
index 26f4181..7a5685d 100644
--- a/CordovaLib/Classes/CDVConfigParser.m
+++ b/CordovaLib/Classes/CDVConfigParser.m
@@ -40,6 +40,9 @@
self.pluginsDict = [[NSMutableDictionary alloc] initWithCapacity:30];
self.settings = [[NSMutableDictionary alloc] initWithCapacity:30];
self.whitelistHosts = [[NSMutableArray alloc] initWithCapacity:30];
+ [self.whitelistHosts addObject:@"file:///*"];
+ [self.whitelistHosts addObject:@"content:///*"];
+ [self.whitelistHosts addObject:@"data:///*"];
self.startupPluginNames = [[NSMutableArray alloc] initWithCapacity:8];
featureName = nil;
}
http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/6ded3e8d/CordovaLib/Classes/CDVWhitelist.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWhitelist.m b/CordovaLib/Classes/CDVWhitelist.m
index e6807bd..14bdd53 100644
--- a/CordovaLib/Classes/CDVWhitelist.m
+++ b/CordovaLib/Classes/CDVWhitelist.m
@@ -22,29 +22,95 @@
NSString* const kCDVDefaultWhitelistRejectionString = @"ERROR whitelist rejection: url='%@'";
NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
+@interface CDVWhitelistPattern : NSObject {
+ @private
+ NSRegularExpression* _scheme;
+ NSRegularExpression* _host;
+ NSNumber* _port;
+ NSRegularExpression* _path;
+}
+
++ (NSString*)regexFromPattern:(NSString*)pattern allowWildcards:(bool)allowWildcards;
+- (id)initWithScheme:(NSString*)scheme host:(NSString*)host port:(NSString*)port path:(NSString*)path;
+- (bool)matches:(NSURL*)url;
+
+@end
+
+@implementation CDVWhitelistPattern
+
++ (NSString*)regexFromPattern:(NSString*)pattern allowWildcards:(bool)allowWildcards
+{
+ NSString* regex = [NSRegularExpression escapedPatternForString:pattern];
+
+ if (allowWildcards) {
+ regex = [regex stringByReplacingOccurrencesOfString:@"\\*" withString:@".*"];
+ }
+ return [NSString stringWithFormat:@"%@$", regex];
+}
+
+- (id)initWithScheme:(NSString*)scheme host:(NSString*)host port:(NSString*)port path:(NSString*)path
+{
+ if ((scheme == nil) || [scheme isEqualToString:@"*"]) {
+ _scheme = nil;
+ } else {
+ _scheme = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:scheme allowWildcards:NO] options:0 error:nil];
+ }
+ if ([host isEqualToString:@"*"]) {
+ _host = nil;
+ } else if ([host hasPrefix:@"*."]) {
+ _host = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"([a-z0-9.-]*\\.)?%@", [CDVWhitelistPattern regexFromPattern:[host substringFromIndex:2] allowWildcards:false]] options:0 error:nil];
+ } else {
+ _host = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:host allowWildcards:NO] options:0 error:nil];
+ }
+ if ((port == nil) || [port isEqualToString:@"*"]) {
+ _port = nil;
+ } else {
+ _port = [[NSNumber alloc] initWithInteger:[port integerValue]];
+ }
+ if ((path == nil) || [path isEqualToString:@"/*"]) {
+ _path = nil;
+ } else {
+ _path = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:path allowWildcards:YES] options:0 error:nil];
+ }
+ return self;
+}
+
+- (bool)matches:(NSURL*)url
+{
+ return (_scheme == nil || [_scheme numberOfMatchesInString:[url scheme] options:NSMatchingAnchored range:NSMakeRange(0, [[url scheme] length])]) &&
+ (_host == nil || [_host numberOfMatchesInString:[url host] options:NSMatchingAnchored range:NSMakeRange(0, [[url host] length])]) &&
+ (_port == nil || [[url port] isEqualToNumber:_port]) &&
+ (_path == nil || [_path numberOfMatchesInString:[url path] options:NSMatchingAnchored range:NSMakeRange(0, [[url path] length])])
+ ;
+}
+
+@end
+
@interface CDVWhitelist ()
-@property (nonatomic, readwrite, strong) NSArray* whitelist;
-@property (nonatomic, readwrite, strong) NSDictionary* expandedWhitelists;
+@property (nonatomic, readwrite, strong) NSMutableArray* whitelist;
+@property (nonatomic, readwrite, strong) NSMutableSet* permittedSchemes;
-- (void)processWhitelist;
+- (void)addWhiteListEntry:(NSString*)pattern;
@end
@implementation CDVWhitelist
-@synthesize whitelist, expandedWhitelists, whitelistRejectionFormatString;
+@synthesize whitelist, permittedSchemes, whitelistRejectionFormatString;
- (id)initWithArray:(NSArray*)array
{
self = [super init];
if (self) {
- self.whitelist = array;
- self.expandedWhitelists = nil;
+ self.whitelist = [[NSMutableArray alloc] init];
+ self.permittedSchemes = [[NSMutableSet alloc] init];
self.whitelistRejectionFormatString = kCDVDefaultWhitelistRejectionString;
- [self processWhitelist];
- }
+ for (NSString* pattern in array) {
+ [self addWhiteListEntry:pattern];
+ }
+ }
return self;
}
@@ -82,78 +148,67 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
return YES;
}
-- (NSString*)extractHostFromUrlString:(NSString*)url
-{
- NSURL* aUrl = [NSURL URLWithString:url];
-
- if ((aUrl != nil) && ([aUrl scheme] != nil)) { // found scheme
- return [aUrl host];
- } else {
- return url;
- }
-}
-
-- (NSString*)extractSchemeFromUrlString:(NSString*)url
-{
- NSURL* aUrl = [NSURL URLWithString:url];
-
- if ((aUrl != nil) && ([aUrl scheme] != nil)) { // found scheme
- return [aUrl scheme];
- } else {
- return kCDVDefaultSchemeName;
- }
-}
-
-- (void)processWhitelist
+- (void)addWhiteListEntry:(NSString*)origin
{
if (self.whitelist == nil) {
- NSLog(@"ERROR: CDVWhitelist was not initialized properly, all urls will be disallowed.");
return;
}
- NSMutableDictionary* _expandedWhitelists = [@{kCDVDefaultSchemeName: [NSMutableArray array]} mutableCopy];
-
- // only allow known TLDs (since Aug 23rd 2011), and two character country codes
- // does not match internationalized domain names with non-ASCII characters
- NSString* tld_match = @"(aero|asia|arpa|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx|[a-z][a-z])";
-
- // iterate through settings ExternalHosts, check for equality
- for (NSString* externalHost in self.whitelist) {
- NSString* host = [self extractHostFromUrlString:externalHost];
- NSString* scheme = [self extractSchemeFromUrlString:externalHost];
-
- // check for single wildcard '*', if found set allowAll to YES
- if ([host isEqualToString:@"*"]) {
- [_expandedWhitelists setObject:[NSMutableArray arrayWithObject:host] forKey:scheme];
- continue;
+ if ([origin isEqualToString:@"*"]) {
+ NSLog(@"Unlimited access to network resources");
+ self.whitelist = nil;
+ self.permittedSchemes = nil;
+ } else { // specific access
+ NSRegularExpression* parts = [NSRegularExpression regularExpressionWithPattern:@"^((\\*|[a-z-]+)://)?(((\\*\\.)?[^*/:]+)|\\*)?(:(\\d+))?(/.*)?" options:0 error:nil];
+ NSTextCheckingResult* m = [parts firstMatchInString:origin options:NSMatchingAnchored range:NSMakeRange(0, [origin length])];
+ if (m != nil) {
+ NSRange r;
+ NSString* scheme = nil;
+ r = [m rangeAtIndex:2];
+ if (r.location != NSNotFound) {
+ scheme = [origin substringWithRange:r];
+ }
+
+ NSString* host = nil;
+ r = [m rangeAtIndex:3];
+ if (r.location != NSNotFound) {
+ host = [origin substringWithRange:r];
+ }
+
+ // Special case for two urls which are allowed to have empty hosts
+ if (([scheme isEqualToString:@"file"] || [scheme isEqualToString:@"content"]) && (host == nil)) {
+ host = @"*";
+ }
+
+ NSString* port = nil;
+ r = [m rangeAtIndex:7];
+ if (r.location != NSNotFound) {
+ port = [origin substringWithRange:r];
+ }
+
+ NSString* path = nil;
+ r = [m rangeAtIndex:8];
+ if (r.location != NSNotFound) {
+ path = [origin substringWithRange:r];
+ }
+
+ if (scheme == nil) {
+ // XXX making it stupid friendly for people who forget to include protocol/SSL
+ [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:@"http" host:host port:port path:path]];
+ [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:@"https" host:host port:port path:path]];
+ } else {
+ [self.whitelist addObject:[[CDVWhitelistPattern alloc] initWithScheme:scheme host:host port:port path:path]];
+ }
+
+ if (self.permittedSchemes != nil) {
+ if ([scheme isEqualToString:@"*"]) {
+ self.permittedSchemes = nil;
+ } else if (scheme != nil) {
+ [self.permittedSchemes addObject:scheme];
+ }
+ }
}
-
- // if this is the first value for this scheme, create a new entry
- if ([_expandedWhitelists objectForKey:scheme] == nil) {
- [_expandedWhitelists setObject:[NSMutableArray array] forKey:scheme];
- }
-
- // starts with wildcard match - we make the first '.' optional (so '*.org.apache.cordova' will match 'org.apache.cordova')
- NSString* prefix = @"*.";
- if ([host hasPrefix:prefix]) {
- // replace the first two characters '*.' with our regex
- host = [host stringByReplacingCharactersInRange:NSMakeRange(0, [prefix length]) withString:@"(\\s{0}|*.)"]; // the '*' and '.' will be substituted later
- }
-
- // ends with wildcard match for TLD
- if (![self isIPv4Address:host] && [host hasSuffix:@".*"]) {
- // replace * with tld_match
- host = [host stringByReplacingCharactersInRange:NSMakeRange([host length] - 1, 1) withString:tld_match];
- }
- // escape periods - since '.' means any character in regex
- host = [host stringByReplacingOccurrencesOfString:@"." withString:@"\\."];
- // wildcard is match 1 or more characters (to make it simple, since we are not doing verification whether the hostname is valid)
- host = [host stringByReplacingOccurrencesOfString:@"*" withString:@".*"];
-
- [[_expandedWhitelists objectForKey:scheme] addObject:host];
}
-
- self.expandedWhitelists = _expandedWhitelists;
}
- (BOOL)schemeIsAllowed:(NSString*)scheme
@@ -165,7 +220,7 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
return YES;
}
- return (self.expandedWhitelists != nil) && ([self.expandedWhitelists objectForKey:scheme] != nil);
+ return (self.permittedSchemes == nil) || [self.permittedSchemes containsObject:scheme];
}
- (BOOL)URLIsAllowed:(NSURL*)url
@@ -175,18 +230,13 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
- (BOOL)URLIsAllowed:(NSURL*)url logFailure:(BOOL)logFailure
{
- NSString* scheme = [url scheme];
-
- // http[s] and ftp[s] should also validate against the common set in the kCDVDefaultSchemeName list
- if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"] || [scheme isEqualToString:@"ftp"] || [scheme isEqualToString:@"ftps"]) {
- NSURL* newUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@", kCDVDefaultSchemeName, [url host]]];
- // If it is allowed, we are done. If not, continue to check for the actual scheme-specific list
- if ([self URLIsAllowed:newUrl logFailure:NO]) {
- return YES;
- }
+ // Shortcut acceptance: Are all urls whitelisted ("*" in whitelist)?
+ if (whitelist == nil) {
+ return YES;
}
- // Check that the scheme is supported
+ // Shortcut rejection: Check that the scheme is supported
+ NSString* scheme = [url scheme];
if (![self schemeIsAllowed:scheme]) {
if (logFailure) {
NSLog(@"%@", [self errorStringForURL:url]);
@@ -194,31 +244,18 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme";
return NO;
}
- NSArray* expandedWhitelist = [self.expandedWhitelists objectForKey:scheme];
-
- // Are we allowing everything for this scheme?
- // TODO: consider just having a static sentinel value for the "allow all" list, so we can use object equality
- if (([expandedWhitelist count] == 1) && [[expandedWhitelist objectAtIndex:0] isEqualToString:@"*"]) {
- return YES;
- }
-
- // iterate through settings ExternalHosts, check for equality
- NSEnumerator* enumerator = [expandedWhitelist objectEnumerator];
- id regex = nil;
- NSString* urlHost = [url host];
-
- // if the url host IS found in the whitelist, load it in the app (however UIWebViewNavigationTypeOther kicks it out to Safari)
- // if the url host IS NOT found in the whitelist, we do nothing
- while (regex = [enumerator nextObject]) {
- NSPredicate* regex_test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
-
- // if wildcard, break out and allow
- if ([regex isEqualToString:@"*"]) {
+ // http[s] and ftp[s] should also validate against the common set in the kCDVDefaultSchemeName list
+ if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"] || [scheme isEqualToString:@"ftp"] || [scheme isEqualToString:@"ftps"]) {
+ NSURL* newUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@%@", kCDVDefaultSchemeName, [url host], [url path]]];
+ // If it is allowed, we are done. If not, continue to check for the actual scheme-specific list
+ if ([self URLIsAllowed:newUrl logFailure:NO]) {
return YES;
}
+ }
- if ([regex_test evaluateWithObject:urlHost] == YES) {
- // if it matches at least one rule, return
+ // Check the url against patterns in the whitelist
+ for (CDVWhitelistPattern* p in self.whitelist) {
+ if ([p matches:url]) {
return YES;
}
}