@@ -385,7 +385,7 @@ - (void)customBarButtonItemAction:(UIBarButtonItem *)sender {
385
385
}
386
386
}
387
387
388
- - (NSURL *)pdfFileURLWithPath : (NSString *)path {
388
+ - (NSURL *)fileURLWithPath : (NSString *)path {
389
389
if (path) {
390
390
path = [path stringByExpandingTildeInPath ];
391
391
path = [path stringByReplacingOccurrencesOfString: @" file:" withString: @" " ];
@@ -397,6 +397,42 @@ - (NSURL *)pdfFileURLWithPath:(NSString *)path {
397
397
return nil ;
398
398
}
399
399
400
+ - (NSURL *)writableFileURLWithPath : (NSString *)path override : (BOOL )override copyIfNeeded : (BOOL )copyIfNeeded {
401
+ NSURL *writableFileURL;
402
+ if (path.absolutePath ) {
403
+ writableFileURL = [NSURL fileURLWithPath: path];
404
+ } else {
405
+ NSString *docsFolder = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES ).firstObject ;
406
+ writableFileURL = [NSURL fileURLWithPath: [docsFolder stringByAppendingPathComponent: path]];
407
+ }
408
+
409
+ NSFileManager *fileManager = NSFileManager .defaultManager ;
410
+ if (override) {
411
+ [fileManager removeItemAtURL: writableFileURL error: NULL ];
412
+ }
413
+
414
+ // If we don't have a writable file already, we move the provided file to the ~/Documents folder.
415
+ if (![fileManager fileExistsAtPath: (NSString *)writableFileURL.path]) {
416
+ // Create the folder where the writable file will be saved.
417
+ NSError *createFolderError;
418
+ if (![fileManager createDirectoryAtPath: writableFileURL.path.stringByDeletingLastPathComponent withIntermediateDirectories: YES attributes: nil error: &createFolderError]) {
419
+ NSLog (@" Failed to create directory: %@ " , createFolderError.localizedDescription );
420
+ return nil ;
421
+ }
422
+
423
+ // Copy the provided file to a writable location if it exists.
424
+ NSURL *fileURL = [self fileURLWithPath: path];
425
+ NSError *copyError;
426
+ if (copyIfNeeded && [fileManager fileExistsAtPath: (NSString *)fileURL.path]) {
427
+ if (![fileManager copyItemAtURL: fileURL toURL: writableFileURL error: ©Error]) {
428
+ NSLog (@" Failed to copy item at URL '%@ ' with error: %@ " , path, copyError.localizedDescription );
429
+ return nil ;
430
+ }
431
+ }
432
+ }
433
+ return writableFileURL;
434
+ }
435
+
400
436
- (BOOL )isImagePath : (NSString *)path {
401
437
NSString *pathExtension = path.pathExtension .lowercaseString ;
402
438
return [pathExtension isEqualToString: @" png" ] || [pathExtension isEqualToString: @" jpeg" ] || [pathExtension isEqualToString: @" jpg" ];
@@ -409,7 +445,7 @@ - (void)configurePDFViewControllerWithPath:(NSString *)path options:(NSDictionar
409
445
410
446
if (path) {
411
447
// configure document
412
- NSURL *url = [self pdfFileURLWithPath : path];
448
+ NSURL *url = [self fileURLWithPath : path];
413
449
if ([self isImagePath: path]) {
414
450
_pdfDocument = [[PSPDFImageDocument alloc ] initWithImageURL: url];
415
451
}
@@ -435,25 +471,11 @@ - (void)configurePDFViewControllerWithPath:(NSString *)path options:(NSDictionar
435
471
}
436
472
437
473
- (PSPDFDocument *)createXFDFDocumentWithPath : (NSString *)xfdfFilePath {
438
- NSURL *xfdfFileURL;
439
- if (xfdfFilePath.isAbsolutePath ) {
440
- xfdfFileURL = [self pdfFileURLWithPath: xfdfFilePath];
441
- } else {
442
- // Locate the XFDF file in the ~/Documents directory
443
- NSString *docsFolder = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES ).firstObject ;
444
- xfdfFileURL = [NSURL fileURLWithPath: [docsFolder stringByAppendingPathComponent: xfdfFilePath]];
445
- }
474
+ // Copy the XFDF file to the ~/Documents foler or create one if we don't have one.
475
+ NSURL *xfdfFileURL = [self writableFileURLWithPath: xfdfFilePath override: NO copyIfNeeded: YES ];
446
476
447
477
// Create an XFDF file from the current document if one doesn't already exist.
448
478
if (![NSFileManager .defaultManager fileExistsAtPath: (NSString *)xfdfFileURL.path]) {
449
- // Create the folder where the XFDF file will be saved.
450
- NSError *createFolderError;
451
- if (![NSFileManager .defaultManager createDirectoryAtPath: xfdfFileURL.path.stringByDeletingLastPathComponent withIntermediateDirectories: YES attributes: nil error: &createFolderError]) {
452
- NSLog (@" Failed to create directory: %@ " , createFolderError.localizedDescription );
453
- return nil ;
454
- }
455
-
456
- // Write the file
457
479
NSError *error;
458
480
PSPDFFileDataSink *dataSink = [[PSPDFFileDataSink alloc ] initWithFileURL: xfdfFileURL options: PSPDFDataSinkOptionNone error: &error];
459
481
if (dataSink) {
@@ -729,7 +751,7 @@ - (void)setLicenseKey:(CDVInvokedUrlCommand *)command {
729
751
730
752
- (void )setFileURLForPSPDFDocumentWithJSON : (NSString *)path {
731
753
// Brute-Force-Set.
732
- [_pdfDocument setValue: [self pdfFileURLWithPath : path] forKey: @" fileURL" ];
754
+ [_pdfDocument setValue: [self fileURLWithPath : path] forKey: @" fileURL" ];
733
755
}
734
756
735
757
- (NSString *)fileURLAsJSON {
@@ -1063,9 +1085,7 @@ - (void)presentWithXFDF:(CDVInvokedUrlCommand *)command {
1063
1085
1064
1086
// Validate the XFDF file path.
1065
1087
if (xfdfFilePath.length == 0 ) {
1066
- NSLog (@" The XFDF path must be a valid string" );
1067
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1068
- callbackId: command.callbackId];
1088
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" The XFDF path must be a valid string." ] callbackId: command.callbackId];
1069
1089
return ;
1070
1090
}
1071
1091
@@ -1413,7 +1433,7 @@ - (void)getAnnotations:(CDVInvokedUrlCommand *)command {
1413
1433
if (annotationsJSON) {
1414
1434
pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: @{@" annotations" : annotationsJSON}];
1415
1435
} else {
1416
- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: @{ @" localizedDescription " : @" Failed to get annotations" } ];
1436
+ pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to get annotations. " ];
1417
1437
}
1418
1438
1419
1439
[self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
@@ -1427,9 +1447,7 @@ - (void)addAnnotation:(CDVInvokedUrlCommand *)command {
1427
1447
} else if ([jsonAnnotation isKindOfClass: NSDictionary .class]) {
1428
1448
data = [NSJSONSerialization dataWithJSONObject: jsonAnnotation options: 0 error: nil ];
1429
1449
} else {
1430
- NSLog (@" Invalid JSON Annotation." );
1431
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1432
- callbackId: command.callbackId];
1450
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Invalid JSON Annotation." ] callbackId: command.callbackId];
1433
1451
return ;
1434
1452
}
1435
1453
@@ -1444,22 +1462,18 @@ - (void)addAnnotation:(CDVInvokedUrlCommand *)command {
1444
1462
}
1445
1463
1446
1464
if (success) {
1447
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK]
1465
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: YES ]
1448
1466
callbackId: command.callbackId];
1449
1467
} else {
1450
- NSLog (@" Failed to add annotation." );
1451
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1452
- callbackId: command.callbackId];
1468
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to add annotation." ] callbackId: command.callbackId];
1453
1469
}
1454
1470
}
1455
1471
1456
1472
- (void )removeAnnotation : (CDVInvokedUrlCommand *)command {
1457
1473
id jsonAnnotation = [command argumentAtIndex: 0 ];
1458
1474
NSString *annotationUUID = jsonAnnotation[@" uuid" ];
1459
1475
if (annotationUUID.length == 0 ) {
1460
- NSLog (@" Invalid annotation UUID." );
1461
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1462
- callbackId: command.callbackId];
1476
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Invalid annotation UUID." ] callbackId: command.callbackId];
1463
1477
}
1464
1478
1465
1479
PSPDFDocument *document = self.pdfController .document ;
@@ -1476,12 +1490,10 @@ - (void)removeAnnotation:(CDVInvokedUrlCommand *)command {
1476
1490
}
1477
1491
1478
1492
if (success) {
1479
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK]
1493
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: YES ]
1480
1494
callbackId: command.callbackId];
1481
1495
} else {
1482
- NSLog (@" Failed to remove annotation." );
1483
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1484
- callbackId: command.callbackId];
1496
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to remove annotation." ] callbackId: command.callbackId];
1485
1497
}
1486
1498
}
1487
1499
@@ -1496,7 +1508,7 @@ - (void)getAllUnsavedAnnotations:(CDVInvokedUrlCommand *)command {
1496
1508
if (annotationsJSON) {
1497
1509
pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: annotationsJSON];
1498
1510
} else {
1499
- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: @{ @" localizedDescription " : @" Failed to get annotations" } ];
1511
+ pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to get unsaved annotations" ];
1500
1512
}
1501
1513
1502
1514
[self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
@@ -1510,9 +1522,7 @@ - (void)applyInstantJSON:(CDVInvokedUrlCommand *)command {
1510
1522
} else if ([jsonValue isKindOfClass: NSDictionary .class]) {
1511
1523
data = [NSJSONSerialization dataWithJSONObject: jsonValue options: 0 error: nil ];
1512
1524
} else {
1513
- NSLog (@" Invalid JSON Annotations." );
1514
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1515
- callbackId: command.callbackId];
1525
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Invalid Instant JSON payload." ] callbackId: command.callbackId];
1516
1526
return ;
1517
1527
}
1518
1528
@@ -1523,12 +1533,10 @@ - (void)applyInstantJSON:(CDVInvokedUrlCommand *)command {
1523
1533
BOOL success = [document applyInstantJSONFromDataProvider: dataContainerProvider toDocumentProvider: documentProvider lenient: NO error: NULL ];
1524
1534
if (success) {
1525
1535
[self .pdfController reloadData ];
1526
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK]
1536
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: YES ]
1527
1537
callbackId: command.callbackId];
1528
1538
} else {
1529
- NSLog (@" Failed to add annotations." );
1530
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1531
- callbackId: command.callbackId];
1539
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to add annotations." ] callbackId: command.callbackId];
1532
1540
}
1533
1541
}
1534
1542
@@ -1560,9 +1568,7 @@ - (void)getFormFieldValue:(CDVInvokedUrlCommand *)command {
1560
1568
NSString *fullyQualifiedName = [command argumentAtIndex: 0 ];
1561
1569
1562
1570
if (fullyQualifiedName.length == 0 ) {
1563
- NSLog (@" Invalid fully qualified name." );
1564
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1565
- callbackId: command.callbackId];
1571
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Invalid fully qualified name." ] callbackId: command.callbackId];
1566
1572
return ;
1567
1573
}
1568
1574
@@ -1581,7 +1587,7 @@ - (void)getFormFieldValue:(CDVInvokedUrlCommand *)command {
1581
1587
if (formFieldValue) {
1582
1588
pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: @{@" value" : formFieldValue}];
1583
1589
} else {
1584
- pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: @{ @" localizedDescription " : @" Failed to get annotations " } ];
1590
+ pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to get form field value. " ];
1585
1591
}
1586
1592
1587
1593
[self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
@@ -1592,27 +1598,30 @@ - (void)setFormFieldValue:(CDVInvokedUrlCommand *)command {
1592
1598
NSString *fullyQualifiedName = [command argumentAtIndex: 1 ];
1593
1599
1594
1600
if (fullyQualifiedName.length == 0 ) {
1595
- NSLog (@" Invalid fully qualified name." );
1596
- [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1597
- callbackId: command.callbackId];
1601
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Invalid fully qualified name." ] callbackId: command.callbackId];
1598
1602
return ;
1599
1603
}
1600
1604
1601
1605
PSPDFDocument *document = self.pdfController .document ;
1602
1606
VALIDATE_DOCUMENT (document)
1603
1607
1608
+ BOOL success = NO ;
1604
1609
for (PSPDFFormElement *formElement in document.formParser .forms ) {
1605
1610
if ([formElement.fullyQualifiedFieldName isEqualToString: fullyQualifiedName]) {
1606
1611
if ([formElement isKindOfClass: PSPDFButtonFormElement.class]) {
1607
1612
if ([value isEqualToString: @" selected" ]) {
1608
1613
[(PSPDFButtonFormElement *)formElement select ];
1614
+ success = YES ;
1609
1615
} else if ([value isEqualToString: @" deselected" ]) {
1610
1616
[(PSPDFButtonFormElement *)formElement deselect ];
1617
+ success = YES ;
1611
1618
}
1612
1619
} else if ([formElement isKindOfClass: PSPDFChoiceFormElement.class]) {
1613
1620
((PSPDFChoiceFormElement *)formElement).selectedIndices = [NSIndexSet indexSetWithIndex: value.integerValue];
1621
+ success = YES ;
1614
1622
} else if ([formElement isKindOfClass: PSPDFTextFieldFormElement.class]) {
1615
1623
formElement.contents = value;
1624
+ success = YES ;
1616
1625
} else if ([formElement isKindOfClass: PSPDFSignatureFormElement.class]) {
1617
1626
NSLog (@" Signature form elements are not supported." );
1618
1627
} else {
@@ -1621,5 +1630,90 @@ - (void)setFormFieldValue:(CDVInvokedUrlCommand *)command {
1621
1630
break ;
1622
1631
}
1623
1632
}
1633
+ if (success) {
1634
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: YES ]
1635
+ callbackId: command.callbackId];
1636
+ } else {
1637
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" Failed to set form field value." ] callbackId: command.callbackId];
1638
+ }
1639
+ }
1640
+
1641
+ #pragma mark - XFDF
1642
+
1643
+ - (void )importXFDF : (CDVInvokedUrlCommand *)command {
1644
+ NSString *xfdfFilePath = [command argumentAtIndex: 0 ];
1645
+ // Validate the XFDF file path.
1646
+ if (xfdfFilePath.length == 0 ) {
1647
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" The XFDF path must be a valid string." ] callbackId: command.callbackId];
1648
+ return ;
1649
+ }
1650
+
1651
+ NSURL *xfdfFileURL = [self fileURLWithPath: xfdfFilePath];
1652
+ if (![NSFileManager .defaultManager fileExistsAtPath: (NSString *)xfdfFileURL.path]) {
1653
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsString: @" The XFDF file does not exist." ] callbackId: command.callbackId];
1654
+ return ;
1655
+ }
1656
+
1657
+ PSPDFDocument *document = self.pdfController .document ;
1658
+ VALIDATE_DOCUMENT (document)
1659
+
1660
+ PSPDFFileDataProvider *dataProvider = [[PSPDFFileDataProvider alloc ] initWithFileURL: xfdfFileURL];
1661
+ PSPDFXFDFParser *parser = [[PSPDFXFDFParser alloc ] initWithDataProvider: dataProvider documentProvider: document.documentProviders[0 ]];
1662
+
1663
+ NSError *error;
1664
+ if ([parser parseWithError: &error]) {
1665
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: YES ]
1666
+ callbackId: command.callbackId];
1667
+ } else {
1668
+ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR
1669
+ messageAsDictionary: @{@" localizedDescription" : error.localizedDescription , @" domain" : error.domain }];
1670
+ [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
1671
+ return ;
1672
+ }
1673
+
1674
+ // Import annotations to the document.
1675
+ NSArray <PSPDFAnnotation *> *annotations = parser.annotations ;
1676
+ if (annotations) {
1677
+ [document addAnnotations: annotations options: nil ];
1678
+ }
1624
1679
}
1680
+
1681
+ - (void )exportXFDF : (CDVInvokedUrlCommand *)command {
1682
+ NSString *xfdfFilePath = [command argumentAtIndex: 0 ];
1683
+ // Validate the XFDF file path.
1684
+ if (xfdfFilePath.length == 0 ) {
1685
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR]
1686
+ callbackId: command.callbackId];
1687
+ return ;
1688
+ }
1689
+
1690
+ // Always overwrite the XFDF file we export to.
1691
+ NSURL *xfdfFileURL = [self writableFileURLWithPath: xfdfFilePath override: YES copyIfNeeded: NO ];
1692
+ PSPDFDocument *document = self.pdfController .document ;
1693
+ VALIDATE_DOCUMENT (document)
1694
+
1695
+ // Collect all existing annotations from the document
1696
+ NSMutableArray *annotations = [NSMutableArray array ];
1697
+ for (NSArray *pageAnnotations in [document allAnnotationsOfType: PSPDFAnnotationTypeAll].allValues ) {
1698
+ [annotations addObjectsFromArray: pageAnnotations];
1699
+ }
1700
+ // Write to the XFDF file.
1701
+ NSError *error;
1702
+ PSPDFFileDataSink *dataSink = [[PSPDFFileDataSink alloc ] initWithFileURL: xfdfFileURL options: PSPDFDataSinkOptionNone error: &error];
1703
+ if (dataSink) {
1704
+ if ([[PSPDFXFDFWriter new ] writeAnnotations: annotations toDataSink: dataSink documentProvider: document.documentProviders[0 ] error: &error]) {
1705
+ [self .commandDelegate sendPluginResult: [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsBool: YES ]
1706
+ callbackId: command.callbackId];
1707
+ } else {
1708
+ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR
1709
+ messageAsDictionary: @{@" localizedDescription" : error.localizedDescription , @" domain" : error.domain }];
1710
+ [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
1711
+ }
1712
+ } else {
1713
+ CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR
1714
+ messageAsDictionary: @{@" localizedDescription" : error.localizedDescription , @" domain" : error.domain }];
1715
+ [self .commandDelegate sendPluginResult: pluginResult callbackId: command.callbackId];
1716
+ }
1717
+ }
1718
+
1625
1719
@end
0 commit comments