@@ -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