开发者

Three20 - TTStyledTextLabel encountering base64 image data instead of URL - Crashes

I am using a TTStyledTextLabel with TTStyledText fromXHTML data to display a news article. It works fine except with the img is data instead of a link, in which case it crashes!

Code

TTStyledTextLabel *storyLabel开发者_如何学编程 = [[TTStyledTextLabel alloc] init]; 
[storyLabel setText: [TTStyledText textFromXHTML:[articleContents objectForKey:@"storyText"]]]; 

works fine with normal img url xml,

but when it encounters image data like this:

img class="alignleft" src="data:image/jpg;base64,/9j/4AAQSkZJRgA... 
(lots more in here)...1HhI0T//2Q==" alt="" width="267" height="189" / 

it crashes with the output:

-[NSURLResponse allHeaderFields]: unrecognized selector 
sent to instance 0xb83b370 

This only happens when it encounters image data, otherwise if is a normal img link it loads fine.

Thanks!


The problem is that the Three20 TTRequestLoader is using NSHTTPURLResponse instead of NSURLResponse in the NSURLConnectionDataDelegate methods. NSURLResponse doesn't have the method allHeaderFields, so the app is crashing.

You can fix it by checking for the class:

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response {
  _response = [response retain];

  if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
    NSDictionary* headers = [response allHeaderFields];
    int contentLength = [[headers objectForKey:@"Content-Length"] intValue];

    // If you hit this assertion it's because a massive file is about to be downloaded.
    // If you're sure you want to do this, add the following line to your app delegate startup
    // method. Setting the max content length to zero allows anything to go through. If you just
    // want to raise the limit, set it to any positive byte size.
    // [[TTURLRequestQueue mainQueue] setMaxContentLength:0]
    TTDASSERT(0 == _queue.maxContentLength || contentLength <=_queue.maxContentLength);

    if (contentLength > _queue.maxContentLength && _queue.maxContentLength) {
      TTDCONDITIONLOG(TTDFLAG_URLREQUEST, @"MAX CONTENT LENGTH EXCEEDED (%d) %@",
                      contentLength, _urlPath);
      [self cancel];
    }

    _responseData = [[NSMutableData alloc] initWithCapacity:contentLength];
  }
  else if ([response isKindOfClass:[NSURLResponse class]]) {
    _responseData = [[NSMutableData alloc] init];
  }
  else {
    [self cancel];
  }
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
  TTNetworkRequestStopped();

  if ([_response isKindOfClass:[NSHTTPURLResponse class]]) {
    TTDCONDITIONLOG(TTDFLAG_ETAGS, @"Response status code: %d", _response.statusCode);

    // We need to accept valid HTTP status codes, not only 200.
    if (_response.statusCode >= 200 && _response.statusCode < 300) {
      [_queue loader:self didLoadResponse:_response data:_responseData];
    } else if (_response.statusCode == 304) {
      [_queue loader:self didLoadUnmodifiedResponse:_response];
    } else {
      TTDCONDITIONLOG(TTDFLAG_URLREQUEST, @"  FAILED LOADING (%d) %@",
                      _response.statusCode, _urlPath);
      NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:_response.statusCode
                                       userInfo:nil];
      [_queue loader:self didFailLoadWithError:error];
    }
  }
  else if ([_response isKindOfClass:[NSURLResponse class]]) {
    [_queue loader:self didLoadResponse:_response data:_responseData];
  }

  TT_RELEASE_SAFELY(_responseData);
  TT_RELEASE_SAFELY(_connection);
}


Going to answer my own question here.

It seems like a rare case that this happens (in my specific situation). The way I solved it was by running a check before hand to see if the img link (which can potentially be image data) has a common image file type extension (jpg, png, gif, etc....). I'm simply ignoring it in the case that it does not and discarding the data.

I don't know much about web standards and whether or not it is considered OK to embed image data where links should be, but I'm now aware that it exists and can cause a crash using this class. Hopefully this can help anyone else who has this issue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜