Add URL validation

This commit is contained in:
Roman Efimov
2013-09-05 11:48:36 -05:00
parent 93c3cb1f8c
commit fc9e057b23
9 changed files with 113 additions and 9 deletions

View File

@@ -936,11 +936,12 @@ BOOL REDeviceIsUIKit7() {
{
NSMutableArray *errors;
for (RETableViewSection *section in self.mutableSections) {
if (section.errors) {
NSArray *sectionErrors = section.errors;
if (sectionErrors) {
if (!errors) {
errors = [[NSMutableArray alloc] init];
}
[errors addObjectsFromArray:section.errors];
[errors addObjectsFromArray:sectionErrors];
}
}
return errors;

View File

@@ -299,12 +299,15 @@
{
NSMutableArray *errors;
for (RETableViewItem *item in self.mutableItems) {
if ([item respondsToSelector:@selector(errors)] && item.errors) {
if (!errors) {
errors = [[NSMutableArray alloc] init];
if ([item respondsToSelector:@selector(errors)]) {
NSArray *itemErrors = item.errors;
if (itemErrors) {
if (!errors) {
errors = [[NSMutableArray alloc] init];
}
if (itemErrors.count > 0)
[errors addObject:itemErrors[0]];
}
if (item.errors.count > 0)
[errors addObject:item.errors[0]];
}
}
return errors;

View File

@@ -46,6 +46,7 @@
30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */; };
30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */; };
30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D7917C667A90010D439 /* ValidationsViewController.m */; };
30B00DEE17D8E9CE0010D439 /* REURLValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00DED17D8E90D0010D439 /* REURLValidator.m */; };
30D1C7D617AC08F4001F731C /* First_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */; };
30D1C7D717AC08F4001F731C /* Last_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */; };
30D1C7D817AC08F4001F731C /* Middle_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */; };
@@ -156,6 +157,8 @@
30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REPresenceValidator.m; sourceTree = "<group>"; };
30B00D7817C667A90010D439 /* ValidationsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationsViewController.h; sourceTree = "<group>"; };
30B00D7917C667A90010D439 /* ValidationsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ValidationsViewController.m; sourceTree = "<group>"; };
30B00DEC17D8E90D0010D439 /* REURLValidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = REURLValidator.h; sourceTree = "<group>"; };
30B00DED17D8E90D0010D439 /* REURLValidator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = REURLValidator.m; sourceTree = "<group>"; };
30D1C7D217AC08F3001F731C /* First_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "First_Alt@2x.png"; path = "Resources/First_Alt@2x.png"; sourceTree = "<group>"; };
30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Last_Alt@2x.png"; path = "Resources/Last_Alt@2x.png"; sourceTree = "<group>"; };
30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Middle_Alt@2x.png"; path = "Resources/Middle_Alt@2x.png"; sourceTree = "<group>"; };
@@ -362,6 +365,8 @@
30B00D5B17C56EEF0010D439 /* RELengthValidator.m */,
30B00D5C17C56EEF0010D439 /* REPresenceValidator.h */,
30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */,
30B00DEC17D8E90D0010D439 /* REURLValidator.h */,
30B00DED17D8E90D0010D439 /* REURLValidator.m */,
);
path = Validators;
sourceTree = "<group>";
@@ -648,6 +653,7 @@
30B00D5F17C56EEF0010D439 /* REValidation.m in Sources */,
30B00D6017C56EEF0010D439 /* REValidator.m in Sources */,
30B00D6117C56EEF0010D439 /* REEmailValidator.m in Sources */,
30B00DEE17D8E9CE0010D439 /* REURLValidator.m in Sources */,
30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */,
30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */,
30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */,

View File

@@ -12,6 +12,7 @@
@property (strong, readwrite, nonatomic) RETextItem *textItem;
@property (strong, readwrite, nonatomic) RETextItem *emailItem;
@property (strong, readwrite, nonatomic) RETextItem *urlItem;
@end
@@ -43,8 +44,12 @@
self.emailItem.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.emailItem.validators = @[@"presence", @"email"];
self.urlItem = [RETextItem itemWithTitle:@"URL" value:@"http://invalid-url.co%m" placeholder:@"URL item"];
self.urlItem.validators = @[@"url"];
[section addItem:self.textItem];
[section addItem:self.emailItem];
[section addItem:self.urlItem];
}
#pragma mark -
@@ -52,9 +57,10 @@
- (void)validateButtonPressed:(UIButton *)sender
{
if (self.manager.errors.count > 0) {
NSArray *managerErrors = self.manager.errors;
if (managerErrors.count > 0) {
NSMutableArray *errors = [NSMutableArray array];
for (NSError *error in self.manager.errors) {
for (NSError *error in managerErrors) {
[errors addObject:error.localizedDescription];
}
NSString *errorString = [errors componentsJoinedByString:@"\n"];

View File

@@ -29,6 +29,7 @@
#import "REPresenceValidator.h"
#import "RELengthValidator.h"
#import "REEmailValidator.h"
#import "REURLValidator.h"
@interface REValidation : NSObject

View File

@@ -57,6 +57,7 @@
[REValidation registerValidator:[REPresenceValidator class]];
[REValidation registerValidator:[RELengthValidator class]];
[REValidation registerValidator:[REEmailValidator class]];
[REValidation registerValidator:[REURLValidator class]];
});
}
@@ -69,6 +70,7 @@
@"com.REValidation.minimumLength": @"%@ is too short (minimum is %i characters).",
@"com.REValidation.maximumLength": @"%@ is too long (maximum is %i characters).",
@"com.REValidation.email": @"%@ is not a valid email.",
@"com.REValidation.url": @"%@ is not a valid url."
};
[REValidation sharedObject].errorMessages = [NSMutableDictionary dictionaryWithDictionary:messages];
});
@@ -91,6 +93,7 @@
+ (NSError *)validateObject:(NSObject *)object name:(NSString *)name validatorString:(NSString *)string
{
NSLog(@"validate = %@, %@", name, string);
NSString *validatorStringName = [string componentsSeparatedByString:@"("][0];
for (NSString *validatorName in [REValidation sharedObject].registeredValidators) {
if ([validatorName isEqualToString:validatorStringName]) {

View File

@@ -36,6 +36,9 @@
+ (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters
{
NSString *string = object ? object : @"";
if (string.length == 0)
return nil;
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];

View File

@@ -0,0 +1,30 @@
//
// REURLValidator.h
// REValidation
//
// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "REValidator.h"
@interface REURLValidator : REValidator
@end

View File

@@ -0,0 +1,51 @@
//
// REURLValidator.m
// REValidation
//
// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "REURLValidator.h"
#import "REValidation.h"
@implementation REURLValidator
+ (NSString *)name
{
return @"url";
}
+ (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters
{
NSString *string = object ? object : @"";
if (string.length == 0)
return nil;
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(?i)(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?$" options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];
if (!match)
return [NSError re_validationErrorForDomain:@"com.REValidation.url", name];
return nil;
}
@end