1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
- (id)initWithURL:(NSURL *)newURL {
	if((self = [super initWithURL:newURL])) {
		[self addRequestHeader:@"Accept-Encoding" value:@"gzip"];
	}
	
	return self;
}

- (NSString *)dataString {
	if (!receivedData) {
		return nil;
	}
	
	NSData* data;
	
	if([[self.responseHeaders objectForKey:@"Content-Encoding"] rangeOfString:@"gzip"].location != NSNotFound) {
		data = [self uncompressData:[self receivedData]];
	} else {
		data = [self receivedData];
	}


	if([[self.responseHeaders objectForKey:@"Content-Type"] rangeOfString:@"utf"].location != NSNotFound) {
		return [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease];
	} else {
		return [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSASCIIStringEncoding] autorelease];
	}
}

//
// @see http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
//
- (NSData *)uncompressData:(NSData*)compressedData {
	if ([compressedData length] == 0) return compressedData;

	unsigned full_length = [compressedData length];
	unsigned half_length = [compressedData length] / 2;
	
	NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length];
	BOOL done = NO;
	int status;
	
	z_stream strm;
	strm.next_in = (Bytef *)[compressedData bytes];
	strm.avail_in = [compressedData length];
	strm.total_out = 0;
	strm.zalloc = Z_NULL;
	strm.zfree = Z_NULL;
	
	if (inflateInit2(&strm, (15+32)) != Z_OK) return nil;
	while (!done)
	{
		// Make sure we have enough room and reset the lengths.
		if (strm.total_out >= [decompressed length])
			[decompressed increaseLengthBy: half_length];
		strm.next_out = [decompressed mutableBytes] + strm.total_out;
		strm.avail_out = [decompressed length] - strm.total_out;
		
		// Inflate another chunk.
		status = inflate (&strm, Z_SYNC_FLUSH);
		if (status == Z_STREAM_END) done = YES;
		else if (status != Z_OK) break;
	}
	if (inflateEnd (&strm) != Z_OK) return nil;
	
	// Set real length.
	if (done)
	{
		[decompressed setLength: strm.total_out];
		return [NSData dataWithData: decompressed];
	}
	else return nil;
}