Error shows document URI
This commit is contained in:
@@ -35,7 +35,7 @@
|
||||
+ (BOOL)isFeedParser { return YES; }
|
||||
|
||||
- (BOOL)xmlParserWillStartParsing {
|
||||
_parsedFeed = [[RSParsedFeed alloc] initWithURLString:self.documentURI];
|
||||
_parsedFeed = [[RSParsedFeed alloc] initWithURL:self.documentURI];
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#import "NSDictionary+RSXML.h"
|
||||
|
||||
@interface RSHTMLLinkParser()
|
||||
@property (nonatomic, readonly) NSURL *baseURL;
|
||||
@property (nonatomic) NSMutableArray<RSHTMLMetadataAnchor*> *mutableLinksList;
|
||||
@property (nonatomic) NSMutableString *currentText;
|
||||
@end
|
||||
@@ -41,7 +40,6 @@
|
||||
+ (BOOL)isHTMLParser { return YES; }
|
||||
|
||||
- (BOOL)xmlParserWillStartParsing {
|
||||
_baseURL = [NSURL URLWithString:self.documentURI];
|
||||
_mutableLinksList = [NSMutableArray new];
|
||||
return YES;
|
||||
}
|
||||
@@ -69,7 +67,7 @@
|
||||
[self.mutableLinksList addObject:obj];
|
||||
// set link properties
|
||||
obj.tooltip = [attribs rsxml_objectForCaseInsensitiveKey:@"title"];
|
||||
obj.link = [[NSURL URLWithString:href relativeToURL:self.baseURL] absoluteString];
|
||||
obj.link = [[NSURL URLWithString:href relativeToURL:self.documentURI] absoluteString];
|
||||
// begin storing data for link description
|
||||
[SAXParser beginStoringCharacters];
|
||||
self.currentText = [NSMutableString new];
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#import "NSDictionary+RSXML.h"
|
||||
|
||||
@interface RSHTMLMetadataParser()
|
||||
@property (nonatomic, readonly) NSURL *baseURL;
|
||||
@property (nonatomic) NSString *faviconLink;
|
||||
@property (nonatomic) NSMutableArray<RSHTMLMetadataIconLink*> *iconLinks;
|
||||
@property (nonatomic) NSMutableArray<RSHTMLMetadataFeedLink*> *feedLinks;
|
||||
@@ -43,7 +42,6 @@
|
||||
+ (BOOL)isHTMLParser { return YES; }
|
||||
|
||||
- (BOOL)xmlParserWillStartParsing {
|
||||
_baseURL = [NSURL URLWithString:self.documentURI];
|
||||
_iconLinks = [NSMutableArray new];
|
||||
_feedLinks = [NSMutableArray new];
|
||||
return YES;
|
||||
@@ -90,11 +88,11 @@
|
||||
rel = [rel lowercaseString];
|
||||
|
||||
if ([rel isEqualToString:@"shortcut icon"]) {
|
||||
self.faviconLink = [link absoluteURLWithBase:self.baseURL];
|
||||
self.faviconLink = [link absoluteURLWithBase:self.documentURI];
|
||||
}
|
||||
else if ([rel isEqualToString:@"icon"] || [rel hasPrefix:@"apple-touch-icon"]) { // also matching "apple-touch-icon-precomposed"
|
||||
RSHTMLMetadataIconLink *icon = [RSHTMLMetadataIconLink new];
|
||||
icon.link = [link absoluteURLWithBase:self.baseURL];
|
||||
icon.link = [link absoluteURLWithBase:self.documentURI];
|
||||
icon.title = rel;
|
||||
icon.sizes = [attribs rsxml_objectForCaseInsensitiveKey:@"sizes"];
|
||||
[self.iconLinks addObject:icon];
|
||||
@@ -103,7 +101,7 @@
|
||||
RSFeedType type = RSFeedTypeFromLinkTypeAttribute([attribs rsxml_objectForCaseInsensitiveKey:@"type"]);
|
||||
if (type != RSFeedTypeNone) {
|
||||
RSHTMLMetadataFeedLink *feedLink = [RSHTMLMetadataFeedLink new];
|
||||
feedLink.link = [link absoluteURLWithBase:self.baseURL];
|
||||
feedLink.link = [link absoluteURLWithBase:self.documentURI];
|
||||
feedLink.title = [attribs rsxml_objectForCaseInsensitiveKey:@"title"];
|
||||
feedLink.type = type;
|
||||
[self.feedLinks addObject:feedLink];
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
@interface RSParsedArticle : NSObject
|
||||
|
||||
- (nonnull instancetype)initWithFeedURL:(NSString * _Nonnull)feedURL dateParsed:(NSDate*)parsed;
|
||||
- (nonnull instancetype)initWithFeedURL:(NSURL * _Nonnull)feedURL dateParsed:(NSDate*)parsed;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSString *feedURL;
|
||||
@property (nonatomic, readonly, nonnull) NSURL *feedURL;
|
||||
@property (nonatomic, readonly, nonnull) NSDate *dateParsed;
|
||||
@property (nonatomic, readonly, nonnull) NSString *articleID; //Calculated. Don't get until other properties have been set.
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
@implementation RSParsedArticle
|
||||
|
||||
- (instancetype)initWithFeedURL:(NSString *)feedURL dateParsed:(NSDate*)parsed {
|
||||
- (instancetype)initWithFeedURL:(NSURL *)feedURL dateParsed:(NSDate*)parsed {
|
||||
|
||||
NSParameterAssert(feedURL != nil);
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
- (NSString *)calculatedUniqueID {
|
||||
|
||||
NSAssert(self.feedURL != nil, @"Feed URL should always be set!");
|
||||
NSMutableString *s = [NSMutableString stringWithString:self.feedURL];
|
||||
NSMutableString *s = [NSMutableString stringWithFormat:@"%@", self.feedURL];
|
||||
|
||||
if (self.guid.length > 0) {
|
||||
[s appendString:self.guid];
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
@class RSParsedArticle;
|
||||
|
||||
@interface RSParsedFeed : NSObject
|
||||
@property (nonatomic, readonly, nonnull) NSString *urlString;
|
||||
@property (nonatomic, readonly, nonnull) NSURL *url;
|
||||
@property (nonatomic, readonly, nonnull) NSDate *dateParsed;
|
||||
@property (nonatomic, readonly, nonnull) NSArray <RSParsedArticle *> *articles;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
@property (nonatomic, nullable) NSString *link;
|
||||
@property (nonatomic, nullable) NSString *subtitle;
|
||||
|
||||
- (nonnull instancetype)initWithURLString:(NSString * _Nonnull)urlString;
|
||||
- (nonnull instancetype)initWithURL:(NSURL * _Nonnull)url;
|
||||
- (RSParsedArticle *)appendNewArticle;
|
||||
|
||||
@end
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
|
||||
@implementation RSParsedFeed
|
||||
|
||||
- (instancetype)initWithURLString:(NSString *)urlString {
|
||||
- (instancetype)initWithURL:(NSURL *)url {
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_urlString = urlString;
|
||||
_url = url;
|
||||
_mutableArticles = [NSMutableArray new];
|
||||
_dateParsed = [NSDate date];
|
||||
}
|
||||
@@ -50,7 +50,7 @@
|
||||
Append new @c RSParsedArticle object to @c .articles and return newly inserted instance.
|
||||
*/
|
||||
- (RSParsedArticle *)appendNewArticle {
|
||||
RSParsedArticle *article = [[RSParsedArticle alloc] initWithFeedURL:self.urlString dateParsed:_dateParsed];
|
||||
RSParsedArticle *article = [[RSParsedArticle alloc] initWithFeedURL:self.url dateParsed:_dateParsed];
|
||||
[_mutableArticles addObject:article];
|
||||
return article;
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@
|
||||
@class RSXMLParser;
|
||||
|
||||
@interface RSXMLData <__covariant T : RSXMLParser *> : NSObject
|
||||
@property (nonatomic, readonly, nonnull) NSString *urlString;
|
||||
@property (nonatomic, readonly, nonnull) NSURL *url;
|
||||
@property (nonatomic, readonly, nullable) NSData *data;
|
||||
@property (nonatomic, readonly, nullable) Class parserClass;
|
||||
@property (nonatomic, readonly, nullable) NSError *parserError;
|
||||
|
||||
- (instancetype)initWithData:(NSData * _Nonnull)data urlString:(NSString * _Nonnull)urlString;
|
||||
- (instancetype)initWithData:(NSData * _Nonnull)data url:(NSURL * _Nonnull)url;
|
||||
|
||||
- (T _Nullable)getParser;
|
||||
- (BOOL)canParseData;
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
static const NSUInteger minNumberOfBytesToSearch = 20;
|
||||
static const NSUInteger numberOfCharactersToSearch = 4096;
|
||||
|
||||
- (instancetype)initWithData:(NSData *)data urlString:(NSString *)urlString {
|
||||
- (instancetype)initWithData:(NSData *)data url:(NSURL *)url {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_data = data;
|
||||
_urlString = urlString;
|
||||
_url = url;
|
||||
_parserError = nil;
|
||||
_parserClass = [self determineParserClass]; // will set error
|
||||
if (!_parserClass && _parserError)
|
||||
@@ -112,11 +112,11 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
|
||||
// TODO: check for things like images and movies and return nil.
|
||||
if (!_data || _data.length < minNumberOfBytesToSearch) {
|
||||
// TODO: check size, type, etc.
|
||||
_parserError = RSXMLMakeError(RSXMLErrorNoData);
|
||||
_parserError = RSXMLMakeError(RSXMLErrorNoData, _url);
|
||||
return nil;
|
||||
}
|
||||
if (NSNotFound == [self findCString:"<"]) {
|
||||
_parserError = RSXMLMakeError(RSXMLErrorMissingLeftCaret);
|
||||
_parserError = RSXMLMakeError(RSXMLErrorMissingLeftCaret, _url);
|
||||
return nil;
|
||||
}
|
||||
if ([self matchAll:(const char*[]){"<rss", "<channel"} count:2]) { // RSS
|
||||
@@ -136,7 +136,7 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
|
||||
return [RSHTMLMetadataParser class];
|
||||
}
|
||||
if ([self findCString:"<errors xmlns='http://schemas.google"] != NSNotFound) {
|
||||
_parserError = RSXMLMakeError(RSXMLErrorContainsXMLErrorsTag);
|
||||
_parserError = RSXMLMakeError(RSXMLErrorContainsXMLErrorsTag, _url);
|
||||
return nil;
|
||||
}
|
||||
// else: try slower NSString conversion and search case insensitive.
|
||||
@@ -154,7 +154,7 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
|
||||
s = [[NSString alloc] initWithBytesNoCopy:(void *)_data.bytes length:_data.length encoding:NSUnicodeStringEncoding freeWhenDone:NO];
|
||||
}
|
||||
if (!s) {
|
||||
_parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser);
|
||||
_parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser, _url);
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ static const NSUInteger numberOfCharactersToSearch = 4096;
|
||||
}
|
||||
}
|
||||
// Try RSS anyway? libxml would return a parsing error
|
||||
_parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser);
|
||||
_parserError = RSXMLMakeError(RSXMLErrorNoSuitableParser, _url);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,5 +41,5 @@ typedef NS_ERROR_ENUM(kRSXMLParserErrorDomain, RSXMLError) {
|
||||
RSXMLErrorExpectingOPML = 230
|
||||
};
|
||||
|
||||
NSError * RSXMLMakeError(RSXMLError code);
|
||||
NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other);
|
||||
NSError * RSXMLMakeError(RSXMLError code, NSURL *uri);
|
||||
NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other, NSURL *uri);
|
||||
|
||||
@@ -56,11 +56,16 @@ NSString * getErrorMessageForRSXMLError(RSXMLError code, RSXMLError other) {
|
||||
}
|
||||
}
|
||||
|
||||
NSError * RSXMLMakeError(RSXMLError code) {
|
||||
return RSXMLMakeErrorWrongParser(code, RSXMLErrorNoData);
|
||||
NSError * RSXMLMakeError(RSXMLError code, NSURL *uri) {
|
||||
return RSXMLMakeErrorWrongParser(code, RSXMLErrorNoData, uri);
|
||||
}
|
||||
|
||||
NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other) {
|
||||
NSError * RSXMLMakeErrorWrongParser(RSXMLError expected, RSXMLError other, NSURL *uri) {
|
||||
NSString *documentURI = @"";
|
||||
if (uri) {
|
||||
documentURI = (uri.isFileURL ? [[uri filePathURL] path] : [uri absoluteString]);
|
||||
}
|
||||
return [NSError errorWithDomain:kRSXMLParserErrorDomain code:expected
|
||||
userInfo:@{NSLocalizedDescriptionKey: getErrorMessageForRSXMLError(expected, other)}];
|
||||
userInfo:@{ NSLocalizedDescriptionKey: getErrorMessageForRSXMLError(expected, other),
|
||||
NSLocalizedRecoverySuggestionErrorKey: documentURI }];
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
|
||||
@interface RSXMLParser<__covariant T> : NSObject <RSXMLParserDelegate, RSSAXParserDelegate>
|
||||
@property (nonatomic, readonly, nonnull, copy) NSString *documentURI;
|
||||
@property (nonatomic, readonly, nonnull, copy) NSURL *documentURI;
|
||||
@property (nonatomic, assign) BOOL dontStopOnLowerAsciiBytes;
|
||||
|
||||
+ (instancetype)parserWithXMLData:(RSXMLData * _Nonnull)xmlData;
|
||||
|
||||
@@ -57,12 +57,12 @@
|
||||
- (instancetype)initWithXMLData:(nonnull RSXMLData *)xmlData {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_documentURI = [xmlData.urlString copy];
|
||||
_documentURI = [xmlData.url copy];
|
||||
_xmlInputError = [xmlData.parserError copy];
|
||||
[self checkIfParserMatches:xmlData.parserClass];
|
||||
_xmlData = xmlData.data;
|
||||
if (!_xmlData) {
|
||||
_xmlInputError = RSXMLMakeError(RSXMLErrorNoData);
|
||||
_xmlInputError = RSXMLMakeError(RSXMLErrorNoData, _documentURI);
|
||||
}
|
||||
_parser = [[RSSAXParser alloc] initWithDelegate:self];
|
||||
}
|
||||
@@ -159,7 +159,7 @@
|
||||
RSXMLError current = [self getExpectedErrorForClass:xmlParserClass];
|
||||
RSXMLError expected = [self getExpectedErrorForClass:[self class]];
|
||||
if (current != expected) {
|
||||
_xmlInputError = RSXMLMakeErrorWrongParser(expected, current);
|
||||
_xmlInputError = RSXMLMakeErrorWrongParser(expected, current, _documentURI);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
- (RSXMLData *)xmlData:(NSString *)title urlString:(NSString *)urlString {
|
||||
NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:title ofType:@"html" inDirectory:@"Resources"];
|
||||
return [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:s] urlString:urlString];
|
||||
return [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:s] url:[NSURL URLWithString:urlString]];
|
||||
}
|
||||
|
||||
- (void)testDaringFireball {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:ext inDirectory:@"Resources"];
|
||||
if (s == nil) return nil;
|
||||
NSData *d = [[NSData alloc] initWithContentsOfFile:s];
|
||||
return [[RSXMLData alloc] initWithData:d urlString:[NSString stringWithFormat:@"%@.%@", name, ext]];
|
||||
return [[RSXMLData alloc] initWithData:d url:[NSURL fileURLWithPath:s]];
|
||||
}
|
||||
|
||||
- (void)testOPMLExport {
|
||||
@@ -60,7 +60,7 @@
|
||||
NSLog(@"%@", exportString);
|
||||
|
||||
NSData *importData = [exportString dataUsingEncoding:NSUTF8StringEncoding];
|
||||
RSXMLData *xmlData = [[RSXMLData alloc] initWithData:importData urlString:@"none"];
|
||||
RSXMLData *xmlData = [[RSXMLData alloc] initWithData:importData url:[NSURL URLWithString:@""]];
|
||||
XCTAssertEqual(xmlData.parserClass, [RSOPMLParser class]);
|
||||
RSOPMLParser *parser = [RSOPMLParser parserWithXMLData:xmlData];
|
||||
XCTAssertNotNil(parser);
|
||||
@@ -91,7 +91,7 @@
|
||||
XCTAssertEqualObjects(error.domain, kRSXMLParserErrorDomain);
|
||||
|
||||
xmlData = [[RSXMLData alloc] initWithData:[[NSData alloc] initWithContentsOfFile:@"/System/Library/Kernels/kernel"]
|
||||
urlString:@"/System/Library/Kernels/kernel"];
|
||||
url:[NSURL fileURLWithPath:@"/System/Library/Kernels/kernel"]];
|
||||
XCTAssertNotNil(xmlData.parserError);
|
||||
XCTAssert(xmlData.parserError.code == RSXMLErrorMissingLeftCaret);
|
||||
RSXMLParser *parser2 = [xmlData getParser];
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
NSString *s = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:ext inDirectory:@"Resources"];
|
||||
if (s == nil) return nil;
|
||||
NSData *d = [[NSData alloc] initWithContentsOfFile:s];
|
||||
return [[RSXMLData alloc] initWithData:d urlString:[NSString stringWithFormat:@"%@.%@", name, ext]];
|
||||
return [[RSXMLData alloc] initWithData:d url:[NSURL fileURLWithPath:s]];
|
||||
}
|
||||
|
||||
- (RSFeedParser*)parserForFile:(NSString*)name extension:(NSString*)ext expect:(Class)cls {
|
||||
@@ -248,7 +248,7 @@
|
||||
[wrongParser parseSync:&error];
|
||||
XCTAssertNotNil(error);
|
||||
XCTAssertEqual(error.code, RSXMLErrorExpectingOPML);
|
||||
XCTAssertEqualObjects(error, RSXMLMakeErrorWrongParser(RSXMLErrorExpectingOPML, RSXMLErrorExpectingFeed));
|
||||
XCTAssertEqualObjects(error, RSXMLMakeErrorWrongParser(RSXMLErrorExpectingOPML, RSXMLErrorExpectingFeed, xmlData.url));
|
||||
XCTAssertEqualObjects(error.localizedDescription, @"Can't parse XML. OPML data expected, but RSS or Atom feed found.");
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
NSError *error = nil;
|
||||
RSXMLData *xmlData = [self xmlFile:@"feed_1" extension:@"rss"];
|
||||
RSParsedFeed *parsedFeed = [[xmlData getParser] parseSync:&error];
|
||||
printf("\n\nparsing: %s\n%s\n", xmlData.urlString.UTF8String, parsedFeed.description.UTF8String);
|
||||
printf("\n\nparsing: %s\n%s\n", xmlData.url.path.UTF8String, parsedFeed.description.UTF8String);
|
||||
XCTAssertNil(error);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user