//
// Copyright (c) 2011 Shun Takebayashi
//
// 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 "STWebArchiver.h"
#import <libxml/HTMLparser.h>
#import <libxml/xpath.h>
@interface STWebArchiver ()
- (NSArray *)valueForAttributeName:(NSString *)attributeName
withEvaluatingXPath:(NSString *)xpathExpression
inDocument:(xmlDocPtr)document;
- (NSArray *)absoluteURLsForPaths:(NSArray *)paths baseURL:(NSURL *)base;
@end
@implementation STWebArchiver
- (void)archiveHTMLData:(NSData *)aData
textEncoding:(NSString *)anEncoding
baseURL:(NSURL *)anURL
completionBlock:(void (^)(NSData *))completion {
htmlDocPtr doc = htmlParseDoc((xmlChar *)[aData bytes], [anEncoding UTF8String]);
NSArray *pathsForImagesAndScripts = [self valueForAttributeName:@"src" withEvaluatingXPath:@"//script[@src]|//img[@src]" inDocument:doc];
NSArray *pathsForStylesheets = [self valueForAttributeName:@"href" withEvaluatingXPath:@"//link[@rel='stylesheet'][@href]" inDocument:doc];
NSArray *resourcesPaths = [pathsForImagesAndScripts arrayByAddingObjectsFromArray:pathsForStylesheets];
NSArray *resourceUrls = [self absoluteURLsForPaths:resourcesPaths baseURL:anURL];
dispatch_async(dispatch_queue_create("Downloads", 0), ^{
NSMutableDictionary *resources = [NSMutableDictionary dictionary];
dispatch_apply([resourceUrls count], dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^(size_t i) {
NSURL *url = [resourceUrls objectAtIndex:i];
NSString *urlString = [url absoluteString];
BOOL unfetched = NO;
@synchronized (resources) {
unfetched = ![resources objectForKey:urlString];
if (unfetched) {
[resources setObject:[NSNull null] forKey:urlString];
}
}
if (unfetched) {
NSURLResponse *response;
NSError *error;
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
NSMutableDictionary *resourceArchive = [NSMutableDictionary dictionaryWithObjectsAndKeys:
urlString, @"WebResourceURL",
[response MIMEType], @"WebResourceMIMEType",
data, @"WebResourceData", nil];
if ([response textEncodingName]) {
[resourceArchive setObject:[response textEncodingName] forKey:@"WebResourceTextEncodingName"];
}
@synchronized (resources) {
[resources setObject:resourceArchive forKey:urlString];
}
}
});
NSMutableDictionary *archiveSource = [NSMutableDictionary dictionaryWithObject:[resources allValues] forKey:@"WebSubresources"];
NSMutableDictionary *mainResource = [NSMutableDictionary dictionary];
[mainResource setObject:aData forKey:@"WebResourceData"];
[mainResource setObject:@"" forKey:@"WebResourceFrameName"];
[mainResource setObject:@"text/html" forKey:@"WebResourceMIMEType"];
[mainResource setObject:anEncoding forKey:@"WebResourceTextEncodingName"];
[mainResource setObject:[anURL absoluteString] forKey:@"WebResourceURL"];
[archiveSource setObject:mainResource forKey:@"WebMainResource"];
NSData *webArchive = [NSPropertyListSerialization dataFromPropertyList:archiveSource
format:NSPropertyListBinaryFormat_v1_0
errorDescription:NULL];
completion(webArchive);
});
xmlFreeDoc(doc);
}
- (NSArray *)valueForAttributeName:(NSString *)attributeName
withEvaluatingXPath:(NSString *)xpathExpression
inDocument:(xmlDocPtr)document {
xmlXPathContextPtr context = xmlXPathNewContext(document);
xmlXPathObjectPtr xpathObject = xmlXPathEvalExpression((xmlChar *)[xpathExpression UTF8String], context);
xmlNodeSetPtr nodes = xpathObject->nodesetval;
NSMutableArray *results = nil;
if (!xmlXPathNodeSetIsEmpty(nodes)) {
results = [NSMutableArray arrayWithCapacity:nodes->nodeNr];
for (int i = 0; i < nodes->nodeNr; i++) {
xmlNodePtr node = nodes->nodeTab[i];
char *attributeChars = (char *)xmlGetProp(node, (xmlChar *)[attributeName UTF8String]);
NSString *attributeString = [NSString stringWithUTF8String:attributeChars];
xmlFree(attributeChars);
[results addObject:attributeString];
}
}
xmlXPathFreeObject(xpathObject);
xmlXPathFreeContext(context);
return results;
}
- (NSArray *)absoluteURLsForPaths:(NSArray *)paths baseURL:(NSURL *)base {
NSMutableArray *results = [NSMutableArray arrayWithCapacity:[paths count]];
for (NSString *path in paths) {
[results addObject:[NSURL URLWithString:path relativeToURL:base]];
}
return results;
}
@end
分享到:
相关推荐
解决QQ中转站下载次数 解决QQ中转站下载次数
这个问题涉及到如何有效地安排车辆,从供应点装载货物并运输到多个需求点,可能还需要经过中转站进行货物的再分配。在这个过程中,我们需要考虑成本、时间、容量限制等多方面因素,以实现运输效率的最大化或成本的...
QQ文件中转站 下载有次数限制,这个小软件可以破解次数限制。只要没被删除就可以下载。
中转站下载次数限制破解器
这款中转站的核心设计包括抓取机械手、多层内外圈存储结构和旋转与升降结构三大主要部分。具体来说,抓取机械手用于将快递包裹从外部送入存储结构内,并能从存储结构中取出包裹。多层内外圈存储结构允许包裹在不同的...
"QQ邮箱发送超大附件(文件中转站)功能使用详解" 本文将详细介绍QQ邮箱发送超大附件(文件中转站)功能的使用详解。该功能允许用户发送超大附件,解决了家庭、单位之间的文件传递问题,并且提供了安全的文件传输...
根据提供的文件信息,该文件名为“垃圾中转站可研报告分享.pdf”,文件描述为“垃圾中转站可研报告分享.pdf”。标签部分为空,表明可能没有明确的关键词或分类信息。而【部分内容】提供了密密麻麻的数据与数字,虽然...
QQFM中转站限次破解工具-iShare 无限次的下载qq中转站工具
总的来说,这个Java SSM快递中转站管理系统结合了现代Web开发的最佳实践,为快递行业的中转站管理提供了强大的技术支持,不仅提升了工作效率,也为数据分析和决策支持提供了便利。通过学习和研究这个系统,开发者...
"生活垃圾压缩中转站环评报告书.pdf" 本报告书主要介绍了##区城市生活垃圾压缩中转站工程的环评报告书,该项目位于##区红阳街办红阳村,总投资216万元,环保投资30万元,占地面积34.3亩,总建筑面积4110.64平方米。...
QQ邮箱中转站下载次数限制破解工具,免费发送
垃圾中转站技术方案知识点 垃圾中转站技术方案是指在废弃物管理中,将垃圾从一处转移到另一处的技术方案。根据常宁市300T垃圾转运站工艺及设备方案,以下是相关的知识点: 一、中转站主要参数与设计依据 * 中转站...
快递中转站-商业计划书
开发区垃圾中转站运行管理考核评分.pdf
"测试文件中转站"通常是指一个临时存储和分发文件的平台,用于在不同系统或团队之间传递数据,进行测试验证。这个压缩包可能包含了多种类型的文件,让我们逐一分析它们所代表的知识点: 1. **config**: 这个...
在IT行业中,网络中转站是一种常见的服务架构模式,它主要负责处理数据的临时存储和转发,以便于客户端上传资源并让其他客户端下载。这样的设计能够优化网络流量,减轻服务器压力,同时提供灵活的数据交换机制。本文...
"temp-file-viewer临时文件分享中转站"是一款专门用于临时文件分享的应用程序,它提供了一个安全、便捷的平台,让用户能够临时上传、存储并分享文件。这种服务尤其适用于那些需要短时间内交换大文件或者不希望文件...
QQ中转站是腾讯QQ邮箱推出的一项在线存储服务,它主要功能是帮助用户在不同的设备之间传输文件,或者向他人发送大容量的文件。QQ中转站提供了方便、快捷的文件管理和分享方式,解决了传统电子邮件附件大小限制的问题...