no message
This commit is contained in:
parent
bb38a40ea9
commit
549b27d6de
@ -62,7 +62,7 @@
|
||||
|
||||
[self.view addSubview:_cancelToken];
|
||||
|
||||
User * user = [User currentUser];
|
||||
//User * user = [User currentUser];
|
||||
|
||||
[self.view setNeedsUpdateConstraints];
|
||||
}
|
||||
@ -102,19 +102,27 @@
|
||||
|
||||
- (void) apiCallAction {
|
||||
|
||||
PNObjcPassword *password = [PNObjcPassword new];
|
||||
[password setPassword:@"asdasdasd"];
|
||||
[password setConfirmPassword:@"asdasdasd"];
|
||||
|
||||
/*User *user = [User currentUser];
|
||||
[user setFirstName:@"Giuseppe"];
|
||||
[user setLastName:@"Nuficora"];
|
||||
[user setEmail:@"packman@giuseppenucifora.com"];
|
||||
[user setPassword:@"asdasdasd"];
|
||||
[user setConfirmPassword:@"asdasdasd"];
|
||||
[user setHasAcceptedNewsletter:NO];
|
||||
[user setHasAcceptedPrivacy:YES];
|
||||
User *user = [User currentUser];
|
||||
[user setFirstName:@"Giuseppe"];
|
||||
[user setLastName:@"Nuficora"];
|
||||
[user setEmail:@"packman@giuseppenucifora.com"];
|
||||
[user setPassword:password];
|
||||
[user setHasAcceptedNewsletter:NO];
|
||||
[user setHasAcceptedPrivacy:YES];
|
||||
|
||||
[user saveLocally];
|
||||
[user saveLocally];
|
||||
|
||||
[user reloadFormServer];*/
|
||||
NSLog(@"%@",[user JSONFormObject]);
|
||||
//NSLog(@"%@",[user JSONObjectMap]);
|
||||
[user registerWithBlockSuccess:^(PNUser * _Nullable responseObject) {
|
||||
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
|
||||
}];
|
||||
|
||||
/*[[User currentUser] socialLoginWithBlockSuccessFromViewController:self
|
||||
blockSuccess:^(PNUser * _Nullable responseObject) {
|
||||
@ -123,17 +131,17 @@
|
||||
|
||||
}];*/
|
||||
|
||||
User * user = [User currentUser];
|
||||
/*User * user = [User currentUser];
|
||||
|
||||
if ([user isAuthenticated]) {
|
||||
if ([user isAuthenticated]) {
|
||||
|
||||
[user loginCurrentUserWithEmail:@"packman@giuseppenucifora.com" password:@"asdasdasd" withBlockSuccess:^(PNUser * _Nullable responseObject) {
|
||||
[user loginCurrentUserWithEmail:@"packman@giuseppenucifora.com" password:@"asdasdasd" withBlockSuccess:^(PNUser * _Nullable responseObject) {
|
||||
|
||||
NSLog(@"response : %@",responseObject);
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
NSLog(@"response : %@",error);
|
||||
}];
|
||||
}
|
||||
NSLog(@"response : %@",responseObject);
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
NSLog(@"response : %@",error);
|
||||
}];
|
||||
}*/
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
|
||||
@ -40,7 +40,7 @@ PODS:
|
||||
- NSString-Helper (1.0.2)
|
||||
- nv-ios-http-status (0.0.1)
|
||||
- PEAR-FileManager-iOS (1.3.1)
|
||||
- PNObject (0.3.6):
|
||||
- PNObject (0.3.7):
|
||||
- AFNetworking
|
||||
- CodFis-Helper
|
||||
- FBSDKCoreKit
|
||||
@ -50,9 +50,11 @@ PODS:
|
||||
- NSString-Helper
|
||||
- nv-ios-http-status
|
||||
- PEAR-FileManager-iOS
|
||||
- RNCryptor
|
||||
- StrongestPasswordValidator
|
||||
- UIDevice-Utils
|
||||
- PureLayout (3.0.1)
|
||||
- RNCryptor (4.0.0)
|
||||
- Specta (1.0.5)
|
||||
- StrongestPasswordValidator (0.1.1)
|
||||
- UIDevice-Utils (0.1.4)
|
||||
@ -94,8 +96,9 @@ SPEC CHECKSUMS:
|
||||
NSString-Helper: 0ee74919829a332f9838fa87b28cb2d1d991e92c
|
||||
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
|
||||
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
|
||||
PNObject: 6f799e51e8206ec5e43dcf109b04a6d14b0475d0
|
||||
PNObject: d71bf835bf4ca94308b9764b3c7e7a101d01343a
|
||||
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
|
||||
RNCryptor: 59d6483908115af5c12b884db23392024e52a5fe
|
||||
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
|
||||
StrongestPasswordValidator: 554de9038705e18904f0337903dfd3b85a6b271b
|
||||
UIDevice-Utils: 0beb5f9d2bd256a3efe05c1e43a2a8b8702199c4
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "PNObject",
|
||||
"version": "0.3.6",
|
||||
"version": "0.3.7",
|
||||
"summary": "PNObject is a simple replica of the more complex ParseObject",
|
||||
"homepage": "https://github.com/giuseppenucifora/PNObject",
|
||||
"license": "MIT",
|
||||
@ -9,7 +9,7 @@
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/giuseppenucifora/PNObject.git",
|
||||
"tag": "0.3.6"
|
||||
"tag": "0.3.7"
|
||||
},
|
||||
"platforms": {
|
||||
"ios": "7.0"
|
||||
@ -54,6 +54,9 @@
|
||||
],
|
||||
"FBSDKLoginKit": [
|
||||
|
||||
],
|
||||
"RNCryptor": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
7
Example/Pods/Manifest.lock
generated
7
Example/Pods/Manifest.lock
generated
@ -40,7 +40,7 @@ PODS:
|
||||
- NSString-Helper (1.0.2)
|
||||
- nv-ios-http-status (0.0.1)
|
||||
- PEAR-FileManager-iOS (1.3.1)
|
||||
- PNObject (0.3.6):
|
||||
- PNObject (0.3.7):
|
||||
- AFNetworking
|
||||
- CodFis-Helper
|
||||
- FBSDKCoreKit
|
||||
@ -50,9 +50,11 @@ PODS:
|
||||
- NSString-Helper
|
||||
- nv-ios-http-status
|
||||
- PEAR-FileManager-iOS
|
||||
- RNCryptor
|
||||
- StrongestPasswordValidator
|
||||
- UIDevice-Utils
|
||||
- PureLayout (3.0.1)
|
||||
- RNCryptor (4.0.0)
|
||||
- Specta (1.0.5)
|
||||
- StrongestPasswordValidator (0.1.1)
|
||||
- UIDevice-Utils (0.1.4)
|
||||
@ -94,8 +96,9 @@ SPEC CHECKSUMS:
|
||||
NSString-Helper: 0ee74919829a332f9838fa87b28cb2d1d991e92c
|
||||
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
|
||||
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
|
||||
PNObject: 6f799e51e8206ec5e43dcf109b04a6d14b0475d0
|
||||
PNObject: d71bf835bf4ca94308b9764b3c7e7a101d01343a
|
||||
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
|
||||
RNCryptor: 59d6483908115af5c12b884db23392024e52a5fe
|
||||
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
|
||||
StrongestPasswordValidator: 554de9038705e18904f0337903dfd3b85a6b271b
|
||||
UIDevice-Utils: 0beb5f9d2bd256a3efe05c1e43a2a8b8702199c4
|
||||
|
||||
7431
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
7431
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
||||
buildForArchiving = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = 'primary'
|
||||
BlueprintIdentifier = 'F6BDA83096F6440DD1D129F7219559C2'
|
||||
BlueprintIdentifier = 'FF6DB175E269D4B6BC28013A2E0B79DC'
|
||||
BlueprintName = 'PNObject'
|
||||
ReferencedContainer = 'container:Pods.xcodeproj'
|
||||
BuildableName = 'PNObject.framework'>
|
||||
|
||||
21
Example/Pods/RNCryptor/LICENSE
generated
Normal file
21
Example/Pods/RNCryptor/LICENSE
generated
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rob Napier
|
||||
|
||||
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.
|
||||
335
Example/Pods/RNCryptor/README.md
generated
Normal file
335
Example/Pods/RNCryptor/README.md
generated
Normal file
@ -0,0 +1,335 @@
|
||||
# RNCryptor
|
||||
|
||||
Cross-language AES Encryptor/Decryptor [data format](https://github.com/RNCryptor/RNCryptor-Spec/blob/master/RNCryptor-Spec-v3.md).
|
||||
|
||||
The primary targets are Swift and Objective-C, but implementations are available in [C](https://github.com/RNCryptor/RNCryptor-C), [C++](https://github.com/RNCryptor/RNCryptor-cpp), [C#](https://github.com/RNCryptor/RNCryptor-cs), [Erlang](https://github.com/RNCryptor/RNCryptor-erlang), [Go](https://github.com/RNCryptor/RNCryptor-go), [Haskell](https://github.com/RNCryptor/rncryptor-hs), [Java](https://github.com/RNCryptor/JNCryptor),
|
||||
[PHP](https://github.com/RNCryptor/RNCryptor-php), [Python](https://github.com/RNCryptor/RNCryptor-python),
|
||||
[Javascript](https://github.com/chesstrian/JSCryptor), and [Ruby](https://github.com/RNCryptor/ruby_rncryptor).
|
||||
|
||||
The data format includes all the metadata required to securely implement AES encryption, as described in ["Properly encrypting with AES with CommonCrypto,"](http://robnapier.net/aes-commoncrypto) and [*iOS 6 Programming Pushing the Limits*](http://iosptl.com), Chapter 15. Specifically, it includes:
|
||||
|
||||
* AES-256 encryption
|
||||
* CBC mode
|
||||
* Password stretching with PBKDF2
|
||||
* Password salting
|
||||
* Random IV
|
||||
* Encrypt-then-hash HMAC
|
||||
|
||||
## Contents
|
||||
|
||||
* [Format Versus Implementation](#format-versus-implementation)
|
||||
* [Basic Password Usage](#basic-password-usage)
|
||||
* [Incremental Usage](#incremental-usage)
|
||||
* [Installation](#installation)
|
||||
* [Advanced Usage](#advanced-usage)
|
||||
* [FAQ](#faq)
|
||||
* [Design Considerations](#design-considerations)
|
||||
* [License](#license)
|
||||
|
||||
## Format Versus Implementation
|
||||
|
||||
The RNCryptor data format is cross-platform and there are many implementations. The framework named "RNCryptor" is a specific implementation for Swift and Objective-C. Both have version numbers. The current data format is v3. The current framework implementation (which reads the v3 format) is v4.
|
||||
|
||||
## Basic Password Usage
|
||||
|
||||
### Swift
|
||||
|
||||
```swift
|
||||
// Encryption
|
||||
let data: NSData = ...
|
||||
let password = "Secret password"
|
||||
let ciphertext = RNCryptor.encryptData(data, password: password)
|
||||
|
||||
// Decryption
|
||||
do {
|
||||
let originalData = try RNCryptor.decryptData(ciphertext, password: password)
|
||||
// ...
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
```
|
||||
|
||||
### Obj-C
|
||||
|
||||
``` objc
|
||||
// Encryption
|
||||
NSData *data = ...
|
||||
NSString *password = @"Secret password";
|
||||
NSData *ciphertext = [RNCryptor encryptData:data password:password];
|
||||
|
||||
// Decryption
|
||||
NSError *error = nil;
|
||||
NSData *plaintext = [RNCryptor decryptData:ciphertext password:password error:&error];
|
||||
if (error != nil) {
|
||||
NSLog(@"ERROR:", error);
|
||||
return
|
||||
}
|
||||
// ...
|
||||
```
|
||||
|
||||
## Incremental Usage
|
||||
|
||||
RNCryptor supports incremental use, for example when using with `NSURLSession`. This is also useful for cases where the encrypted or decrypted data will not comfortably fit in memory.
|
||||
|
||||
To operate in incremental mode, you create an `Encryptor` or `Decryptor`, call `updateWithData()` repeatedly, gathering its results, and then call `finalData()` and gather its result.
|
||||
|
||||
### Swift
|
||||
|
||||
```swift
|
||||
//
|
||||
// Encryption
|
||||
//
|
||||
let password = "Secret password"
|
||||
let encryptor = RNCryptor.Encryptor(password: password)
|
||||
let ciphertext = NSMutableData()
|
||||
|
||||
// ... Each time data comes in, update the encryptor and accumulate some ciphertext ...
|
||||
ciphertext.appendData(encryptor.updateWithData(data))
|
||||
|
||||
// ... When data is done, finish up ...
|
||||
ciphertext.appendData(encryptor.finalData())
|
||||
|
||||
//
|
||||
// Decryption
|
||||
//
|
||||
let password = "Secret password"
|
||||
let decryptor = RNCryptor.Decryptor(password: password)
|
||||
let plaintext = NSMutableData()
|
||||
|
||||
// ... Each time data comes in, update the decryptor and accumulate some plaintext ...
|
||||
try plaintext.appendData(decryptor.updateWithData(data))
|
||||
|
||||
// ... When data is done, finish up ...
|
||||
try plaintext.appendData(decryptor.finalData())
|
||||
```
|
||||
|
||||
### Obj-C
|
||||
|
||||
``` objc
|
||||
//
|
||||
// Encryption
|
||||
//
|
||||
NSString *password = @"Secret password";
|
||||
RNEncryptor *encryptor = [[RNEncryptor alloc] initWithPassword:password];
|
||||
NSMutableData *ciphertext = [NSMutableData new];
|
||||
|
||||
// ... Each time data comes in, update the encryptor and accumulate some ciphertext ...
|
||||
[ciphertext appendData:[encryptor updateWithData:data]];
|
||||
|
||||
// ... When data is done, finish up ...
|
||||
[ciphertext appendData:[encryptor finalData]];
|
||||
|
||||
|
||||
//
|
||||
// Decryption
|
||||
//
|
||||
RNDecryptor *decryptor = [[RNDecryptor alloc] initWithPassword:password];
|
||||
NSMutableData *plaintext = [NSMutableData new];
|
||||
|
||||
// ... Each time data comes in, update the decryptor and accumulate some plaintext ...
|
||||
NSError *error = nil;
|
||||
NSData *partialPlaintext = [decryptor updateWithData:data error:&error];
|
||||
if (error != nil) {
|
||||
NSLog(@"FAILED DECRYPT: %@", error);
|
||||
return;
|
||||
}
|
||||
[plaintext appendData:partialPlaintext];
|
||||
|
||||
// ... When data is done, finish up ...
|
||||
NSError *error = nil;
|
||||
NSData *partialPlaintext = [decryptor finalDataAndReturnError:&error];
|
||||
if (error != nil) {
|
||||
NSLog(@"FAILED DECRYPT: %@", error);
|
||||
return;
|
||||
}
|
||||
|
||||
[ciphertext appendData:partialPlaintext];
|
||||
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Requirements
|
||||
|
||||
RNCryptor 4 is written in Swift 2, so requires Xcode 7, and can target iOS 7 or later (iOS 8 or later if used as a framework), and OS X 10.9 or later. If you want a pure ObjC implementation that supports older versions of iOS and OS X, see [RNCryptor 3](https://github.com/RNCryptor/RNCryptor/releases/tag/RNCryptor-3.0.1).
|
||||
|
||||
### The Bridging Header
|
||||
|
||||
CommonCrypto is not a modular header in Xcode 7. This makes it very challenging to import into Swift. To work around this, the necessary header files have been copied into `RNCryptor.h`, which needs to be bridged into Swift. You can do this either by using RNCryptor as a framework, adding `#import "RNCryptor/RNCryptor.h"` to your existing bridging header, or making `RNCryptor/RNCryptor.h` your bridging header in Build Settings, "Objective-C Bridging Header."
|
||||
|
||||
Hopefully Apple will [make CommonCrypto a modular header soon](http://www.openradar.me/22965816). When this happens, the bridging header will not be needed, and RNCryptor will be a single file.
|
||||
|
||||
### Installing Manually
|
||||
|
||||
The easiest way to use RNCryptor is by making it part of your project, without a framework. RNCryptor is just one swift file and one bridging header, and you can skip all the complexity of managing frameworks this way. It also makes version control very simple if you use submodules, or checkin specific versions of RNCryptor to your repository.
|
||||
|
||||
This process works for most targets: iOS and OS X GUI apps, Swift frameworks, and OS X commandline apps. **It is not safe for ObjC frameworks or frameworks that may be imported into ObjC, since it would cause duplicate symbols if some other framework includes RNCryptor.**
|
||||
|
||||
* Drag and link `RNCryptor/RNCryptor.swift` into your project
|
||||
* If you already have a bridging header file, add `#import "RNCryptor/RNCryptor.h"`
|
||||
* If you don't have a bridging header, in your target's Build Settings, set "Objective-C Bridging Header" to "RNCryptor/RNCryptor.h"
|
||||
|
||||
Built this way, you don't need to (and can't) `import RNCryptor` into your code. RNCryptor will be part of your module.
|
||||
|
||||
### [Carthage](https://github.com/Carthage/Carthage)
|
||||
|
||||
github "RNCryptor/RNCryptor" "RNCryptor-4.0.0-beta.1"
|
||||
|
||||
Don't forget to embed `RNCryptor.framework`. Built this way, you should add `import RNCryptor` to your code.
|
||||
|
||||
This approach will not work for OS X commandline apps.
|
||||
|
||||
### [CocoaPods](https://cocoapods.org)
|
||||
|
||||
pod 'RNCryptor', '~> 4.0.0-beta'
|
||||
|
||||
This approach will not work for OS X commandline apps.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Version-Specific Cryptors
|
||||
|
||||
The default `RNCryptor.Encryptor` is the "current" version of the data format (currently v3). If you're interoperating with other implementations, you may need to choose a specific format for compatibility.
|
||||
|
||||
To create a version-locked cryptor, use `RNCryptor.EncryptorV3` and `RNCryptor.DecryptorV3`.
|
||||
|
||||
Remember: the version specified here is the *format* version, not the implementation version. The v4 RNCryptor framework reads and writes the v3 RNCryptor data format.
|
||||
|
||||
### Key-Based Encryption
|
||||
|
||||
*You need a little expertise to use key-based encryption correctly, and it is very easy to make insecure systems that look secure. The most important rule is that keys must be random across all their bytes. If you're not comfortable with basic cryptographic concepts like AES-CBC, IV, and HMAC, you probably should avoid using key-based encryption.*
|
||||
|
||||
Cryptography works with keys, which are random byte sequences of a specific length. The RNCryptor v3 format uses two 256-bit (32-byte) keys to perform encryption and authentication.
|
||||
|
||||
Passwords are not "random byte sequences of a specific length." They're not random at all, and they can be a wide variety of lengths, very seldom exactly 32. RNCryptor defines a specific and secure way to convert passwords into keys, and that is one of it's primary features.
|
||||
|
||||
Occasionally there are reasons to work directly with random keys. Converting a password into a key is intentionally slow (tens of milliseconds). Password-encrypted messages are also a 16 bytes longer than key-encrypted messages. If your system encrypts and decrypts many short messages, this can be a significant performance impact, particularly on a server.
|
||||
|
||||
RNCryptor supports direct key-based encryption and decryption. The size and number of keys may change between format versions, so key-based cryptors are [version-specific](#version-specific-cryptors).
|
||||
|
||||
In order to be secure, the keys must be a random sequence of bytes. If you're starting with a string of any kind, you are almost certainly doing this wrong.
|
||||
|
||||
```swift
|
||||
let encryptor = RNCryptor.EncryptorV3(encryptionKey: encryptKey, hmacKey: hmacKey)
|
||||
let decryptor = RNCryptor.DecryptorV3(encryptionKey: encryptKey, hmacKey: hmacKey)
|
||||
```
|
||||
|
||||
```objc
|
||||
RNEncryptor *encryptor = [[[RNEncryptorV3 alloc] initWithEncryptionKey:encryptionKey hmacKey:hmacKey];
|
||||
RNDecryptor *decryptor = [[[RNDecryptorV3 alloc] initWithEncryptionKey:encryptionKey hmacKey:hmacKey];
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I detect an incorrect password?
|
||||
|
||||
If you decrypt with the wrong password, you will receive an `HMACMismatch` error. This is the same error you will receive if your ciphertext is corrupted.
|
||||
|
||||
The v3 data format has no way to detect incorrect passwords directly. It just decrypts gibberish, and then uses the HMAC (a kind of encrypted hash) to determine that the result is corrupt. You won't discover this until the entire message has been decrypted (during the call to `finalData()`).
|
||||
|
||||
This can be inconvenient for the user if they have entered the wrong password to decrypt a very large file. If you have this situation, the recommendation is to encrypt some small, known piece of data with the same password. Test the password on the small ciphertext before decrypting the larger one.
|
||||
|
||||
The [v4 data format](https://github.com/RNCryptor/RNCryptor-Spec/blob/master/draft-RNCryptor-Spec-v4.0.md) will provide a faster and more useful mechanism for validating the password or key.
|
||||
|
||||
### Can I use RNCryptor to read and write my non-RNCryptor data format?
|
||||
|
||||
No. RNCryptor implements a specific data format. It is not a general-purpose encryption library. If you have created your own data format, you will need to write specific code to deal with whatever you created. Please make sure the data format you've invented is secure. (This is much harder than it sounds.)
|
||||
|
||||
If you're using the OpenSSL encryption format, see [RNOpenSSLCryptor](https://github.com/rnapier/RNOpenSSLCryptor).
|
||||
|
||||
### Can I change the parameters used (algorithm, iterations, etc)?
|
||||
|
||||
No. See previous question. The [v4 format](https://github.com/RNCryptor/RNCryptor-Spec/blob/master/draft-RNCryptor-Spec-v4.0.md) will permit some control over PBKDF2 iterations, but the only thing configurable in the v3 format is whether a password or key is used. This keeps RNCryptor implementations dramatically simpler and interoperable.
|
||||
|
||||
### How do I manually set the IV?
|
||||
|
||||
You don't. See the last two questions.
|
||||
|
||||
Also note that if you ever reuse a key+IV combination, you risk attackers decrypting the beginning of your message. A static IV makes a key+IV reuse much more likely (guarenteed if you also have a static key). Wikipedia has a [quick overview of this problem](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Initialization_vector_.28IV.29).
|
||||
|
||||
### How do I encrypt/decrypt a string?
|
||||
|
||||
AES encrypts bytes. It does not encrypt characters, letters, words, pictures, videos, cats, or ennui. It encrypts bytes. You need to convert other things (such as strings) to and from bytes in a consistent way. There are several ways to do that. Some of the most popular are UTF-8 encoding, Base-64 encoding, and Hex encoding. There are many other options. There is no good way for RNCryptor to guess which encoding you want, so it doesn't try. It accepts and returns bytes in the form of `NSData`.
|
||||
|
||||
To convert strings to data as UTF-8, use `dataUsingEncoding()` and `init(data:encoding:)`. To convert strings to data as Base-64, use `init(base64EncodedString:options:)` and `base64EncodedStringWithOptions()`.
|
||||
|
||||
### Does RNCryptor support random access decryption?
|
||||
|
||||
The usual use case for this is encrypting media files like video. RNCryptor uses CBC encryption, which prevents easy random-access. While other modes are better for random-access (CTR for instance), they are more complicated to implement correctly and CommonCrypto doesn't support using them for random access anyway.
|
||||
|
||||
It would be fairly easy to build a wrapper around RNCryptor that allowed random-access to blocks of some fixed size (say 64k), and that might work well for video with modest overhead (see [inferno](http://securitydriven.net/inferno/) for a similar idea in C#). Such a format would be fairly easy to port to other platforms that already support RNCryptor.
|
||||
|
||||
If there is interest, I may eventually build this as a separate framework.
|
||||
|
||||
## Design Considerations
|
||||
|
||||
`RNCryptor` has several design goals, in order of importance:
|
||||
|
||||
### Easy to use correctly for most common use cases
|
||||
|
||||
The most critical concern is that it be easy for non-experts to use `RNCryptor` correctly. A framework that is more secure, but requires a steep learning curve on the developer will either be not used, or used incorrectly. Whenever possible, a single line of code should "do the right thing" for the most common cases.
|
||||
|
||||
This also requires that it fail correctly and provide good errors.
|
||||
|
||||
### Reliance on CommonCryptor functionality
|
||||
|
||||
`RNCryptor` has very little "security" code. It relies as much as possible on the OS-provided CommonCryptor. If a feature does not exist in CommonCryptor, then it generally will not be provided in `RNCryptor`.
|
||||
|
||||
### Best practice security
|
||||
|
||||
Wherever possible within the above constraints, the best available algorithms
|
||||
are applied. This means AES-256, HMAC+SHA256, and PBKDF2. (Note that several of these decisions were reasonable for v3, but may change for v4.)
|
||||
|
||||
* AES-256. While Bruce Schneier has made some interesting recommendations
|
||||
regarding moving to AES-128 due to certain attacks on AES-256, my current
|
||||
thinking is in line with [Colin
|
||||
Percival](http://www.daemonology.net/blog/2009-07-31-thoughts-on-AES.html).
|
||||
PBKDF2 output is effectively random, which should negate related-keys attacks
|
||||
against the kinds of use cases we're interested in.
|
||||
|
||||
* AES-CBC mode. This was a somewhat complex decision, but the ubiquity of CBC
|
||||
outweighs other considerations here. There are no major problems with CBC mode,
|
||||
and nonce-based modes like CTR have other trade-offs. See ["Mode changes for
|
||||
RNCryptor"](http://robnapier.net/mode-rncryptor) for more details on this
|
||||
decision.
|
||||
|
||||
* Encrypt-then-MAC. If there were a good authenticated AES mode on iOS (GCM for
|
||||
instance), I would probably use that for its simplicity. Colin Percival makes
|
||||
[good arguments for hand-coding an encrypt-than-
|
||||
MAC](http://www.daemonology.net/blog/2009-06-24-encrypt-then-mac.html) rather
|
||||
than using an authenticated AES mode, but in RNCryptor mananging the HMAC
|
||||
actually adds quite a bit of complexity. I'd rather the complexity at a more
|
||||
broadly peer-reviewed layer like CommonCryptor than at the RNCryptor layer. But
|
||||
this isn't an option, so I fall back to my own Encrypt-than-MAC.
|
||||
|
||||
* HMAC+SHA256. No surprises here.
|
||||
|
||||
* PBKDF2. While bcrypt and scrypt may be more secure than PBKDF2, CommonCryptor
|
||||
only supports PBKDF2. [NIST also continues to recommend
|
||||
PBKDF2](http://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage). We use 10k rounds of PBKDF2
|
||||
which represents about 80ms on an iPhone 4.
|
||||
|
||||
### Code simplicity
|
||||
|
||||
RNCryptor endeavors to be implemented as simply as possible, avoiding tricky code. It is designed to be easy to read and code review.
|
||||
|
||||
### Performance
|
||||
|
||||
Performance is a goal, but not the most important goal. The code must be secure
|
||||
and easy to use. Within that, it is as fast and memory-efficient as possible.
|
||||
|
||||
### Portability
|
||||
|
||||
Without sacrificing other goals, it is preferable to read the output format of
|
||||
`RNCryptor` on other platforms.
|
||||
|
||||
## License
|
||||
|
||||
Except where otherwise indicated in the source code, this code is licensed under
|
||||
the MIT License:
|
||||
|
||||
>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 NON-INFRINGEMENT. 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. ```
|
||||
1545
Example/Pods/RNCryptor/RNCryptor.h
generated
Normal file
1545
Example/Pods/RNCryptor/RNCryptor.h
generated
Normal file
File diff suppressed because it is too large
Load Diff
778
Example/Pods/RNCryptor/RNCryptor.swift
generated
Normal file
778
Example/Pods/RNCryptor/RNCryptor.swift
generated
Normal file
@ -0,0 +1,778 @@
|
||||
//
|
||||
// RNCryptor.swift
|
||||
//
|
||||
// Copyright © 2015 Rob Napier. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License:
|
||||
//
|
||||
// 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 NON-INFRINGEMENT. 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 Foundation
|
||||
|
||||
/// The `RNCryptorType` protocol defines generic API to a mutable,
|
||||
/// incremental, password-based encryptor or decryptor. Its generic
|
||||
/// usage is as follows:
|
||||
///
|
||||
/// let cryptor = Encryptor(password: "mypassword")
|
||||
/// // or Decryptor()
|
||||
///
|
||||
/// var result NSMutableData
|
||||
/// for data in datas {
|
||||
/// result.appendData(try cryptor.update(data))
|
||||
/// }
|
||||
/// result.appendData(try cryptor.final())
|
||||
///
|
||||
/// After calling `finalData()`, the cryptor is no longer valid.
|
||||
public protocol RNCryptorType {
|
||||
|
||||
/// Creates and returns a cryptor.
|
||||
///
|
||||
/// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
|
||||
init(password: String)
|
||||
|
||||
/// Updates cryptor with data and returns processed data.
|
||||
///
|
||||
/// - parameter data: Data to process. May be empty.
|
||||
/// - throws: `Error`
|
||||
/// - returns: Processed data. May be empty.
|
||||
func updateWithData(data: NSData) throws -> NSData
|
||||
|
||||
/// Returns trailing data and invalidates the cryptor.
|
||||
///
|
||||
/// - throws: `Error`
|
||||
/// - returns: Trailing data
|
||||
func finalData() throws -> NSData
|
||||
}
|
||||
|
||||
public extension RNCryptorType {
|
||||
/// Simplified, generic interface to `RNCryptorType`. Takes a data,
|
||||
/// returns a processed data. Generally you should use
|
||||
/// `RNCryptor.encryptData(password:)`, or
|
||||
/// `RNCryptor.decryptData(password:)` instead, but this is useful
|
||||
/// for code that is neutral on whether it is encrypting or decrypting.
|
||||
///
|
||||
/// - throws: `Error`
|
||||
private func oneshot(data: NSData) throws -> NSData {
|
||||
let result = NSMutableData(data: try updateWithData(data))
|
||||
result.appendData(try finalData())
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Move this to RNCryptor.Error if @objc can rename it correctly.
|
||||
/// Errors thrown by `RNCryptorType`.
|
||||
@objc public enum RNCryptorError: Int, ErrorType {
|
||||
/// Ciphertext was corrupt or password was incorrect.
|
||||
/// It is not possible to distinguish between these cases in the v3 data format.
|
||||
case HMACMismatch = 1
|
||||
|
||||
/// Unrecognized data format. Usually this means the data is corrupt.
|
||||
case UnknownHeader = 2
|
||||
|
||||
/// `final()` was called before sufficient data was passed to `updateWithData()`
|
||||
case MessageTooShort
|
||||
|
||||
/// Memory allocation failure. This should never happen.
|
||||
case MemoryFailure
|
||||
|
||||
/// A password-based decryptor was used on a key-based ciphertext, or vice-versa.
|
||||
case InvalidCredentialType
|
||||
}
|
||||
|
||||
/// RNCryptor encryption/decryption interface.
|
||||
public class RNCryptor: NSObject {
|
||||
|
||||
/// Encrypt data using password and return encrypted data.
|
||||
public static func encryptData(data: NSData, password: String) -> NSData {
|
||||
return Encryptor(password: password).encryptData(data)
|
||||
}
|
||||
|
||||
/// Decrypt data using password and return decrypted data. Throws if
|
||||
/// password is incorrect or ciphertext is in the wrong format.
|
||||
/// - throws `Error`
|
||||
public static func decryptData(data: NSData, password: String) throws -> NSData {
|
||||
return try Decryptor(password: password).decryptData(data)
|
||||
}
|
||||
|
||||
/// Generates random NSData of given length
|
||||
/// Crashes if `length` is larger than allocatable memory, or if the system random number generator is not available.
|
||||
public static func randomDataOfLength(length: Int) -> NSData {
|
||||
let data = NSMutableData(length: length)!
|
||||
let result = SecRandomCopyBytes(kSecRandomDefault, length, UnsafeMutablePointer<UInt8>(data.mutableBytes))
|
||||
guard result == errSecSuccess else {
|
||||
fatalError("SECURITY FAILURE: Could not generate secure random numbers: \(result).")
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
/// A encryptor for the latest data format. If compatibility with other RNCryptor
|
||||
/// implementations is required, you may wish to use the specific encryptor version rather
|
||||
/// than accepting "latest."
|
||||
///
|
||||
@objc(RNEncryptor)
|
||||
public final class Encryptor: NSObject, RNCryptorType {
|
||||
private let encryptor: EncryptorV3
|
||||
|
||||
/// Creates and returns a cryptor.
|
||||
///
|
||||
/// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
|
||||
public init(password: String) {
|
||||
precondition(password != "")
|
||||
encryptor = EncryptorV3(password: password)
|
||||
}
|
||||
|
||||
/// Updates cryptor with data and returns processed data.
|
||||
///
|
||||
/// - parameter data: Data to process. May be empty.
|
||||
/// - returns: Processed data. May be empty.
|
||||
public func updateWithData(data: NSData) -> NSData {
|
||||
return encryptor.updateWithData(data)
|
||||
}
|
||||
|
||||
/// Returns trailing data and invalidates the cryptor.
|
||||
///
|
||||
/// - returns: Trailing data
|
||||
public func finalData() -> NSData {
|
||||
return encryptor.finalData()
|
||||
}
|
||||
|
||||
/// Simplified, generic interface to `RNCryptorType`. Takes a data,
|
||||
/// returns a processed data, and invalidates the cryptor.
|
||||
public func encryptData(data: NSData) -> NSData {
|
||||
return encryptor.encryptData(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Password-based decryptor that can handle any supported format.
|
||||
@objc(RNDecryptor)
|
||||
public final class Decryptor : NSObject, RNCryptorType {
|
||||
private var decryptors: [VersionedDecryptorType.Type] = [DecryptorV3.self]
|
||||
|
||||
private var buffer = NSMutableData()
|
||||
private var decryptor: RNCryptorType?
|
||||
private let password: String
|
||||
|
||||
/// Creates and returns a cryptor.
|
||||
///
|
||||
/// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
|
||||
public init(password: String) {
|
||||
assert(password != "")
|
||||
self.password = password
|
||||
}
|
||||
|
||||
/// Decrypt data using password and return decrypted data, invalidating decryptor. Throws if
|
||||
/// password is incorrect or ciphertext is in the wrong format.
|
||||
/// - throws `Error`
|
||||
public func decryptData(data: NSData) throws -> NSData {
|
||||
return try oneshot(data)
|
||||
}
|
||||
|
||||
/// Updates cryptor with data and returns processed data.
|
||||
///
|
||||
/// - parameter data: Data to process. May be empty.
|
||||
/// - throws: `Error`
|
||||
/// - returns: Processed data. May be empty.
|
||||
public func updateWithData(data: NSData) throws -> NSData {
|
||||
if let d = decryptor {
|
||||
return try d.updateWithData(data)
|
||||
}
|
||||
|
||||
buffer.appendData(data)
|
||||
|
||||
let toCheck:[VersionedDecryptorType.Type]
|
||||
(toCheck, decryptors) = decryptors.splitPassFail{ self.buffer.length >= $0.preambleSize }
|
||||
|
||||
for decryptorType in toCheck {
|
||||
if decryptorType.canDecrypt(buffer.bytesView[0..<decryptorType.preambleSize]) {
|
||||
let d = decryptorType.init(password: password)
|
||||
decryptor = d
|
||||
let result = try d.updateWithData(buffer)
|
||||
buffer.length = 0
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
guard !decryptors.isEmpty else { throw RNCryptorError.UnknownHeader }
|
||||
return NSData()
|
||||
}
|
||||
|
||||
/// Returns trailing data and invalidates the cryptor.
|
||||
///
|
||||
/// - throws: `Error`
|
||||
/// - returns: Trailing data
|
||||
public func finalData() throws -> NSData {
|
||||
guard let d = decryptor else {
|
||||
throw RNCryptorError.UnknownHeader
|
||||
}
|
||||
return try d.finalData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// V3 implementaion
|
||||
public extension RNCryptor {
|
||||
/// V3 format settings
|
||||
@objc(RNCryptorFormatV3)
|
||||
public final class FormatV3: NSObject {
|
||||
/// Size of AES and HMAC keys
|
||||
public static let keySize = kCCKeySizeAES256
|
||||
|
||||
/// Size of PBKDF2 salt
|
||||
public static let saltSize = 8
|
||||
|
||||
/// Generate a key from a password and salt
|
||||
/// - parameters:
|
||||
/// - password: Password to convert
|
||||
/// - salt: Salt. Generally constructed with RNCryptor.randomDataOfLength(FormatV3.saltSize)
|
||||
/// - returns: Key of length FormatV3.keySize
|
||||
public static func keyForPassword(password: String, salt: NSData) -> NSData {
|
||||
let derivedKey = NSMutableData(length: keySize)!
|
||||
let derivedKeyPtr = UnsafeMutablePointer<UInt8>(derivedKey.mutableBytes)
|
||||
|
||||
let passwordData = password.dataUsingEncoding(NSUTF8StringEncoding)!
|
||||
let passwordPtr = UnsafePointer<Int8>(passwordData.bytes)
|
||||
|
||||
let saltPtr = UnsafePointer<UInt8>(salt.bytes)
|
||||
|
||||
// All the crazy casting because CommonCryptor hates Swift
|
||||
let algorithm = CCPBKDFAlgorithm(kCCPBKDF2)
|
||||
let prf = CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1)
|
||||
let pbkdf2Rounds = UInt32(10000)
|
||||
|
||||
let result = CCKeyDerivationPBKDF(
|
||||
algorithm,
|
||||
passwordPtr, passwordData.length,
|
||||
saltPtr, salt.length,
|
||||
prf, pbkdf2Rounds,
|
||||
derivedKeyPtr, derivedKey.length)
|
||||
|
||||
guard result == CCCryptorStatus(kCCSuccess) else {
|
||||
fatalError("SECURITY FAILURE: Could not derive secure password (\(result)): \(derivedKey).")
|
||||
}
|
||||
return derivedKey
|
||||
}
|
||||
|
||||
static let formatVersion = UInt8(3)
|
||||
static let ivSize = kCCBlockSizeAES128
|
||||
static let hmacSize = Int(CC_SHA256_DIGEST_LENGTH)
|
||||
static let keyHeaderSize = 1 + 1 + kCCBlockSizeAES128
|
||||
static let passwordHeaderSize = 1 + 1 + 8 + 8 + kCCBlockSizeAES128
|
||||
}
|
||||
|
||||
/// Format version 3 encryptor. Use this to ensure a specific format verison
|
||||
/// or when using keys (which are inherrently versions-specific). To use
|
||||
/// "the latest encryptor" with a password, use `Encryptor` instead.
|
||||
@objc(RNEncryptorV3)
|
||||
public final class EncryptorV3 : NSObject, RNCryptorType {
|
||||
private var engine: Engine
|
||||
private var hmac: HMACV3
|
||||
private var pendingHeader: NSData?
|
||||
|
||||
/// Creates and returns an encryptor.
|
||||
///
|
||||
/// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
|
||||
public convenience init(password: String) {
|
||||
self.init(
|
||||
password: password,
|
||||
encryptionSalt: RNCryptor.randomDataOfLength(V3.saltSize),
|
||||
hmacSalt: RNCryptor.randomDataOfLength(V3.saltSize),
|
||||
iv: RNCryptor.randomDataOfLength(V3.ivSize))
|
||||
}
|
||||
|
||||
/// Creates and returns an encryptor using keys.
|
||||
///
|
||||
/// - Attention: This method requires some expertise to use correctly.
|
||||
/// Most users should use `init(password:)` which is simpler
|
||||
/// to use securely.
|
||||
///
|
||||
/// Keys should not be generated directly from strings (`.dataUsingEncoding()` or similar).
|
||||
/// Ideally, keys should be random (`Cryptor.randomDataOfLength()` or some other high-quality
|
||||
/// random generator. If keys must be generated from strings, then use `FormatV3.keyForPassword(salt:)`
|
||||
/// with a random salt, or just use password-based encryption (that's what it's for).
|
||||
///
|
||||
/// - parameters:
|
||||
/// - encryptionKey: AES-256 key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
|
||||
/// - hmacKey: HMAC key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
|
||||
public convenience init(encryptionKey: NSData, hmacKey: NSData) {
|
||||
self.init(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: RNCryptor.randomDataOfLength(V3.ivSize))
|
||||
}
|
||||
|
||||
/// Takes a data, returns a processed data, and invalidates the cryptor.
|
||||
public func encryptData(data: NSData) -> NSData {
|
||||
return try! oneshot(data)
|
||||
}
|
||||
|
||||
/// Updates cryptor with data and returns encrypted data.
|
||||
///
|
||||
/// - parameter data: Data to process. May be empty.
|
||||
/// - returns: Processed data. May be empty.
|
||||
public func updateWithData(data: NSData) -> NSData {
|
||||
// It should not be possible for this to fail during encryption
|
||||
return handle(engine.updateWithData(data))
|
||||
}
|
||||
|
||||
/// Returns trailing data and invalidates the cryptor.
|
||||
///
|
||||
/// - returns: Trailing data
|
||||
public func finalData() -> NSData {
|
||||
let result = NSMutableData(data: handle(engine.finalData()))
|
||||
result.appendData(hmac.finalData())
|
||||
return result
|
||||
}
|
||||
|
||||
// Expose random numbers for testing
|
||||
internal convenience init(encryptionKey: NSData, hmacKey: NSData, iv: NSData) {
|
||||
let preamble = [V3.formatVersion, UInt8(0)]
|
||||
let header = NSMutableData(bytes: preamble, length: preamble.count)
|
||||
header.appendData(iv)
|
||||
self.init(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
|
||||
}
|
||||
|
||||
// Expose random numbers for testing
|
||||
internal convenience init(password: String, encryptionSalt: NSData, hmacSalt: NSData, iv: NSData) {
|
||||
let encryptionKey = V3.keyForPassword(password, salt: encryptionSalt)
|
||||
let hmacKey = V3.keyForPassword(password, salt: hmacSalt)
|
||||
|
||||
// TODO: This chained-+ is very slow to compile in Swift 2b5 (http://www.openradar.me/21842206)
|
||||
// let header = [V3.version, UInt8(1)] + encryptionSalt + hmacSalt + iv
|
||||
let preamble = [V3.formatVersion, UInt8(1)]
|
||||
let header = NSMutableData(bytes: preamble, length: preamble.count)
|
||||
header.appendData(encryptionSalt)
|
||||
header.appendData(hmacSalt)
|
||||
header.appendData(iv)
|
||||
|
||||
self.init(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
|
||||
}
|
||||
|
||||
private init(encryptionKey: NSData, hmacKey: NSData, iv: NSData, header: NSData) {
|
||||
precondition(encryptionKey.length == V3.keySize)
|
||||
precondition(hmacKey.length == V3.keySize)
|
||||
precondition(iv.length == V3.ivSize)
|
||||
hmac = HMACV3(key: hmacKey)
|
||||
engine = Engine(operation: .Encrypt, key: encryptionKey, iv: iv)
|
||||
pendingHeader = header
|
||||
}
|
||||
|
||||
private func handle(data: NSData) -> NSData {
|
||||
var result: NSData
|
||||
if let ph = pendingHeader {
|
||||
let accum = NSMutableData(data: ph)
|
||||
pendingHeader = nil
|
||||
accum.appendData(data)
|
||||
result = accum
|
||||
} else {
|
||||
result = data
|
||||
}
|
||||
hmac.updateWithData(result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/// Format version 3 decryptor. This is required in order to decrypt
|
||||
/// using keys (since key configuration is version-specific). For password
|
||||
/// decryption, `Decryptor` is generally preferred, and will call this
|
||||
/// if appropriate.
|
||||
@objc(RNDecryptorV3)
|
||||
public final class DecryptorV3: NSObject, VersionedDecryptorType {
|
||||
//
|
||||
// Static methods
|
||||
//
|
||||
private static let preambleSize = 1
|
||||
private static func canDecrypt(preamble: NSData) -> Bool {
|
||||
assert(preamble.length >= 1)
|
||||
return preamble.bytesView[0] == 3
|
||||
}
|
||||
|
||||
//
|
||||
// Private properties
|
||||
//
|
||||
private var buffer = NSMutableData()
|
||||
private var decryptorEngine: DecryptorEngineV3?
|
||||
private let credential: Credential
|
||||
|
||||
|
||||
/// Creates and returns a decryptor.
|
||||
///
|
||||
/// - parameter password: Non-empty password string. This will be interpretted as UTF-8.
|
||||
public init(password: String) {
|
||||
credential = .Password(password)
|
||||
}
|
||||
|
||||
/// Creates and returns a decryptor using keys.
|
||||
///
|
||||
/// - parameters:
|
||||
/// - encryptionKey: AES-256 key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
|
||||
/// - hmacKey: HMAC key. Must be exactly FormatV3.keySize (kCCKeySizeAES256, 32 bytes)
|
||||
public init(encryptionKey: NSData, hmacKey: NSData) {
|
||||
precondition(encryptionKey.length == V3.keySize)
|
||||
precondition(hmacKey.length == V3.hmacSize)
|
||||
credential = .Keys(encryptionKey: encryptionKey, hmacKey: hmacKey)
|
||||
}
|
||||
|
||||
/// Decrypt data using password and return decrypted data. Throws if
|
||||
/// password is incorrect or ciphertext is in the wrong format.
|
||||
/// - throws `Error`
|
||||
public func decryptData(data: NSData) throws -> NSData {
|
||||
return try oneshot(data)
|
||||
}
|
||||
|
||||
/// Updates cryptor with data and returns encrypted data.
|
||||
///
|
||||
/// - parameter data: Data to process. May be empty.
|
||||
/// - returns: Processed data. May be empty.
|
||||
public func updateWithData(data: NSData) throws -> NSData {
|
||||
if let e = decryptorEngine {
|
||||
return e.updateWithData(data)
|
||||
}
|
||||
|
||||
buffer.appendData(data)
|
||||
guard buffer.length >= requiredHeaderSize else {
|
||||
return NSData()
|
||||
}
|
||||
|
||||
let e = try createEngineWithCredential(credential, header: buffer.bytesView[0..<requiredHeaderSize])
|
||||
decryptorEngine = e
|
||||
let body = buffer.bytesView[requiredHeaderSize..<buffer.length]
|
||||
buffer.length = 0
|
||||
return e.updateWithData(body)
|
||||
}
|
||||
|
||||
/// Returns trailing data and invalidates the cryptor.
|
||||
///
|
||||
/// - returns: Trailing data
|
||||
public func finalData() throws -> NSData {
|
||||
guard let result = try decryptorEngine?.finalData() else {
|
||||
throw RNCryptorError.MessageTooShort
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//
|
||||
// Private functions
|
||||
//
|
||||
|
||||
private var requiredHeaderSize: Int {
|
||||
switch credential {
|
||||
case .Password(_): return V3.passwordHeaderSize
|
||||
case .Keys(_, _): return V3.keyHeaderSize
|
||||
}
|
||||
}
|
||||
|
||||
private func createEngineWithCredential(credential: Credential, header: NSData) throws -> DecryptorEngineV3 {
|
||||
switch credential {
|
||||
case let .Password(password):
|
||||
return try createEngineWithPassword(password, header: header)
|
||||
case let .Keys(encryptionKey, hmacKey):
|
||||
return try createEngineWithKeys(encryptionKey: encryptionKey, hmacKey: hmacKey, header: header)
|
||||
}
|
||||
}
|
||||
|
||||
private func createEngineWithPassword(password: String, header: NSData) throws -> DecryptorEngineV3 {
|
||||
assert(password != "")
|
||||
precondition(header.length == V3.passwordHeaderSize)
|
||||
|
||||
guard DecryptorV3.canDecrypt(header) else {
|
||||
throw RNCryptorError.UnknownHeader
|
||||
}
|
||||
|
||||
guard header.bytesView[1] == 1 else {
|
||||
throw RNCryptorError.InvalidCredentialType
|
||||
}
|
||||
|
||||
let encryptionSalt = header.bytesView[2...9]
|
||||
let hmacSalt = header.bytesView[10...17]
|
||||
let iv = header.bytesView[18...33]
|
||||
|
||||
let encryptionKey = V3.keyForPassword(password, salt: encryptionSalt)
|
||||
let hmacKey = V3.keyForPassword(password, salt: hmacSalt)
|
||||
|
||||
return DecryptorEngineV3(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
|
||||
}
|
||||
|
||||
private func createEngineWithKeys(encryptionKey encryptionKey: NSData, hmacKey: NSData, header: NSData) throws -> DecryptorEngineV3 {
|
||||
precondition(header.length == V3.keyHeaderSize)
|
||||
precondition(encryptionKey.length == V3.keySize)
|
||||
precondition(hmacKey.length == V3.keySize)
|
||||
|
||||
guard DecryptorV3.canDecrypt(header) else {
|
||||
throw RNCryptorError.UnknownHeader
|
||||
}
|
||||
|
||||
guard header.bytesView[1] == 0 else {
|
||||
throw RNCryptorError.InvalidCredentialType
|
||||
}
|
||||
|
||||
let iv = header.bytesView[2..<18]
|
||||
return DecryptorEngineV3(encryptionKey: encryptionKey, hmacKey: hmacKey, iv: iv, header: header)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal enum CryptorOperation: CCOperation {
|
||||
case Encrypt = 0 // CCOperation(kCCEncrypt)
|
||||
case Decrypt = 1 // CCOperation(kCCDecrypt)
|
||||
}
|
||||
|
||||
internal final class Engine {
|
||||
private let cryptor: CCCryptorRef
|
||||
private var buffer = NSMutableData()
|
||||
|
||||
init(operation: CryptorOperation, key: NSData, iv: NSData) {
|
||||
var cryptorOut = CCCryptorRef()
|
||||
let result = CCCryptorCreate(
|
||||
operation.rawValue,
|
||||
CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding),
|
||||
key.bytes, key.length,
|
||||
iv.bytes,
|
||||
&cryptorOut
|
||||
)
|
||||
cryptor = cryptorOut
|
||||
|
||||
// It is a programming error to create us with illegal values
|
||||
// This is an internal class, so we can constrain what is sent to us.
|
||||
// If this is ever made public, it should throw instead of asserting.
|
||||
assert(result == CCCryptorStatus(kCCSuccess))
|
||||
}
|
||||
|
||||
deinit {
|
||||
if cryptor != CCCryptorRef() {
|
||||
CCCryptorRelease(cryptor)
|
||||
}
|
||||
}
|
||||
|
||||
func sizeBufferForDataOfLength(length: Int) -> Int {
|
||||
let size = CCCryptorGetOutputLength(cryptor, length, true)
|
||||
buffer.length = size
|
||||
return size
|
||||
}
|
||||
|
||||
func updateWithData(data: NSData) -> NSData {
|
||||
let outputLength = sizeBufferForDataOfLength(data.length)
|
||||
var dataOutMoved: Int = 0
|
||||
|
||||
let result = CCCryptorUpdate(
|
||||
cryptor,
|
||||
data.bytes, data.length,
|
||||
buffer.mutableBytes, outputLength,
|
||||
&dataOutMoved)
|
||||
|
||||
// The only error returned by CCCryptorUpdate is kCCBufferTooSmall, which would be a programming error
|
||||
assert(result == CCCryptorStatus(kCCSuccess), "RNCRYPTOR BUG. PLEASE REPORT.")
|
||||
|
||||
buffer.length = dataOutMoved
|
||||
return buffer
|
||||
}
|
||||
|
||||
func finalData() -> NSData {
|
||||
let outputLength = sizeBufferForDataOfLength(0)
|
||||
var dataOutMoved: Int = 0
|
||||
|
||||
let result = CCCryptorFinal(
|
||||
cryptor,
|
||||
buffer.mutableBytes, outputLength,
|
||||
&dataOutMoved
|
||||
)
|
||||
|
||||
// Note that since iOS 6, CCryptor will never return padding errors or other decode errors.
|
||||
// I'm not aware of any non-catestrophic (MemoryAllocation) situation in which this
|
||||
// can fail. Using assert() just in case, but we'll ignore errors in Release.
|
||||
// https://devforums.apple.com/message/920802#920802
|
||||
assert(result == CCCryptorStatus(kCCSuccess), "RNCRYPTOR BUG. PLEASE REPORT.")
|
||||
|
||||
buffer.length = dataOutMoved
|
||||
return buffer
|
||||
}
|
||||
}
|
||||
|
||||
internal typealias V3 = RNCryptor.FormatV3
|
||||
|
||||
private enum Credential {
|
||||
case Password(String)
|
||||
case Keys(encryptionKey: NSData, hmacKey: NSData)
|
||||
}
|
||||
|
||||
private final class DecryptorEngineV3 {
|
||||
private let buffer = OverflowingBuffer(capacity: V3.hmacSize)
|
||||
private var hmac: HMACV3
|
||||
private var engine: Engine
|
||||
|
||||
init(encryptionKey: NSData, hmacKey: NSData, iv: NSData, header: NSData) {
|
||||
precondition(encryptionKey.length == V3.keySize)
|
||||
precondition(hmacKey.length == V3.hmacSize)
|
||||
precondition(iv.length == V3.ivSize)
|
||||
|
||||
hmac = HMACV3(key: hmacKey)
|
||||
hmac.updateWithData(header)
|
||||
engine = Engine(operation: .Decrypt, key: encryptionKey, iv: iv)
|
||||
}
|
||||
|
||||
func updateWithData(data: NSData) -> NSData {
|
||||
let overflow = buffer.updateWithData(data)
|
||||
hmac.updateWithData(overflow)
|
||||
return engine.updateWithData(overflow)
|
||||
}
|
||||
|
||||
func finalData() throws -> NSData {
|
||||
let result = engine.finalData()
|
||||
let hash = hmac.finalData()
|
||||
if !isEqualInConsistentTime(trusted: hash, untrusted: buffer.finalData()) {
|
||||
throw RNCryptorError.HMACMismatch
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private final class HMACV3 {
|
||||
var context: CCHmacContext = CCHmacContext()
|
||||
|
||||
init(key: NSData) {
|
||||
CCHmacInit(
|
||||
&context,
|
||||
CCHmacAlgorithm(kCCHmacAlgSHA256),
|
||||
key.bytes,
|
||||
key.length
|
||||
)
|
||||
}
|
||||
|
||||
func updateWithData(data: NSData) {
|
||||
CCHmacUpdate(&context, data.bytes, data.length)
|
||||
}
|
||||
|
||||
func finalData() -> NSData {
|
||||
let hmac = NSMutableData(length: V3.hmacSize)!
|
||||
CCHmacFinal(&context, hmac.mutableBytes)
|
||||
return hmac
|
||||
}
|
||||
}
|
||||
|
||||
// Internal protocol for version-specific decryptors.
|
||||
private protocol VersionedDecryptorType: RNCryptorType {
|
||||
static var preambleSize: Int { get }
|
||||
static func canDecrypt(preamble: NSData) -> Bool
|
||||
init(password: String)
|
||||
}
|
||||
|
||||
private extension CollectionType {
|
||||
// Split collection into ([pass], [fail]) based on predicate.
|
||||
func splitPassFail(pred: Generator.Element -> Bool) -> ([Generator.Element], [Generator.Element]) {
|
||||
var pass: [Generator.Element] = []
|
||||
var fail: [Generator.Element] = []
|
||||
for e in self {
|
||||
if pred(e) {
|
||||
pass.append(e)
|
||||
} else {
|
||||
fail.append(e)
|
||||
}
|
||||
}
|
||||
return (pass, fail)
|
||||
}
|
||||
}
|
||||
|
||||
internal class OverflowingBuffer {
|
||||
private var buffer = NSMutableData()
|
||||
let capacity: Int
|
||||
|
||||
init(capacity: Int) {
|
||||
self.capacity = capacity
|
||||
}
|
||||
|
||||
@warn_unused_result
|
||||
func updateWithData(data: NSData) -> NSData {
|
||||
if data.length >= capacity {
|
||||
return sendAllArray(data)
|
||||
} else if buffer.length + data.length <= capacity {
|
||||
buffer.appendData(data)
|
||||
return NSData()
|
||||
} else {
|
||||
return sendSomeArray(data)
|
||||
}
|
||||
}
|
||||
|
||||
func finalData() -> NSData {
|
||||
let result = buffer
|
||||
buffer = NSMutableData() // Data belongs to caller now.
|
||||
return result
|
||||
}
|
||||
|
||||
private func sendAllArray(data: NSData) -> NSData {
|
||||
let toSend = data.length - capacity
|
||||
assert(toSend >= 0)
|
||||
assert(data.length - toSend <= capacity)
|
||||
|
||||
let result = NSMutableData(data: buffer)
|
||||
result.appendData(data.bytesView[0..<toSend])
|
||||
buffer.length = 0
|
||||
buffer.appendData(data.bytesView[toSend..<data.length])
|
||||
return result
|
||||
}
|
||||
|
||||
private func sendSomeArray(data: NSData) -> NSData {
|
||||
let toSend = (buffer.length + data.length) - capacity
|
||||
assert(toSend > 0) // If it were <= 0, we would have extended the array
|
||||
assert(toSend < buffer.length) // If we would have sent everything, replaceBuffer should have been called
|
||||
|
||||
let result = buffer.bytesView[0..<toSend]
|
||||
buffer.replaceBytesInRange(NSRange(0..<toSend), withBytes: nil, length: 0)
|
||||
buffer.appendData(data)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private extension NSData {
|
||||
var bytesView: BytesView { return BytesView(self) }
|
||||
}
|
||||
|
||||
private struct BytesView: CollectionType {
|
||||
let data: NSData
|
||||
init(_ data: NSData) { self.data = data }
|
||||
|
||||
subscript (position: Int) -> UInt8 {
|
||||
return UnsafePointer<UInt8>(data.bytes)[position]
|
||||
}
|
||||
subscript (bounds: Range<Int>) -> NSData {
|
||||
return data.subdataWithRange(NSRange(bounds))
|
||||
}
|
||||
var startIndex: Int = 0
|
||||
var endIndex: Int { return data.length }
|
||||
}
|
||||
|
||||
/** Compare two NSData in time proportional to the untrusted data
|
||||
|
||||
Equatable-based comparisons genreally stop comparing at the first difference.
|
||||
This can be used by attackers, in some situations,
|
||||
to determine a secret value by considering the time required to compare the values.
|
||||
|
||||
We enumerate over the untrusted values so that the time is proportaional to the attacker's data,
|
||||
which provides the attack no informatoin about the length of the secret.
|
||||
*/
|
||||
private func isEqualInConsistentTime(trusted trusted: NSData, untrusted: NSData) -> Bool {
|
||||
// The point of this routine is XOR the bytes of each data and accumulate the results with OR.
|
||||
// If any bytes are different, then the OR will accumulate some non-0 value.
|
||||
|
||||
var result: UInt8 = untrusted.length == trusted.length ? 0 : 1 // Start with 0 (equal) only if our lengths are equal
|
||||
for (i, untrustedByte) in untrusted.bytesView.enumerate() {
|
||||
// Use mod to wrap around ourselves if they are longer than we are.
|
||||
// Remember, we already broke equality if our lengths are different.
|
||||
result |= trusted.bytesView[i % trusted.length] ^ untrustedByte
|
||||
}
|
||||
|
||||
return result == 0
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.3.6</string>
|
||||
<string>0.3.7</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#import "PNAddress.h"
|
||||
#import "PNInstallation.h"
|
||||
#import "PNLocation.h"
|
||||
#import "PNObjcPassword.h"
|
||||
#import "PNUser.h"
|
||||
#import "PNObject+PNObjectConnection.h"
|
||||
#import "PNObject+Protected.h"
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.3.6</string>
|
||||
<string>0.3.7</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@ -249,6 +249,30 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
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.
|
||||
|
||||
|
||||
## RNCryptor
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rob Napier
|
||||
|
||||
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.
|
||||
|
||||
## StrongestPasswordValidator
|
||||
|
||||
Copyright (c) 2016 Giuseppe Nucifora <me@giuseppenucifora.com>
|
||||
|
||||
@ -304,6 +304,34 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rob Napier
|
||||
|
||||
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.</string>
|
||||
<key>Title</key>
|
||||
<string>RNCryptor</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2016 Giuseppe Nucifora <me@giuseppenucifora.com>
|
||||
|
||||
@ -95,6 +95,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "Pods-PNObject_Example/PEAR_FileManager_iOS.framework"
|
||||
install_framework "Pods-PNObject_Example/PNObject.framework"
|
||||
install_framework "Pods-PNObject_Example/PureLayout.framework"
|
||||
install_framework "Pods-PNObject_Example/RNCryptor.framework"
|
||||
install_framework "Pods-PNObject_Example/StrongestPasswordValidator.framework"
|
||||
install_framework "Pods-PNObject_Example/UIDevice_Utils.framework"
|
||||
install_framework "Pods-PNObject_Example/nv_ios_http_status.framework"
|
||||
@ -111,6 +112,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "Pods-PNObject_Example/PEAR_FileManager_iOS.framework"
|
||||
install_framework "Pods-PNObject_Example/PNObject.framework"
|
||||
install_framework "Pods-PNObject_Example/PureLayout.framework"
|
||||
install_framework "Pods-PNObject_Example/RNCryptor.framework"
|
||||
install_framework "Pods-PNObject_Example/StrongestPasswordValidator.framework"
|
||||
install_framework "Pods-PNObject_Example/UIDevice_Utils.framework"
|
||||
install_framework "Pods-PNObject_Example/nv_ios_http_status.framework"
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RNCryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "RNCryptor" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_FRAMEWORK_BUILD_PATH = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Example"
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PureLayout.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RNCryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "PureLayout" -framework "RNCryptor" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_FRAMEWORK_BUILD_PATH = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Example"
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
@ -236,6 +236,30 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
## RNCryptor
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rob Napier
|
||||
|
||||
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.
|
||||
|
||||
## StrongestPasswordValidator
|
||||
|
||||
Copyright (c) 2016 Giuseppe Nucifora <me@giuseppenucifora.com>
|
||||
|
||||
@ -287,6 +287,34 @@ THE SOFTWARE.
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rob Napier
|
||||
|
||||
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.</string>
|
||||
<key>Title</key>
|
||||
<string>RNCryptor</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2016 Giuseppe Nucifora <me@giuseppenucifora.com>
|
||||
|
||||
@ -94,6 +94,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "Pods-PNObject_Tests/NSString_Helper.framework"
|
||||
install_framework "Pods-PNObject_Tests/PEAR_FileManager_iOS.framework"
|
||||
install_framework "Pods-PNObject_Tests/PNObject.framework"
|
||||
install_framework "Pods-PNObject_Tests/RNCryptor.framework"
|
||||
install_framework "Pods-PNObject_Tests/StrongestPasswordValidator.framework"
|
||||
install_framework "Pods-PNObject_Tests/UIDevice_Utils.framework"
|
||||
install_framework "Pods-PNObject_Tests/nv_ios_http_status.framework"
|
||||
@ -113,6 +114,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "Pods-PNObject_Tests/NSString_Helper.framework"
|
||||
install_framework "Pods-PNObject_Tests/PEAR_FileManager_iOS.framework"
|
||||
install_framework "Pods-PNObject_Tests/PNObject.framework"
|
||||
install_framework "Pods-PNObject_Tests/RNCryptor.framework"
|
||||
install_framework "Pods-PNObject_Tests/StrongestPasswordValidator.framework"
|
||||
install_framework "Pods-PNObject_Tests/UIDevice_Utils.framework"
|
||||
install_framework "Pods-PNObject_Tests/nv_ios_http_status.framework"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RNCryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "RNCryptor" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_FRAMEWORK_BUILD_PATH = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Tests"
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/AFNetworking.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Bolts.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/CodFis_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Expecta_Snapshots.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKCoreKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKLoginKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSDKShareKit.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/FBSnapshotTestCase.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSDate_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/NSString_Helper.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PEAR_FileManager_iOS.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/PNObject.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/RNCryptor.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/Specta.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/StrongestPasswordValidator.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/UIDevice_Utils.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/nv_ios_http_status.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "Bolts" -framework "CodFis_Helper" -framework "Expecta" -framework "Expecta_Snapshots" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "FBSDKShareKit" -framework "FBSnapshotTestCase" -framework "NSDate_Utils" -framework "NSString_Helper" -framework "PEAR_FileManager_iOS" -framework "PNObject" -framework "RNCryptor" -framework "Specta" -framework "StrongestPasswordValidator" -framework "UIDevice_Utils" -framework "nv_ios_http_status"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_FRAMEWORK_BUILD_PATH = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-PNObject_Tests"
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
|
||||
26
Example/Pods/Target Support Files/RNCryptor/Info.plist
generated
Normal file
26
Example/Pods/Target Support Files/RNCryptor/Info.plist
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${CURRENT_PROJECT_VERSION}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
5
Example/Pods/Target Support Files/RNCryptor/RNCryptor-dummy.m
generated
Normal file
5
Example/Pods/Target Support Files/RNCryptor/RNCryptor-dummy.m
generated
Normal file
@ -0,0 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_RNCryptor : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_RNCryptor
|
||||
@end
|
||||
4
Example/Pods/Target Support Files/RNCryptor/RNCryptor-prefix.pch
generated
Normal file
4
Example/Pods/Target Support Files/RNCryptor/RNCryptor-prefix.pch
generated
Normal file
@ -0,0 +1,4 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
7
Example/Pods/Target Support Files/RNCryptor/RNCryptor-umbrella.h
generated
Normal file
7
Example/Pods/Target Support Files/RNCryptor/RNCryptor-umbrella.h
generated
Normal file
@ -0,0 +1,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RNCryptor.h"
|
||||
|
||||
FOUNDATION_EXPORT double RNCryptorVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char RNCryptorVersionString[];
|
||||
|
||||
6
Example/Pods/Target Support Files/RNCryptor/RNCryptor.modulemap
generated
Normal file
6
Example/Pods/Target Support Files/RNCryptor/RNCryptor.modulemap
generated
Normal file
@ -0,0 +1,6 @@
|
||||
framework module RNCryptor {
|
||||
umbrella header "RNCryptor-umbrella.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
6
Example/Pods/Target Support Files/RNCryptor/RNCryptor.xcconfig
generated
Normal file
6
Example/Pods/Target Support Files/RNCryptor/RNCryptor.xcconfig
generated
Normal file
@ -0,0 +1,6 @@
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
@ -46,6 +46,7 @@ s.dependency 'StrongestPasswordValidator'
|
||||
s.dependency 'FBSDKCoreKit'
|
||||
s.dependency 'FBSDKShareKit'
|
||||
s.dependency 'FBSDKLoginKit'
|
||||
s.dependency 'RNCryptor'
|
||||
|
||||
|
||||
end
|
||||
|
||||
30
Pod/Classes/PNClasses/PNObjcPassword.h
Normal file
30
Pod/Classes/PNClasses/PNObjcPassword.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// PNObjcPassword.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Giuseppe Nucifora on 13/01/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import "PNObject.h"
|
||||
|
||||
@interface PNObjcPassword : PNObject <PNObjectSubclassing>
|
||||
|
||||
+ (BOOL) validateMinimumRequirenment:(NSString * _Nullable) passString;
|
||||
|
||||
- (BOOL) isValid;
|
||||
|
||||
///--------------------------------------
|
||||
#pragma mark - PNObjcPassword Properties
|
||||
///--------------------------------------
|
||||
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSString *password;
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSString *confirmPassword;
|
||||
|
||||
@end
|
||||
81
Pod/Classes/PNClasses/PNObjcPassword.m
Normal file
81
Pod/Classes/PNClasses/PNObjcPassword.m
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// PNObjcPassword.m
|
||||
// Pods
|
||||
//
|
||||
// Created by Giuseppe Nucifora on 13/01/16.
|
||||
//
|
||||
//
|
||||
|
||||
#import "PNObjcPassword.h"
|
||||
#import "PNUser.h"
|
||||
#import "PNObjectConstants.h"
|
||||
|
||||
@implementation PNObjcPassword
|
||||
|
||||
+ (NSString *) objectClassName {
|
||||
return @"Password";
|
||||
}
|
||||
|
||||
+(NSString *)objectEndPoint {
|
||||
return @"Password";
|
||||
}
|
||||
|
||||
+ (NSDictionary *) objcetMapping {
|
||||
NSDictionary *mapping = @{@"password":@"password",
|
||||
@"confirmPassword":@"confirmPassword",
|
||||
};
|
||||
return mapping;
|
||||
}
|
||||
|
||||
+ (BOOL)singleInstance {
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void) setPassword:(NSString *)password {
|
||||
if ([self validateMinimumRequirenment:password]) {
|
||||
_password = password;
|
||||
}
|
||||
else {
|
||||
NSLogDebug(@"Inserted Passord is not valid.Lenght must be >= %ld",(long)[[PNObjectConfig sharedInstance] minPasswordLenght]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setConfirmPassword:(NSString *)confirmPassword {
|
||||
if ([self validateMinimumRequirenment:confirmPassword]) {
|
||||
if ([confirmPassword isEqualToString:_password]) {
|
||||
_confirmPassword = confirmPassword;
|
||||
}
|
||||
else {
|
||||
NSLogDebug(@"Inserted Passord is not same password.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
NSLogDebug(@"Inserted Passord is not valid.Lenght must be >= %ld",(long)[[PNObjectConfig sharedInstance] minPasswordLenght]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isValid {
|
||||
if ([self validateMinimumRequirenment:_password] && [self validateMinimumRequirenment:_confirmPassword] && [_confirmPassword isEqualToString:_password]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) validateMinimumRequirenment:(NSString * _Nullable) passString {
|
||||
if ([passString length] >= [[PNObjectConfig sharedInstance] minPasswordLenght]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL) validateMinimumRequirenment:(NSString * _Nullable) passString {
|
||||
if ([passString length] >= [[PNObjectConfig sharedInstance] minPasswordLenght]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "PNObject.h"
|
||||
#import "PNObjcPassword.h"
|
||||
|
||||
@interface PNUser : PNObject
|
||||
|
||||
@ -33,15 +34,6 @@
|
||||
*/
|
||||
+ (BOOL) isValidPassword:(NSString* _Nonnull) password;
|
||||
|
||||
/**
|
||||
* <#Description#>
|
||||
*
|
||||
* @param password <#password description#>
|
||||
*
|
||||
* @return <#return value description#>
|
||||
*/
|
||||
- (BOOL) isValidPassword:(NSString* _Nonnull) password;
|
||||
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@ -159,11 +151,7 @@
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSString * password;
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSString * confirmPassword;
|
||||
@property (nonatomic, strong, nullable) PNObjcPassword * password;
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@ -184,6 +172,9 @@
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSString * facebookAccessToken;
|
||||
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) NSDate * registeredAt;
|
||||
|
||||
@end
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||
#import <FBSDKLoginKit/FBSDKLoginKit.h>
|
||||
#import <FBSDKShareKit/FBSDKShareKit.h>
|
||||
#import "PNObjcPassword.h"
|
||||
|
||||
|
||||
@interface PNUser() <PNObjectSubclassing>
|
||||
@ -98,56 +99,23 @@ static bool isFirstAccess = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setPassword:(NSString *)password {
|
||||
if ([self isValidPassword:password]) {
|
||||
_password = password;
|
||||
}
|
||||
else {
|
||||
NSLogDebug(@"Inserted Passord is not valid.Lenght must be >= %ld",(long)[[PNObjectConfig sharedInstance] minPasswordLenght]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setConfirmPassword:(NSString *)confirmPassword {
|
||||
if ([self isValidPassword:confirmPassword]) {
|
||||
if ([confirmPassword isEqualToString:_password]) {
|
||||
_confirmPassword = confirmPassword;
|
||||
}
|
||||
else {
|
||||
NSLogDebug(@"Inserted Passord is not same password.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
NSLogDebug(@"Inserted Passord is not valid.Lenght must be >= %ld",(long)[[PNObjectConfig sharedInstance] minPasswordLenght]);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) isValidPassword:(NSString* _Nonnull) password {
|
||||
if ([password length] >= [[PNObjectConfig sharedInstance] minPasswordLenght]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL) isValidPassword:(NSString* _Nonnull) password {
|
||||
if ([password length] >= [[PNObjectConfig sharedInstance] minPasswordLenght]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)logout {
|
||||
[self autoRemoveLocally];
|
||||
[self resetObject];
|
||||
}
|
||||
|
||||
- (BOOL) hasValidEmailAndPasswordData {
|
||||
if(self.email && [self.email isValidEmail] && self.password && [self isValidPassword:[self password]]){
|
||||
if(self.email && [self.email isValidEmail] && self.password && [self.password isValid]){
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL) isValidPassword:(NSString* _Nonnull) password {
|
||||
return [PNObjcPassword validateMinimumRequirenment:password];
|
||||
}
|
||||
|
||||
- (void) autoLogin {
|
||||
[self autoLoginWithBlockSuccess:nil failure:nil];
|
||||
}
|
||||
@ -300,10 +268,13 @@ static bool isFirstAccess = YES;
|
||||
|
||||
[[PNObjectConfig sharedInstance] refreshTokenForUserWithEmail:email password:password withBlockSuccess:^(BOOL refreshSuccess) {
|
||||
if (refreshSuccess) {
|
||||
PNObjcPassword *objectPassword = [PNObjcPassword new];
|
||||
[objectPassword setPassword:password];
|
||||
[objectPassword setConfirmPassword:password];
|
||||
|
||||
[self setAuthenticated:YES];
|
||||
[self setEmail:email];
|
||||
[self setPassword:password];
|
||||
[self setConfirmPassword:password];
|
||||
[self setPassword:objectPassword];
|
||||
[self saveLocally];
|
||||
|
||||
if (success) {
|
||||
@ -331,8 +302,7 @@ static bool isFirstAccess = YES;
|
||||
@"sex":@"sex",
|
||||
@"birthDate":@"birthDate",
|
||||
@"phone":@"phone",
|
||||
@"password":@"plainPassword[first]",
|
||||
@"confirmPassword":@"plainPassword[second]",
|
||||
@"password":@{@"key":@"password",@"type":@"PNObjcPassword"},
|
||||
@"hasAcceptedPrivacy":@"hasAcceptedPrivacy",
|
||||
@"hasAcceptedNewsletter":@"hasAcceptedNewsletter",
|
||||
@"hasVerifiedEmail":@"hasVerifiedEmail",
|
||||
|
||||
@ -6,7 +6,15 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import <PNObject/PNObject.h>
|
||||
#import "PNObject.h"
|
||||
|
||||
#pragma mark MappingSelector Keys
|
||||
|
||||
extern NSString* _Nonnull const PNObjectMappingKey;
|
||||
extern NSString* _Nonnull const PNObjectMappingType;
|
||||
extern NSString* _Nonnull const PNObjectMappingSelector;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface PNObject (Protected)
|
||||
/**
|
||||
@ -38,6 +46,15 @@
|
||||
*/
|
||||
+ (NSDictionary * _Nullable)propertiesForClass:(Class _Nonnull)PNObjClass;
|
||||
|
||||
/**
|
||||
* <#Description#>
|
||||
*
|
||||
* @param mappingSelector <#mappingSelector description#>
|
||||
*
|
||||
* @return <#return value description#>
|
||||
*/
|
||||
- (NSDictionary* _Nonnull) getFormObject:(SEL _Nonnull) dictionaryMappingSelector;
|
||||
|
||||
- (void)resetObject;
|
||||
|
||||
///--------------------------------------
|
||||
@ -50,11 +67,11 @@
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nonnull) NSDictionary * JSON;
|
||||
@property (nonatomic, strong, nullable) NSMutableDictionary * JSON;
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nonnull) NSString * endPoint;
|
||||
@property (nonatomic, strong, nullable) NSString * endPoint;
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
|
||||
@ -11,6 +11,14 @@
|
||||
#import <NSDate_Utils/NSDate+NSDate_Util.h>
|
||||
#import "objc/runtime.h"
|
||||
|
||||
extern NSString* _Nonnull const PNObjectMappingKey;
|
||||
extern NSString* _Nonnull const PNObjectMappingType;
|
||||
extern NSString* _Nonnull const PNObjectMappingSelector;
|
||||
|
||||
NSString * const PNObjectMappingKey = @"PNObjectLocalNotificationRefreshTokenClientCredentialSuccess";
|
||||
NSString * const PNObjectMappingType = @"PNObjectLocalNotificationRefreshTokenClientCredentialFail";
|
||||
NSString * const PNObjectMappingSelector = @"PNObjectLocalNotificationRefreshTokenClientCredentialFail";
|
||||
|
||||
@implementation PNObject (Protected)
|
||||
|
||||
@dynamic endPoint;
|
||||
@ -25,38 +33,39 @@
|
||||
- (void)populateObjectFromJSON:(id _Nullable)JSON
|
||||
{
|
||||
NSDictionary *properties = [PNObject propertiesForClass:self.class];
|
||||
|
||||
|
||||
for(NSString *propertyName in properties) {
|
||||
|
||||
|
||||
if([propertyName isEqualToString:@"mappingError"])
|
||||
continue;
|
||||
|
||||
|
||||
NSString *mappedJSONKey;
|
||||
NSString *mappedJSONType;
|
||||
|
||||
|
||||
NSString *propertyType = [properties valueForKey:propertyName];
|
||||
NSLogDebug(@"%@",self.JSONObject);
|
||||
|
||||
NSLogDebug(@"%@",[[self class] objcetMapping]);
|
||||
|
||||
|
||||
id mappingValue = [[[self class] objcetMapping] valueForKey:propertyName];
|
||||
|
||||
|
||||
|
||||
if([mappingValue isKindOfClass:NSDictionary.class]) {
|
||||
mappedJSONKey = [mappingValue valueForKey:@"key"];
|
||||
mappedJSONType = [mappingValue valueForKey:@"type"];
|
||||
} else {
|
||||
mappedJSONKey = mappingValue;
|
||||
}
|
||||
|
||||
|
||||
if ([[PNObject protectedProperties] containsObject:propertyName]) {
|
||||
|
||||
|
||||
if ([[PNObject protectedProperties] containsObject:propertyName] || [self isObjNull:mappedJSONKey]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Get JSON value for the mapped key
|
||||
id value = [JSON valueForKeyPath:mappedJSONKey];
|
||||
|
||||
|
||||
|
||||
if([self isObjNull:value]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
((void (^)())@{
|
||||
@"c" : ^{
|
||||
char val = [value charValue];
|
||||
@ -90,13 +99,10 @@
|
||||
if (![self isObjNull:value]) {
|
||||
[self setValue:value forKey:propertyName];
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
@"NSNumber" : ^{
|
||||
NSInteger val = 0;
|
||||
if (value && ![value isKindOfClass:[NSNull class]]) {
|
||||
val = [value integerValue];
|
||||
}
|
||||
NSInteger val = [value integerValue];
|
||||
|
||||
[self setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@ -106,6 +112,11 @@
|
||||
if (![self isObjNull:val]) {
|
||||
[self setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSURL" : ^{
|
||||
NSString *str = [NSString stringWithFormat:@"%@", value];
|
||||
NSURL *val = [NSURL URLWithString:str];
|
||||
[self setValue:val forKey:propertyName];
|
||||
},
|
||||
@"NSArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
@ -113,7 +124,7 @@
|
||||
PNObject *val = [[NSClassFromString(mappedJSONType) alloc] initWithJSON:JSONObject];
|
||||
[arr addObject:val];
|
||||
}
|
||||
|
||||
|
||||
[self setValue:arr forKey:propertyName];
|
||||
},
|
||||
@"NSMutableArray" : ^{
|
||||
@ -122,12 +133,15 @@
|
||||
PNObject *val = [[NSClassFromString(mappedJSONType) alloc] initWithJSON:JSONObject];
|
||||
[arr addObject:val];
|
||||
}
|
||||
|
||||
|
||||
[self setValue:arr forKey:propertyName];
|
||||
}
|
||||
}[propertyType] ?: ^{
|
||||
|
||||
BOOL isPNObjectSubclass = [NSClassFromString(propertyType) isSubclassOfClass:[PNObject class]];
|
||||
|
||||
if(isPNObjectSubclass) {
|
||||
|
||||
PNObject *val = [[NSClassFromString(propertyType) alloc] initWithJSON:value];
|
||||
[self setValue:val forKey:propertyName];
|
||||
}
|
||||
@ -142,35 +156,35 @@
|
||||
- (void)resetObject
|
||||
{
|
||||
NSDictionary *properties = [PNObject propertiesForClass:self.class];
|
||||
|
||||
|
||||
for(NSString *propertyName in properties) {
|
||||
|
||||
|
||||
if([propertyName isEqualToString:@"mappingError"])
|
||||
continue;
|
||||
|
||||
|
||||
NSString *mappedJSONKey;
|
||||
NSString *mappedJSONType;
|
||||
|
||||
|
||||
NSString *propertyType = [properties valueForKey:propertyName];
|
||||
|
||||
id mappingValue = [self.JSONObject valueForKey:propertyName];
|
||||
|
||||
|
||||
id mappingValue = [self.JSONObjectMap valueForKey:propertyName];
|
||||
|
||||
if([mappingValue isKindOfClass:NSDictionary.class]) {
|
||||
mappedJSONKey = [mappingValue valueForKey:@"key"];
|
||||
mappedJSONType = [mappingValue valueForKey:@"type"];
|
||||
} else {
|
||||
mappedJSONKey = mappingValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if ([[PNObject protectedProperties] containsObject:propertyName]
|
||||
|| [propertyName isEqualToString:@"description"]
|
||||
|| [propertyName isEqualToString:@"debugDescription"]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Get JSON value for the mapped key
|
||||
|
||||
|
||||
((void (^)())@{
|
||||
@"c" : ^{
|
||||
char val = '\0';
|
||||
@ -227,6 +241,258 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary* _Nonnull) getFormObject:(SEL _Nonnull) dictionaryMappingSelector
|
||||
{
|
||||
NSMutableDictionary *JSON = [NSMutableDictionary dictionary];
|
||||
|
||||
if ([[self class] respondsToSelector:dictionaryMappingSelector]) {
|
||||
|
||||
NSDictionary *properties = [PNObject propertiesForClass:self.class];
|
||||
|
||||
NSDictionary *formMapping = [[self class] performSelector:dictionaryMappingSelector];
|
||||
|
||||
for (NSString *formMappingKey in formMapping) {
|
||||
|
||||
if ([[properties allKeys] containsObject:formMappingKey] && [properties objectForKey:formMappingKey]) {
|
||||
|
||||
id property = [self valueForKey:formMappingKey];
|
||||
|
||||
id formMappingValue = [formMapping objectForKey:formMappingKey];
|
||||
|
||||
NSString *mappedKey;
|
||||
NSString *mappedType;
|
||||
NSDictionary *mappedValues;
|
||||
|
||||
if ([formMappingValue isKindOfClass:[NSDictionary class]]) {
|
||||
mappedKey = [formMappingValue valueForKey:@"key"];
|
||||
mappedType = [formMappingValue valueForKey:@"type"];
|
||||
mappedValues = [formMappingValue valueForKey:@"values"];
|
||||
}
|
||||
else {
|
||||
mappedKey = formMappingKey;
|
||||
}
|
||||
|
||||
((void (^)())@{
|
||||
@"c" : ^{
|
||||
char val = [property charValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"d" : ^{
|
||||
double val = [property doubleValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"f" : ^{
|
||||
float val = [property floatValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"i" : ^{
|
||||
int val = [property intValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"l" : ^{
|
||||
long val = [property longValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"s" : ^{
|
||||
short val = [property shortValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"B" : ^{
|
||||
BOOL val = [property boolValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
|
||||
@"UIImage" : ^{
|
||||
UIImage *image = [UIImage imageWithData:property];
|
||||
[JSON setValue:image forKey:mappedKey];
|
||||
},
|
||||
@"NSURL" : ^{
|
||||
NSURL *url = property;
|
||||
|
||||
if (![self isObjNull:url]) {
|
||||
[JSON setValue:[url absoluteString] forKey:mappedKey];
|
||||
}
|
||||
},
|
||||
@"NSString" : ^{
|
||||
NSString *val = [NSString stringWithFormat:@"%@", property];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:mappedKey];
|
||||
}
|
||||
},
|
||||
@"NSNumber" : ^{
|
||||
NSInteger val = [property integerValue];
|
||||
[JSON setValue:@(val) forKey:mappedKey];
|
||||
},
|
||||
@"NSDate" : ^{
|
||||
NSDate *val = [property toLocalTime];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:mappedKey];
|
||||
}
|
||||
},
|
||||
@"NSArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id object in property) {
|
||||
|
||||
BOOL isPNObjectSubclass = [[object class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
NSDictionary *objectDict = [(PNObject*) object getFormObject:dictionaryMappingSelector];
|
||||
|
||||
[arr addObject:objectDict];
|
||||
}
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:mappedKey];
|
||||
},
|
||||
@"NSMutableArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id object in property) {
|
||||
|
||||
BOOL isPNObjectSubclass = [[object class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
NSDictionary *objectDict = [(PNObject*) object getFormObject:dictionaryMappingSelector];
|
||||
|
||||
[arr addObject:objectDict];
|
||||
}
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:mappedKey];
|
||||
}
|
||||
}[[property class]] ?: ^{
|
||||
BOOL isPNObjectSubclass = [[property class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
|
||||
NSDictionary *objectDict = [(PNObject*)property getFormObject:dictionaryMappingSelector];
|
||||
|
||||
[JSON setValue:objectDict forKey:mappedKey];
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
/*for (NSString* propertyName in self.JSONObjectMap) {
|
||||
|
||||
id mappingValue = [self.JSONObjectMap objectForKey:propertyName];
|
||||
|
||||
if([mappingValue isKindOfClass:NSDictionary.class]) {
|
||||
mappedJSONKey = [mappingValue valueForKey:@"key"];
|
||||
mappedJSONType = [mappingValue valueForKey:@"type"];
|
||||
} else {
|
||||
mappedJSONKey = mappingValue;
|
||||
}
|
||||
|
||||
NSString *propertyType = [properties valueForKey:propertyName];
|
||||
|
||||
if (![[formMapping allKeys] containsObject:propertyName]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
id value = [self valueForKey:propertyName];
|
||||
//TODO: forse è da sostituire propertyName con il valore de
|
||||
((void (^)())@{
|
||||
@"c" : ^{
|
||||
char val = [value charValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"d" : ^{
|
||||
double val = [value doubleValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"f" : ^{
|
||||
float val = [value floatValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"i" : ^{
|
||||
int val = [value intValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"l" : ^{
|
||||
long val = [value longValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"s" : ^{
|
||||
short val = [value shortValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"B" : ^{
|
||||
BOOL val = [value boolValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
|
||||
@"UIImage" : ^{
|
||||
UIImage *image = [UIImage imageWithData:value];
|
||||
[JSON setValue:image forKey:propertyName];
|
||||
},
|
||||
@"NSURL" : ^{
|
||||
NSURL *url = value;
|
||||
|
||||
if (![self isObjNull:url]) {
|
||||
[JSON setValue:[url absoluteString] forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSString" : ^{
|
||||
NSString *val = [NSString stringWithFormat:@"%@", value];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSNumber" : ^{
|
||||
NSInteger val = [value integerValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"NSDate" : ^{
|
||||
NSDate *val = [value toLocalTime];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id object in value) {
|
||||
|
||||
BOOL isPNObjectSubclass = [[object class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
NSDictionary *objectDict = [(PNObject*) object reverseMapping];
|
||||
|
||||
[arr addObject:objectDict];
|
||||
}
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:propertyName];
|
||||
},
|
||||
@"NSMutableArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id object in value) {
|
||||
|
||||
BOOL isPNObjectSubclass = [[object class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
NSDictionary *objectDict = [(PNObject*) object reverseMapping];
|
||||
|
||||
[arr addObject:objectDict];
|
||||
}
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:propertyName];
|
||||
}
|
||||
}[propertyType] ?: ^{
|
||||
BOOL isPNObjectSubclass = [NSClassFromString(propertyType) isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
|
||||
NSDictionary *objectDict = [(PNObject*)value reverseMapping];
|
||||
|
||||
[JSON setValue:objectDict forKey:propertyName];
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
})();
|
||||
}*/
|
||||
}
|
||||
return JSON;
|
||||
}
|
||||
|
||||
- (BOOL)isObjNull:(id _Nullable)obj
|
||||
{
|
||||
if(!obj || nil == obj || NSNull.null == obj || ([obj isKindOfClass:[NSString class]] && [obj isEqualToString:@"(null)"]) || [obj isEqual:[NSNull null]])
|
||||
@ -240,15 +506,15 @@ static BOOL property_getTypeString( objc_property_t property, char *buffer )
|
||||
const char * attrs = property_getAttributes( property );
|
||||
if ( attrs == NULL )
|
||||
return NO;
|
||||
|
||||
|
||||
const char * e = strchr( attrs, ',' );
|
||||
if ( e == NULL )
|
||||
return NO;
|
||||
|
||||
|
||||
int len = (int)(e - attrs);
|
||||
memcpy( buffer, attrs, len );
|
||||
buffer[len] = '\0';
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -259,13 +525,13 @@ static BOOL property_getTypeString( objc_property_t property, char *buffer )
|
||||
if (PNObjClass == NULL) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
NSMutableDictionary *results = [NSMutableDictionary dictionary];
|
||||
if ([PNObjClass isSubclassOfClass:[PNObject class]] && PNObjClass != [PNObject class]) {
|
||||
|
||||
[results addEntriesFromDictionary:[self propertiesForClass:class_getSuperclass(PNObjClass)]];
|
||||
}
|
||||
|
||||
|
||||
unsigned int outCount, i;
|
||||
objc_property_t *properties = class_copyPropertyList(PNObjClass, &outCount);
|
||||
for (i = 0; i < outCount; i++) {
|
||||
@ -279,7 +545,7 @@ static BOOL property_getTypeString( objc_property_t property, char *buffer )
|
||||
}
|
||||
NSString *propertyName = [NSString stringWithUTF8String:propName];
|
||||
NSString *propertyType = [NSString stringWithUTF8String:propType];
|
||||
|
||||
|
||||
NSRange range = [propertyType rangeOfString:@"T@\""];
|
||||
NSRange range2 = [propertyType rangeOfString:@"T"];
|
||||
if (range.location != NSNotFound) {
|
||||
|
||||
@ -32,6 +32,8 @@
|
||||
|
||||
+ (NSString * _Nonnull) PNObjEndPoint;
|
||||
|
||||
+ (NSArray * _Nonnull) batch:(id _Nonnull)JSON;
|
||||
|
||||
- (_Nullable instancetype) initWithJSON:( NSDictionary * _Nonnull) JSON;
|
||||
|
||||
- (id _Nonnull) saveLocally;
|
||||
@ -40,6 +42,8 @@
|
||||
|
||||
- (NSDictionary * _Nonnull) JSONFormObject;
|
||||
|
||||
- (NSDictionary * _Nonnull) reverseMapping;
|
||||
|
||||
///--------------------------------------
|
||||
#pragma mark - PNObject Properties
|
||||
///--------------------------------------
|
||||
@ -55,7 +59,7 @@
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, nonnull) NSDictionary * JSONObject;
|
||||
@property (nonatomic, strong, nonnull) NSDictionary * JSONObjectMap;
|
||||
|
||||
|
||||
@end
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
@property (nonatomic) BOOL singleInstance;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation PNObject
|
||||
@ -84,22 +85,22 @@
|
||||
|
||||
_objID = [[NSProcessInfo processInfo] globallyUniqueString];
|
||||
|
||||
_objectModel = [PNObjectModel sharedInstance];
|
||||
[_objectModel setPersistencyDelegate:self];
|
||||
self.objectModel = [PNObjectModel sharedInstance];
|
||||
[self.objectModel setPersistencyDelegate:self];
|
||||
|
||||
NSMutableDictionary * objectDict = [[NSMutableDictionary alloc] initWithDictionary:[[self class] objcetMapping]];
|
||||
[objectDict addEntriesFromDictionary:[PNObject objcetMapping]];
|
||||
|
||||
_JSONObject = objectDict;
|
||||
self.JSONObjectMap = objectDict;
|
||||
|
||||
NSAssert(_JSONObject, @"You must create objectMapping");
|
||||
NSAssert(self.JSONObjectMap, @"You must create objectMapping");
|
||||
|
||||
_singleInstance = [[self class] singleInstance];
|
||||
self.singleInstance = [[self class] singleInstance];
|
||||
|
||||
_createdAt = [[NSDate date] toLocalTime];
|
||||
self.createdAt = [[NSDate date] toLocalTime];
|
||||
}
|
||||
|
||||
_JSON = [[NSMutableDictionary alloc] init];
|
||||
self.JSON = [[NSMutableDictionary alloc] init];
|
||||
|
||||
NSDictionary *properties = [PNObject propertiesForClass:self.class];
|
||||
|
||||
@ -121,17 +122,17 @@
|
||||
|
||||
_objID = [[NSProcessInfo processInfo] globallyUniqueString];
|
||||
|
||||
_objectModel = [PNObjectModel sharedInstance];
|
||||
[_objectModel setPersistencyDelegate:self];
|
||||
self.objectModel = [PNObjectModel sharedInstance];
|
||||
[self.objectModel setPersistencyDelegate:self];
|
||||
|
||||
NSMutableDictionary * objectDict = [[NSMutableDictionary alloc] initWithDictionary:[[self class] objcetMapping]];
|
||||
[objectDict addEntriesFromDictionary:[PNObject objcetMapping]];
|
||||
|
||||
_JSONObject = objectDict;
|
||||
self.JSONObjectMap = objectDict;
|
||||
|
||||
NSAssert(_JSONObject, @"You must create objectMapping");
|
||||
NSAssert(self.JSONObjectMap, @"You must create objectMapping");
|
||||
|
||||
_singleInstance = [[self class] singleInstance];
|
||||
self.singleInstance = [[self class] singleInstance];
|
||||
|
||||
_createdAt = [[NSDate date] toLocalTime];
|
||||
|
||||
@ -146,15 +147,15 @@
|
||||
[self addObserver:self forKeyPath:propertyName options:NSKeyValueObservingOptionNew context:nil];
|
||||
}
|
||||
|
||||
NSAssert(_JSONObject, @"You must create objectMapping");
|
||||
_JSON = [[NSMutableDictionary alloc] initWithDictionary:JSON];
|
||||
NSAssert(self.JSONObjectMap, @"You must create objectMapping");
|
||||
self.JSON = [[NSMutableDictionary alloc] initWithDictionary:JSON];
|
||||
|
||||
[self populateObjectFromJSON:_JSON];
|
||||
[self populateObjectFromJSON:self.JSON];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDictionary * _Nonnull)reverseMapping
|
||||
- (NSDictionary * _Nonnull) reverseMapping
|
||||
{
|
||||
NSMutableDictionary *JSON = [NSMutableDictionary dictionary];
|
||||
|
||||
@ -163,8 +164,8 @@
|
||||
|
||||
NSDictionary *properties = [PNObject propertiesForClass:self.class];
|
||||
|
||||
for (NSString* propertyName in _JSONObject) {
|
||||
id mappingValue = [_JSONObject objectForKey:propertyName];
|
||||
for (NSString* propertyName in self.JSONObjectMap) {
|
||||
id mappingValue = [self.JSONObjectMap objectForKey:propertyName];
|
||||
|
||||
if([mappingValue isKindOfClass:NSDictionary.class]) {
|
||||
mappedJSONKey = [mappingValue valueForKey:@"key"];
|
||||
@ -173,124 +174,119 @@
|
||||
mappedJSONKey = mappingValue;
|
||||
}
|
||||
|
||||
|
||||
NSString *propertyType = [properties valueForKey:propertyName];
|
||||
|
||||
id value = [self valueForKey:propertyName];
|
||||
NSLog(@"PropertyName PropertyType: %@ - %@",propertyName,propertyType);
|
||||
|
||||
NSLog(@"PropertyName PropertyType Value: %@ - %@ - %@",propertyName,propertyType,value);
|
||||
id value;
|
||||
|
||||
((void (^)())@{
|
||||
@"c" : ^{
|
||||
char val = [value charValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"d" : ^{
|
||||
double val = [value doubleValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"f" : ^{
|
||||
float val = [value floatValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"i" : ^{
|
||||
int val = [value intValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"l" : ^{
|
||||
long val = [value longValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"s" : ^{
|
||||
short val = [value shortValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"B" : ^{
|
||||
BOOL val = [value boolValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
|
||||
@"UIImage" : ^{
|
||||
UIImage *image = [UIImage imageWithData:value];
|
||||
[JSON setValue:image forKey:propertyName];
|
||||
},
|
||||
@"NSURL" : ^{
|
||||
NSURL *url = value;
|
||||
|
||||
if (![self isObjNull:url]) {
|
||||
[JSON setValue:[url absoluteString] forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSString" : ^{
|
||||
NSString *val = [NSString stringWithFormat:@"%@", value];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSNumber" : ^{
|
||||
NSInteger val = [value integerValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"NSDate" : ^{
|
||||
NSDate *val = [value toLocalTime];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id PNObject in value) {
|
||||
SEL selector = NSSelectorFromString(@"JSONObject");
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [[PNObject class] instanceMethodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:PNObject];
|
||||
[invocation invoke];
|
||||
NSDictionary *returnValue;
|
||||
[invocation getReturnValue:&returnValue];
|
||||
|
||||
[arr addObject:returnValue];
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:propertyName];
|
||||
},
|
||||
@"NSMutableArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id JSONObject in value) {
|
||||
PNObject *val = [[NSClassFromString(mappedJSONType) alloc] initWithJSON:JSONObject];
|
||||
[arr addObject:val];
|
||||
|
||||
SEL selector = NSSelectorFromString(@"JSONObject");
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[PNObject class] instanceMethodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:value];
|
||||
[invocation invoke];
|
||||
NSDictionary *returnValue;
|
||||
[invocation getReturnValue:&returnValue];
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:propertyName];
|
||||
@try {
|
||||
value = [self valueForKey:propertyName];
|
||||
}
|
||||
}[propertyType] ?: ^{
|
||||
BOOL isPNObjectSubclass = [NSClassFromString(propertyType) isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
SEL selector = NSSelectorFromString(@"JSONObject");
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[PNObject class] instanceMethodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:value];
|
||||
[invocation invoke];
|
||||
NSDictionary *returnValue;
|
||||
[invocation getReturnValue:&returnValue];
|
||||
@catch (NSException *exception) {
|
||||
continue;
|
||||
}
|
||||
@finally {
|
||||
|
||||
[JSON setValue:returnValue forKey:propertyName];
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
})();
|
||||
//NSLog(@"PropertyName PropertyType Value: %@ - %@ - %@",propertyName,propertyType,value);
|
||||
|
||||
((void (^)())@{
|
||||
@"c" : ^{
|
||||
char val = [value charValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"d" : ^{
|
||||
double val = [value doubleValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"f" : ^{
|
||||
float val = [value floatValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"i" : ^{
|
||||
int val = [value intValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"l" : ^{
|
||||
long val = [value longValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"s" : ^{
|
||||
short val = [value shortValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"B" : ^{
|
||||
BOOL val = [value boolValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"NSURL" : ^{
|
||||
NSURL *url = value;
|
||||
|
||||
if (![self isObjNull:url]) {
|
||||
[JSON setValue:[url absoluteString] forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSString" : ^{
|
||||
NSString *val = [NSString stringWithFormat:@"%@", value];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSNumber" : ^{
|
||||
NSInteger val = [value integerValue];
|
||||
[JSON setValue:@(val) forKey:propertyName];
|
||||
},
|
||||
@"NSDate" : ^{
|
||||
NSDate *val = [value toLocalTime];
|
||||
if (![self isObjNull:val]) {
|
||||
[JSON setValue:val forKey:propertyName];
|
||||
}
|
||||
},
|
||||
@"NSArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id object in value) {
|
||||
|
||||
BOOL isPNObjectSubclass = [[object class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
NSDictionary *objectDict = [(PNObject*) object reverseMapping];
|
||||
|
||||
[arr addObject:objectDict];
|
||||
}
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:propertyName];
|
||||
},
|
||||
@"NSMutableArray" : ^{
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
for(id object in value) {
|
||||
|
||||
BOOL isPNObjectSubclass = [[object class] isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
NSDictionary *objectDict = [(PNObject*) object reverseMapping];
|
||||
|
||||
[arr addObject:objectDict];
|
||||
}
|
||||
}
|
||||
|
||||
[JSON setValue:arr forKey:propertyName];
|
||||
}
|
||||
}[propertyType] ?: ^{
|
||||
BOOL isPNObjectSubclass = [NSClassFromString(propertyType) isSubclassOfClass:[PNObject class]];
|
||||
if(isPNObjectSubclass) {
|
||||
|
||||
NSDictionary *objectDict = [(PNObject*)value reverseMapping];
|
||||
|
||||
[JSON setValue:objectDict forKey:propertyName];
|
||||
}
|
||||
else {
|
||||
// do nothing
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
_JSON = JSON;
|
||||
|
||||
return _JSON;
|
||||
return JSON;
|
||||
}
|
||||
|
||||
- (NSDictionary * _Nonnull) JSONFormObject {
|
||||
@ -301,28 +297,16 @@
|
||||
|
||||
for (NSString *key in JSONMap) {
|
||||
|
||||
if ([_JSON objectForKey:[JSONMap objectForKey:key]]) {
|
||||
[JSONFormObject setObject:[_JSON objectForKey:[JSONMap objectForKey:key]] forKey:[JSONMap objectForKey:key]];
|
||||
if ([self.JSON objectForKey:[JSONMap objectForKey:key]]) {
|
||||
[JSONFormObject setObject:[self.JSON objectForKey:[JSONMap objectForKey:key]] forKey:[JSONMap objectForKey:key]];
|
||||
}
|
||||
}
|
||||
return JSONFormObject;
|
||||
}
|
||||
|
||||
|
||||
- (NSDictionary* _Nonnull) JSONObject {
|
||||
if (!_JSON) {
|
||||
return [self reverseMapping];
|
||||
}
|
||||
else {
|
||||
return _JSON;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString* _Nonnull) description {
|
||||
if (!_JSON) {
|
||||
[self reverseMapping];
|
||||
}
|
||||
return [_JSON description];
|
||||
return [[self reverseMapping] description];
|
||||
}
|
||||
|
||||
- (void) setSingleInstance:(BOOL)singleInstance {
|
||||
@ -359,11 +343,25 @@
|
||||
|
||||
__weak id weakSelf = self;
|
||||
|
||||
return [_objectModel saveLocally:weakSelf];
|
||||
return [self.objectModel saveLocally:weakSelf];
|
||||
}
|
||||
|
||||
- (BOOL) autoRemoveLocally {
|
||||
return [_objectModel removeObjectLocally:self];
|
||||
return [self.objectModel removeObjectLocally:self];
|
||||
}
|
||||
|
||||
+ (NSArray *)batch:(id)JSON
|
||||
{
|
||||
NSString *className = NSStringFromClass([self class]);
|
||||
|
||||
NSMutableArray *batch = [NSMutableArray array];
|
||||
|
||||
for(id objectJSON in JSON) {
|
||||
PNObject *val = [[NSClassFromString(className) alloc] initWithJSON:objectJSON];
|
||||
[batch addObject:val];
|
||||
}
|
||||
|
||||
return batch;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@ -372,45 +370,52 @@
|
||||
{
|
||||
@try {
|
||||
if ([change objectForKey:@"new"]) {
|
||||
[_JSON setObject:[change objectForKey:@"new"] forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
|
||||
if ([[[change objectForKey:@"new"] class] isSubclassOfClass:[PNObject class]]) {
|
||||
|
||||
NSDictionary *objectDict = [(PNObject*)[change objectForKey:@"new"] reverseMapping];
|
||||
|
||||
[self.JSON setValue:objectDict forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
|
||||
}
|
||||
else {
|
||||
[self.JSON setObject:[change objectForKey:@"new"] forKey:[[[self class] objcetMapping] objectForKey:keyPath]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
[_JSON removeObjectForKey:[[[self class] objcetMapping] objectForKey:keyPath]];
|
||||
[self.JSON removeObjectForKey:[[[self class] objcetMapping] objectForKey:keyPath]];
|
||||
}
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
|
||||
|
||||
}
|
||||
@finally {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NSDictionary *properties = [PNObject propertiesForClass:self.class];
|
||||
|
||||
|
||||
for (NSString *propertyName in properties) {
|
||||
if ([propertyName isEqualToString:@"description"] || [propertyName isEqualToString:@"debugDescription"]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@try {
|
||||
[self removeObserver:self forKeyPath:propertyName];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
|
||||
|
||||
}
|
||||
@finally {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
_JSON = nil;
|
||||
_JSONObject = nil;
|
||||
self.JSON = nil;
|
||||
_JSONObjectMap = nil;
|
||||
_objID = nil;
|
||||
_createdAt = nil;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AFNetworking/AFNetworking.h>
|
||||
#import "HTTPStatusCodes.h"
|
||||
//#import "HTTPStatusCodes"
|
||||
|
||||
#import "AFOAuth2Manager.h"
|
||||
#import "AFHTTPRequestSerializer+OAuth2.h"
|
||||
@ -175,5 +175,9 @@ extern NSString* _Nonnull const Client_Secret;
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic) NSInteger minPasswordLenght;
|
||||
/**
|
||||
* <#Description#>
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) NSString *encrypKey;
|
||||
|
||||
@end
|
||||
@ -24,6 +24,8 @@ NSString * const PNObjectLocalNotificationRefreshTokenUserFail = @"PNObjectLocal
|
||||
|
||||
NSInteger const minPassLenght = 4;
|
||||
|
||||
NSString * const PNObjectEncryptionKey = @"PNObjectConfigEncryptionKey";
|
||||
|
||||
NSString * const PNObjectServiceCredentialIdentifier = @"PNObjectServiceCredentialIdentifier";
|
||||
|
||||
NSString* const EnvironmentProduction = @"PNObjectConfigEnvProduction";
|
||||
@ -146,6 +148,15 @@ static bool isFirstAccess = YES;
|
||||
|
||||
_headerFields = [[NSMutableDictionary alloc] init];
|
||||
|
||||
if ([[NSUserDefaults standardUserDefaults] objectForKey:PNObjectEncryptionKey]) {
|
||||
_encrypKey = [[NSUserDefaults standardUserDefaults] objectForKey:PNObjectEncryptionKey];
|
||||
}
|
||||
else {
|
||||
_encrypKey = [[NSProcessInfo processInfo] globallyUniqueString];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:_encrypKey forKey:PNObjectEncryptionKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
}
|
||||
return self;
|
||||
@ -218,7 +229,7 @@ static bool isFirstAccess = YES;
|
||||
[[_manager requestSerializer] setAuthorizationHeaderFieldWithCredential:_currentOauthCredential];
|
||||
}
|
||||
else {
|
||||
[self refreshTokenForClientCredential];
|
||||
[self refreshToken];
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,6 +245,15 @@ static bool isFirstAccess = YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) refreshToken {
|
||||
if([PNUser currentUser] && [[PNUser currentUser] hasValidEmailAndPasswordData]) {
|
||||
[self refreshTokenForUser];
|
||||
}
|
||||
else {
|
||||
[self refreshTokenForClientCredential];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) refreshTokenForUser {
|
||||
|
||||
[self refreshTokenForUserWithBlockSuccess:nil failure:nil];
|
||||
@ -243,7 +263,7 @@ static bool isFirstAccess = YES;
|
||||
failure:(nullable void (^)(NSError * _Nonnull error))failure {
|
||||
|
||||
if([PNUser currentUser] && [[PNUser currentUser] hasValidEmailAndPasswordData]) {
|
||||
[_manager authenticateUsingOAuthWithURLString:[_currentEndPointBaseUrl stringByAppendingString:@"oauth-token"] username:[[PNUser currentUser] email] password:[[PNUser currentUser] password] scope:nil success:^(AFOAuthCredential * _Nonnull credential) {
|
||||
[_manager authenticateUsingOAuthWithURLString:[_currentEndPointBaseUrl stringByAppendingString:@"oauth-token"] username:[[PNUser currentUser] email] password:[[[PNUser currentUser] password] password] scope:nil success:^(AFOAuthCredential * _Nonnull credential) {
|
||||
_currentOauthCredential = credential;
|
||||
|
||||
[AFOAuthCredential storeCredential:_currentOauthCredential withIdentifier:PNObjectServiceCredentialIdentifier];
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#import "PEARFileManager.h"
|
||||
#import "PNObjectConstants.h"
|
||||
|
||||
@import RNCryptor;
|
||||
|
||||
@interface PNObjectModel()
|
||||
|
||||
@property (nonatomic, strong) PEARFileManager *fileManager;
|
||||
@ -161,16 +163,10 @@ static bool isFirstAccess = YES;
|
||||
|
||||
if ([(PNObject*) object singleInstance]) {
|
||||
|
||||
SEL selector = NSSelectorFromString(@"JSONObject");
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[PNObject class] instanceMethodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:object];
|
||||
[invocation invoke];
|
||||
NSDictionary *objectDict = [(PNObject*) object reverseMapping];
|
||||
|
||||
NSDictionary *objectDict;
|
||||
[invocation getReturnValue:&objectDict];
|
||||
|
||||
NSData *objectData = [NSKeyedArchiver archivedDataWithRootObject:objectDict];
|
||||
NSData *objectData = [RNCryptor encryptData:[NSKeyedArchiver archivedDataWithRootObject:objectDict] password:[[PNObjectConfig sharedInstance] encrypKey]];
|
||||
|
||||
|
||||
if ([self issetPNObjectModelForObject:object]) {
|
||||
if ([_fileManager updateFileWithData:objectData filePath:[self objectName:object] permisson:@(0755)]) {
|
||||
@ -192,25 +188,19 @@ static bool isFirstAccess = YES;
|
||||
else {
|
||||
if ([self issetPNObjectModelForObject:object]) {
|
||||
|
||||
NSData * data = [_fileManager fetchFileDataWithPath:[self objectName:object]];
|
||||
|
||||
//NSData * data = [_fileManager fetchFileDataWithPath:[self objectName:object]];
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
NSData *data = [RNCryptor decryptData:[_fileManager fetchFileDataWithPath:[self objectName:object]] password:[[PNObjectConfig sharedInstance] encrypKey] error:&error];
|
||||
|
||||
NSMutableArray *objects = [[NSMutableArray alloc] initWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:data]];
|
||||
|
||||
|
||||
SEL selector = NSSelectorFromString(@"JSONObject");
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[PNObject class] instanceMethodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:object];
|
||||
[invocation invoke];
|
||||
|
||||
NSDictionary *objectDict;
|
||||
[invocation getReturnValue:&objectDict];
|
||||
|
||||
NSLogDebug(@"%@",objectDict);
|
||||
NSDictionary *objectDict = [(PNObject*)object reverseMapping];
|
||||
|
||||
[objects addObject:objectDict];
|
||||
|
||||
NSData *objectData = [NSKeyedArchiver archivedDataWithRootObject:objects];
|
||||
NSData *objectData = [RNCryptor encryptData:[NSKeyedArchiver archivedDataWithRootObject:objects] password:[[PNObjectConfig sharedInstance] encrypKey]];
|
||||
|
||||
if ([_fileManager updateFileWithData:objectData filePath:[self objectName:object] permisson:@(0755)]) {
|
||||
|
||||
@ -223,20 +213,12 @@ static bool isFirstAccess = YES;
|
||||
else {
|
||||
|
||||
NSMutableArray *objects = [[NSMutableArray alloc] init];
|
||||
|
||||
|
||||
SEL selector = NSSelectorFromString(@"JSONObject");
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[PNObject class] instanceMethodSignatureForSelector:selector]];
|
||||
[invocation setSelector:selector];
|
||||
[invocation setTarget:object];
|
||||
[invocation invoke];
|
||||
|
||||
NSDictionary *objectDict;
|
||||
[invocation getReturnValue:&objectDict];
|
||||
|
||||
NSDictionary *objectDict = [(PNObject*)object reverseMapping];
|
||||
|
||||
[objects addObject:objectDict];
|
||||
|
||||
NSData *objectData = [NSKeyedArchiver archivedDataWithRootObject:objects];
|
||||
NSData *objectData = [RNCryptor encryptData:[NSKeyedArchiver archivedDataWithRootObject:objects] password:[[PNObjectConfig sharedInstance] encrypKey]];
|
||||
|
||||
if ([_fileManager createFileWithData:objectData filePath:[self objectName:object] permisson:@(0755)]) {
|
||||
return object;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user