Skip to content

Commit 23255a9

Browse files
author
Librelio Dev
committed
Merge remote-tracking branch 'origin/master'
2 parents a23f6e8 + b9005d2 commit 23255a9

File tree

2 files changed

+218
-33
lines changed

2 files changed

+218
-33
lines changed

Classes/WAPDFParser.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
// Copyright 2011 WidgetAvenue - Librelio. All rights reserved.
22

3+
#import <Foundation/Foundation.h>
34
#import "WAParserProtocol.h"
45

6+
typedef enum {
7+
Needed,
8+
Requested,
9+
Downloaded,
10+
NotNeeded
11+
} ExtraInformationStatus;
512

6-
7-
@interface WAPDFParser : NSObject <WAParserProtocol>{
13+
@interface WAPDFParser : NSObject <WAParserProtocol,NSURLConnectionDelegate,NSURLConnectionDataDelegate>{
814
int intParam,numberOfPages;
915
NSString * urlString;
1016
CFURLRef pdfURL;//DO NOT USE CGPDFDocumentRef in an instance var, it produces crashes. Use CGPDFDocumentCreateWithURL every time you need it
1117
NSMutableArray * outlineArray;
1218

13-
19+
ExtraInformationStatus extraInfoStatus;
20+
NSFileHandle *currentConnFileHandle;
21+
NSString *currentConnPath;
1422
}
1523

1624
@property (nonatomic, retain) NSMutableArray * outlineArray;
@@ -20,6 +28,7 @@
2028
@property (nonatomic, retain) NSString * urlString;
2129
@property int numberOfPages;
2230

31+
@property (nonatomic, retain) NSDictionary *linksUpdate;
2332

2433

2534
- (NSArray*)getLinksOnPage:(int)page;

Classes/WAPDFParser.m

Lines changed: 206 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ - (NSString*) getLinkFromDestArray:(CGPDFArrayRef)destArray;
2424

2525
@implementation WAPDFParser
2626

27-
@synthesize intParam,numberOfPages,outlineArray,currentString;
27+
@synthesize intParam,numberOfPages,outlineArray,currentString,linksUpdate=_linksUpdate;
2828
#pragma mark -
2929
#pragma mark Lifecycle functions
3030

@@ -97,8 +97,8 @@ - (void) setUrlString: (NSString *) theString
9797
[self generateCacheForAllPagesAtSize:PDFPageViewSizeBig];
9898

9999

100-
101-
100+
101+
extraInfoStatus = Needed;
102102

103103

104104

@@ -135,6 +135,8 @@ - (void)dealloc {
135135
[urlString release];
136136
[currentString release];
137137
[outlineArray release];
138+
if(_linksUpdate)
139+
[_linksUpdate release];
138140
[super dealloc];
139141

140142
}
@@ -145,7 +147,15 @@ - (void)dealloc {
145147

146148

147149

148-
150+
- (NSDictionary*) linksUpdate
151+
{
152+
if(_linksUpdate == nil)
153+
{
154+
NSString *updatesPath = [[NSBundle mainBundle] pathOfFileWithUrl:[[urlString noArgsPartOfUrlString] urlByChangingExtensionOfUrlStringToSuffix:@"_updates.plist"]];
155+
_linksUpdate = updatesPath ? [[NSDictionary dictionaryWithContentsOfFile:updatesPath] retain] : nil;
156+
}
157+
return _linksUpdate;
158+
}
149159

150160
- (int) getPageNumber:(int)page{
151161
//Gets the page number from the pdf document, which may be different from the pagination used in this class; for example, page 1 may be the third page of the pdf when it includes a cover
@@ -298,6 +308,23 @@ -(UIImage*) drawTileForPage:(int)page withTileRect:(CGRect)tileRect withImageRec
298308
#pragma mark -
299309
#pragma mark Links handling
300310

311+
- (NSDictionary*)getLinksUpdateOnPageByIndexAtPage:(int)pageNumber inLinksUpdate:(NSDictionary*)linksUpdate
312+
{
313+
NSArray *links;
314+
if(!linksUpdate || (links = [linksUpdate objectForKey:[NSString stringWithFormat:@"p%d", pageNumber]]) == nil)
315+
return nil;
316+
NSMutableDictionary *mret = [[[NSMutableDictionary alloc] init] retain];
317+
for(NSDictionary *link in links)
318+
{
319+
id index = [link objectForKey:@"IndexAtPage"];
320+
if(index != nil)
321+
[mret setObject:link forKey:[NSString stringWithFormat:@"%@", index]];
322+
}
323+
NSDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:mret];
324+
[mret release];
325+
return dict;
326+
}
327+
301328
- (NSArray*)getLinksOnPage:(int)page{
302329
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(pdfURL);
303330
NSMutableArray *tempArray= [NSMutableArray array];
@@ -314,15 +341,21 @@ - (NSArray*)getLinksOnPage:(int)page{
314341
CGPDFArrayRef annotsArray;
315342
if (!CGPDFDictionaryGetArray(pageDict, "Annots", &annotsArray)) continue;
316343
size_t annotsCount = CGPDFArrayGetCount(annotsArray);
344+
345+
// update links at page `j`
346+
NSDictionary *linksUpdateById = [self getLinksUpdateOnPageByIndexAtPage:j inLinksUpdate:self.linksUpdate];
347+
317348
for (size_t i = 0; i < annotsCount ; i++)
318349
{
319350
NSDictionary * tempDic;
351+
NSString * tempUrl = nil;
320352
CGPDFDictionaryRef annotDict;
321353
if (!CGPDFArrayGetDictionary(annotsArray, i, &annotDict)) continue;
322354
CGRect linkRect = [self getAnnotationRect:annotDict inPageRef:pageRef];
323355
NSValue *rectValue = [NSValue valueWithCGRect:linkRect];
324356

325357

358+
326359
//Check what type of annotation this is
327360
const char * subType = nil;
328361
if (!CGPDFDictionaryGetName(annotDict, "Subtype", &subType )) continue;
@@ -332,24 +365,50 @@ - (NSArray*)getLinksOnPage:(int)page{
332365
CGPDFDictionaryRef aLink;
333366
if (CGPDFDictionaryGetDictionary(annotDict, "A", &aLink))
334367
{
335-
NSString * tempString = [self getLinkFromActionDictionary:aLink];
336-
//SLog(@"Link:%@",tempString);
337-
tempDic = [NSDictionary dictionaryWithObjectsAndKeys:rectValue,@"Rect",tempString,@"URL",nil];
338-
[tempArray addObject:tempDic];
339-
368+
tempUrl = [self getLinkFromActionDictionary:aLink];
340369
}
341370
else {
342371
CGPDFArrayRef anotherArray;
343372
if (CGPDFDictionaryGetArray(annotDict, "Dest", &anotherArray))
344373
{
345-
NSString * tempString = [self getLinkFromDestArray:anotherArray];
346-
tempDic = [NSDictionary dictionaryWithObjectsAndKeys:rectValue,@"Rect",tempString,@"URL",nil];
347-
[tempArray addObject:tempDic];
348-
349-
374+
tempUrl = [self getLinkFromDestArray:anotherArray];
350375
}
351376
}
352377

378+
NSDictionary *updateLink = linksUpdateById ? [linksUpdateById objectForKey:[NSString stringWithFormat:@"%d", (int)i]] : nil;
379+
// override data if updateLink exists
380+
if(updateLink != nil)
381+
{
382+
NSString *v = [updateLink objectForKey:@"Action"];
383+
if([v isKindOfClass:[NSString class]])
384+
{
385+
if([v isEqualToString:@"Remove"])
386+
continue;
387+
else if([v isKindOfClass:[NSString class]] && [v isEqualToString:@"Edit"])
388+
{
389+
v = [updateLink objectForKey:@"Rect"];
390+
if([v isKindOfClass:[NSString class]])
391+
{
392+
CGFloat rectArr[4], *fp = rectArr;
393+
for(NSString *str in [v componentsSeparatedByString:@" "])
394+
*(fp++) = [str integerValue];
395+
if(fp - rectArr == 4)
396+
{
397+
rectValue = [NSValue valueWithCGRect:[self CGRectFromPDFRect:rectArr inPageRef:pageRef]];
398+
}
399+
}
400+
v = [updateLink objectForKey:@"Link"];
401+
if([v isKindOfClass:[NSString class]])
402+
tempUrl = v;
403+
}
404+
}
405+
}
406+
407+
if(tempUrl != nil)
408+
{
409+
tempDic = [NSDictionary dictionaryWithObjectsAndKeys:rectValue,@"Rect",tempUrl,@"URL",nil];
410+
[tempArray addObject:tempDic];
411+
}
353412

354413
}
355414
else if (!strcmp(subType, "RichMedia")) //Annotation is a rich media
@@ -427,6 +486,41 @@ - (NSArray*)getLinksOnPage:(int)page{
427486

428487
}
429488

489+
// add update links
490+
NSArray *links = self.linksUpdate ? [self.linksUpdate objectForKey:[NSString stringWithFormat:@"p%d", (int)j]] : nil;
491+
if([links isKindOfClass:[NSArray class]])
492+
{
493+
for(NSDictionary *link in links)
494+
{
495+
NSValue *rectValue = nil;
496+
NSString *tempUrl = nil;
497+
NSString *v = [link objectForKey:@"Action"];
498+
if([v isKindOfClass:[NSString class]] && [v isEqualToString:@"Add"])
499+
{
500+
v = [link objectForKey:@"Rect"];
501+
if([v isKindOfClass:[NSString class]])
502+
{
503+
CGFloat rectArr[4], *fp = rectArr;
504+
for(NSString *str in [v componentsSeparatedByString:@" "])
505+
*(fp++) = [str integerValue];
506+
if(fp - rectArr == 4)
507+
{
508+
rectValue = [NSValue valueWithCGRect:[self CGRectFromPDFRect:rectArr inPageRef:pageRef]];
509+
}
510+
}
511+
v = [link objectForKey:@"Link"];
512+
if([v isKindOfClass:[NSString class]])
513+
tempUrl = v;
514+
515+
516+
if(tempUrl != nil && rectValue != nil)
517+
{
518+
NSDictionary *tempDic = [NSDictionary dictionaryWithObjectsAndKeys:rectValue,@"Rect",tempUrl,@"URL",nil];
519+
[tempArray addObject:tempDic];
520+
}
521+
}
522+
}
523+
}
430524
}
431525

432526

@@ -435,7 +529,6 @@ - (NSArray*)getLinksOnPage:(int)page{
435529
//CGPDFPageRelease(pageRef);//This crashes the app
436530
CGPDFDocumentRelease(pdf);
437531

438-
439532
return tempArray;
440533

441534

@@ -518,10 +611,19 @@ - (NSString*) getLinkFromDestArray:(CGPDFArrayRef)destArray{
518611

519612
}
520613

614+
- (CGRect)CGRectFromPDFRect:(CGFloat*)linkPoints inPageRef:(CGPDFPageRef)pageRef{
615+
CGRect rect;
616+
CGRect documentRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox);
617+
rect.origin.x = linkPoints[0]- documentRect.origin.x;
618+
rect.origin.y = documentRect.size.height+documentRect.origin.y - linkPoints[3];
619+
rect.size.width = linkPoints[2] - linkPoints[0];
620+
rect.size.height = linkPoints[3] - linkPoints[1];
621+
return rect;
622+
}
623+
521624
- (CGRect) getAnnotationRect:(CGPDFDictionaryRef) annotDict inPageRef:(CGPDFPageRef)pageRef{
522625
CGFloat linkPoints[4] = {0.0,0.0,0.0,0.0};
523626
CGPDFArrayRef anArray;
524-
CGRect linkrect;
525627
if (CGPDFDictionaryGetArray(annotDict, "Rect", &anArray))
526628
{
527629
for (size_t j = 0; j < 4; j++)
@@ -533,20 +635,9 @@ - (CGRect) getAnnotationRect:(CGPDFDictionaryRef) annotDict inPageRef:(CGPDFPage
533635

534636
}
535637

536-
537-
CGRect documentRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox);
538-
//SLog(@"documentRect: %f, %f, %f, %f", documentRect.origin.x,documentRect.origin.y,documentRect.size.width,documentRect.size.height);
539-
//We need to make some conversions in order to match coordinate systems.
540-
linkrect.origin.x = linkPoints[0]- documentRect.origin.x;
541-
linkrect.origin.y = documentRect.size.height+documentRect.origin.y - linkPoints[3];
542-
linkrect.size.width = linkPoints[2] - linkPoints[0];
543-
linkrect.size.height = linkPoints[3] - linkPoints[1];
544-
//SLog(@"Annot Rect: %f, %f, %f, %f", linkrect.origin.x,linkrect.origin.y,linkrect.size.width,linkrect.size.height);
545-
546-
return linkrect;
638+
return [self CGRectFromPDFRect:linkPoints inPageRef:pageRef];
547639
}
548-
549-
640+
CGRect linkrect;
550641
return linkrect;
551642

552643

@@ -851,9 +942,94 @@ - (CGFloat) cacheProgress{
851942

852943
}
853944

945+
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
946+
{
947+
if(currentConnFileHandle)
948+
[currentConnFileHandle writeData:data];
949+
}
950+
951+
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
952+
{
953+
if(currentConnFileHandle)
954+
{
955+
[currentConnFileHandle release];
956+
extraInfoStatus = Downloaded;
957+
[currentConnPath release];
958+
959+
//fire notification
960+
[[NSNotificationCenter defaultCenter] postNotificationName:@"didGetExtraInformation" object:urlString];
961+
}
962+
}
963+
964+
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
965+
{
966+
if (([response statusCode]==304)||([response statusCode]==401)||([response statusCode]==402)||([response statusCode]==403)||([response statusCode]==461)||([response statusCode]==462)||([response statusCode]==463)){
967+
//SLog(@"Connection error %i",[response statusCode]);
968+
NSDictionary * userDic = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%li",(long)[response statusCode]] forKey:@"SSErrorHTTPStatusCodeKey"];
969+
NSError * error = [NSError errorWithDomain:@"Librelio" code:2 userInfo:userDic];
970+
971+
972+
[self connection:connection didFailWithError:error];
973+
}
974+
}
975+
976+
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
977+
{
978+
[currentConnFileHandle closeFile];
979+
[currentConnFileHandle release];
980+
if([[NSFileManager defaultManager] isDeletableFileAtPath:currentConnPath])
981+
[[NSFileManager defaultManager] removeItemAtPath:currentConnPath error:&error];
982+
currentConnFileHandle = nil;
983+
[currentConnPath release];
984+
currentConnPath = nil;
985+
extraInfoStatus = Downloaded;
986+
//fire notification
987+
[[NSNotificationCenter defaultCenter] postNotificationName:@"didGetExtraInformation" object:urlString];
988+
}
989+
854990
- (BOOL) shouldGetExtraInformation{
991+
BOOL needed = extraInfoStatus == Needed || extraInfoStatus == Requested;
992+
if(extraInfoStatus == Needed || extraInfoStatus == Downloaded)
993+
{
994+
NSString *updatesTmpUrl = [urlString urlByChangingExtensionOfUrlStringToSuffix:@"_updates.plist"];
995+
NSString *updatesUrl;
996+
NSArray *pc = [updatesTmpUrl pathComponents];
997+
if([[pc objectAtIndex:0] isEqualToString:@"TempWa"])
998+
{
999+
1000+
NSRange slr = (NSRange){ 1, [pc count] - 1 };
1001+
updatesUrl = [NSString stringWithFormat:@"/%@", [[pc subarrayWithRange:slr] componentsJoinedByString:@"/"]];
1002+
}
1003+
else if([pc count] > 1 && [[pc objectAtIndex:0] isEqualToString:@"/"] &&
1004+
[[pc objectAtIndex:1] isEqualToString:@"TempWa"])
1005+
{
1006+
NSRange slr = (NSRange){ 2, [pc count] - 2 };
1007+
updatesUrl = [NSString stringWithFormat:@"/%@", [[pc subarrayWithRange:slr] componentsJoinedByString:@"/"]];
1008+
}
1009+
NSString *updatesAbsUrl = [WAUtilities completeDownloadUrlforUrlString:updatesUrl];
1010+
1011+
1012+
if(extraInfoStatus == Downloaded)
1013+
{
1014+
NSString *savePath = [updatesUrl noArgsPartOfUrlString];
1015+
NSString *updatesTmpPath = [[NSBundle mainBundle] pathOfFileWithUrl:updatesTmpUrl];
1016+
if(updatesTmpPath != nil)
1017+
[WAUtilities storeFileWithUrlString:savePath withFileAtPath:updatesTmpPath];
1018+
extraInfoStatus = NotNeeded;
1019+
}
1020+
else
1021+
{
1022+
[WAUtilities storeFileWithUrlString:updatesTmpUrl withData:nil];
1023+
NSString *updatesTmpPath = [[NSBundle mainBundle] pathOfFileWithUrl:updatesTmpUrl];
1024+
currentConnFileHandle = [[NSFileHandle fileHandleForWritingAtPath:updatesTmpPath] retain];
1025+
NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:updatesAbsUrl]] delegate:self];
1026+
[conn start];
1027+
currentConnPath = [updatesTmpPath retain];
1028+
extraInfoStatus = Requested;
1029+
}
1030+
}
8551031

856-
return NO;
1032+
return needed;
8571033
}
8581034

8591035

0 commit comments

Comments
 (0)