zxing/iphone/ZXingWidget/Classes/resultParsers/EmailAddressResultParser.m

131 lines
4.6 KiB
Mathematica
Raw Normal View History

//
// EmailAddressResultParser.m
// ZXing
//
// Ported to Objective-C by George Nachman on 7/29/2011
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "EmailAddressResultParser.h"
#import "EmailParsedResult.h"
#import "ArrayAndStringCategories.h"
//
// Represents a result that encodes an e-mail address, either as a plain address
// like "joe@example.org" or a mailto: URL like "mailto:joe@example.org".
// It can also take query parameters. For example:
// "mailto:joe@example.org?subject=hello&body=hello+world"
// "mailto:?to=joe%40example.org&subject=hello&body=hello+world"
//
// A query paramter of "to" will supercede the user/host portion of the URL if
// both are present.
//
// If the mailto: prefix is absent, this will recognize strings that look
// approximately like email addresses: they have an @ sign and no characters
// outlawed by RFC 2822.
//
// Originally by Sean Owen
//
@implementation EmailAddressResultParser
+ (void)load {
[ResultParser registerResultParserClass:self];
}
+ (ParsedResult *)parsedResultForString:(NSString *)rawText
format:(BarcodeFormat)format {
if (rawText == nil) {
return nil;
}
NSString *kMailto = @"mailto";
NSURL *url = [NSURL URLWithString:rawText];
if (url && [[[url scheme] lowercaseString] isEqualToString:kMailto]) {
NSDictionary *nameValues = nil;
if ([url query]) {
nameValues = [ResultParser dictionaryForQueryString:[url query]];
}
// Set the "to" value with the query parameter or as much of the
// user+host as we have.
NSString *user = [url user];
NSString *host = [url host];
NSString *emailAddress = nil;
EmailParsedResult *result =
[[[EmailParsedResult alloc] init] autorelease];
if ([nameValues objectForKey:@"to"]) {
emailAddress = [nameValues objectForKey:@"to"];
} else if (user && host) {
emailAddress = [NSString stringWithFormat:@"%@@%@", user, host];
} else if (user) {
emailAddress = user;
}
if (!emailAddress) {
return nil;
}
// Add optional fields if present.
result.to = emailAddress;
if ([nameValues objectForKey:@"subject"]) {
result.subject = [nameValues objectForKey:@"subject"];
}
if ([nameValues objectForKey:@"body"]) {
result.body = [nameValues objectForKey:@"body"];
}
return result;
} else {
// It doesn't start with mailto:, but maybe it looks like an email
// address.
if (![self isBasicallyValidEmailAddress:rawText]) {
return nil;
}
EmailParsedResult *result =
[[[EmailParsedResult alloc] init] autorelease];
result.to = rawText;
return result;
}
}
// This implements only the most basic checking for an email address's validity:
// that it contains an '@' contains no characters disallowed by RFC 2822.
// This is an overly lenient definition of validity. We want to generally be
// lenient here since this class is only intended to encapsulate what's in a
// barcode, not "judge" it.
+ (BOOL)isBasicallyValidEmailAddress:(NSString *)address {
NSRange atRange = [address rangeOfString:@"@"];
if (atRange.location == NSNotFound) {
return NO;
}
// Strip out the first at sign (exactly one is allowed).
NSString *atlessEmail =
[address stringByReplacingCharactersInRange:atRange
withString:@""];
// Set of non-alphanumeric characters allowed by rfc2822.
NSString *allowedChars = @"!#$%&'*+-/=?^_`{}|~.";
NSMutableCharacterSet *allowedSet =
[NSCharacterSet characterSetWithCharactersInString:allowedChars];
[allowedSet formUnionWithCharacterSet:
[NSCharacterSet alphanumericCharacterSet]];
NSCharacterSet *bogusSet = [allowedSet invertedSet];
if ([atlessEmail rangeOfCharacterFromSet:bogusSet].location != NSNotFound) {
return NO;
}
return YES;
}
@end