How to transfer encrypted data over AirDrop - ios

I want to transfer my NSObject "RND_PatientData" which is encrypted from my application to another person using the application using AirDrop.
At present my data is saved using this code:
- (RND_PatientData *)data {
if (_data != nil) return _data;
NSString *dataPath = [_docPath stringByAppendingPathComponent:kDataFile];
NSData *codedData = [[NSData alloc] initWithContentsOfFile:dataPath];
if (codedData == nil) return nil;
NSString *deviceName = [[UIDevice currentDevice] name];
NSData *decryptedData = [RNDecryptor decryptData:codedData withSettings:kRNCryptorAES256Settings password:deviceName error:nil];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:decryptedData];
_data = [unarchiver decodeObjectForKey:kDataKey];
[unarchiver finishDecoding];
return _data;
}
- (void)saveData {
if (_data == nil) return;
[self createDataPath];
NSString *dataPath = [_docPath stringByAppendingPathComponent:kDataFile];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:_data forKey:kDataKey];
[archiver finishEncoding];
NSError *error;
NSString *deviceName = [[UIDevice currentDevice] name];
NSData *encryptedData = [RNEncryptor encryptData:data
withSettings:kRNCryptorAES256Settings
password:deviceName
error:&error];
[encryptedData writeToFile:dataPath atomically:YES];
This data is also encrypted using the device UDID and the RNDecryptor library before being saved.
Now, I would like the perosn to be able to transfer the data via AirDrop.
Is it better to decrypt the data on the sender phone and then transfer it unencrypted and encrypt it on the receiver phone using the same framework or to transfer it encrypted and decrypt it using the sender device UDID?
I load my current data as a NSMutableArray :
_patients = [RND_PatientDB loadDocs];
The method goes as follow:
+ (NSMutableArray *)loadDocs {
// Get private docs dir
NSString *documentsDirectory = [RND_PatientDB getPrivateDocsDir];
NSLog(#"Loading patients from %#", documentsDirectory);
// Get contents of documents directory
NSError *error;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
if (files == nil) {
NSLog(#"Error reading contents of documents directory: %#", [error localizedDescription]);
return nil;
}
// Create Patients for each file
NSMutableArray *retval = [NSMutableArray arrayWithCapacity:files.count];
for (NSString *file in files) {
if ([file.pathExtension compare:#"patients" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:file];
RND_Patient *doc = [[RND_Patient alloc] initWithDocPath:fullPath];
[retval addObject:doc];
}
}
return retval;
}
+ (NSString *)nextPatientDocPath {
// Get private docs dir
NSString *documentsDirectory = [RND_PatientDB getPrivateDocsDir];
// Get contents of documents directory
NSError *error;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
if (files == nil) {
NSLog(#"Error reading contents of documents directory: %#", [error localizedDescription]);
return nil;
}
// Search for an available name
int maxNumber = 0;
for (NSString *file in files) {
if ([file.pathExtension compare:#"patients" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
NSString *fileName = [file stringByDeletingPathExtension];
maxNumber = MAX(maxNumber, fileName.intValue);
}
}
// Get available name
NSString *availableName = [NSString stringWithFormat:#"%d.patients", maxNumber+1];
return [documentsDirectory stringByAppendingPathComponent:availableName];
}
I've tried following instructions here to send NSArray via AirDrop, but I cannot understand how the certificate works. Anyone has ressources I can use to learn more about this procedure? Also am I doing it the right way or is there an easier method to send my NSMutableArray of _patients comprised of RND_PATIENT NSObject to another person using my application?

Related

iOS - writeToFile from NSData completion handler

I am getting bytes of a file from a webservice, my goal is to get these bytes, put them into NSData and then write into a file, once the writeToFile is 100% complete, I would then display the file (its a PDF, can be up to 6 pages) in QLPreviewController.
I am able to get the bytes from the webservice and put them into NSData like so:
NSArray *byteArray = [dataSource.areaData GetPDFFileData:[NSString stringWithFormat:#"%#",encodedUrlStr]];
NSData *data;
for (NSDictionary *dict in byteArray) {
NSString *base64 = dict[#"data"];
data = [[NSData alloc] initWithBase64EncodedString:base64 options:0];
}
Now I am trying to write the file like so:
if (data)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,PDFFile];
[data writeToFile:filePath atomically:YES];
}
Now what I am trying to do is have some sort of completion handler so nothing else happens until the file is completely written. What would be the best way to do this?
I am also starting to look into NSFileHandle, would that be a better solution?
use NSFilePresenter to monitor for changes to the file
and use a NSFileCoordinator to write to it
in mock code:
NSFilePresenter *p = [NSFilePresenter presenterWithFile:f];
[p signupForChangeNotificationsOrSetDelegateOrWhatever....];
//write
NSFileCoordinator *c = [NSFileCoordinator coordinatorWithPresenter:p];
[c coordinate writeData....]
... called back by p cause we changed
No need to worry about completion if this runs in main queue it's serial , but it's better to save in background queue and read content to verify and present in main Queue
DispatchQueue.global(qos: .background).async {
print("This is run on the background queue")
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSLog(#"not exists");
NSData *fileContents = [#"" dataUsingEncoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] createFileAtPath:filePath
contents:fileContents
attributes:nil];
}
else
{
NSLog(#"exists");
}
NSFileHandle *myHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
[myHandle seekToEndOfFile];
NSString*strTowrite=[NSString stringWithFormat:#"%# || %# --- %# \r\n",dt,acion,name];
[myHandle writeabilityHandler];
[myHandle writeData:[strTowrite dataUsingEncoding:NSUTF8StringEncoding]];
DispatchQueue.main.async {
NSString*content=[[NSString alloc] initWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:&error];
if(content)
{
NSLog(#"content is : %# Err : %#",content,error);
// [self sendfile];
}
else
{
NSLog(#"Failed to store the file. Error = %#", error);
}
}
}

Access local file path in Objective C

I have added a folder name Resources and under it there is another folder name File inside the file folder there are two xml files which i'm trying to parse. When i give pathforResource method name to my Resources folder it shows path is null. How can i access the two xml file from these folders?
Resources->File->text.xml.
My code is this,
NSMutableArray *aryXMLName = [NSMutableArray new];
[aryXMLName addObject:#"text.xml"];
[aryXMLName addObject:#"test1.xml"];
for(NSString *str in aryXMLName){
NSString *path = [[NSBundle mainBundle] pathForResource:str ofType:#"Resources"];
NSLog(#"Path : %#",path);
NSData *data=[NSData dataWithContentsOfFile:path];
if ([str isEqualToString:#"text.xml"]) {
if (data == nil)
return;
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"string: %#", str);
NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLString:str];
NSLog(#"dictionary: %#", xmlDoc);
}else if ([str isEqualToString:#"test1.xml"]){
if (data == nil)
return;
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"string: %#", str);
NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLString:str];
NSLog(#"dictionary: %#", xmlDoc);
}
}
The scenario is like this,
enter image description here
Replace this code:
NSMutableArray *aryXMLName = [NSMutableArray new];
[aryXMLName addObject:#"test"];
[aryXMLName addObject:#"text1"];
for(NSString *str in aryXMLName){
NSString *path = [[NSBundle mainBundle] pathForResource:str ofType:#"xml"];
NSLog(#"Path : %#",path);
NSData *data=[NSData dataWithContentsOfFile:path];
if ([str isEqualToString:#"test"]) {
if (data == nil)
return;
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"string: %#", str);
NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLString:str];
NSLog(#"dictionary: %#", xmlDoc);
}else if ([str isEqualToString:#"text1"]){
if (data == nil)
return;
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"string: %#", str);
NSDictionary *xmlDoc = [NSDictionary dictionaryWithXMLString:str];
NSLog(#"dictionary: %#", xmlDoc);
}
}

How to Access local JSON file response in NSDictionary for showing in UITableView?

Basically I got response from server side and then i saved it in local file.Actually I fetched the response from server side and then saved into documents directory ,and now trying to fetch but it comes in NSString only ,i unable to get in NSDictionary....Here is following code
- (IBAction)loginButtonPressed:(id)sender
{
NSString *URLString = #"http://localhost/rest/login";
AFHTTPSessionManager *manager =[AFHTTPSessionManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *params = #{#"username": userNameTxtField.text, #"password": pwdTextField.text};
NSLog(#"Parameters:\n%#",params);
[manager POST:URLString parameters:params progress:nil success:^(NSURLSessionDataTask *operation, id responseObject)
{
NSLog(#"Successfully Login ....: %#", responseObject);
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
path = [NSString stringWithFormat:#"%#/sample.json", documents];
NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:path append:YES];
[stream open];
NSError *writeError = nil;
NSInteger bytesWritten = [NSJSONSerialization writeJSONObject:responseObject toStream:stream options:NSJSONWritingPrettyPrinted error:&writeError];
if ((bytesWritten = 0))
{
NSLog(#"Error writing JSON Data");
}
else{
NSLog(#"Sucessfuly saved data...");
}
[stream close];
NSLog(#"path is :%#",path);
} failure:^(NSURLSessionDataTask *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}];
}
- (IBAction)fetch:(id)sender
{
NSError *deserializingError;
NSData *data=[NSData dataWithContentsOfFile:path];
NSString *jsonString = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&deserializingError];
NSMutableDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"vaues are:%#",dict);
}
Your response object should be a type of NSDictionary. Therefore you can use its writeToFileAtPath method to save it to your documents directory.
When recreating the dictionary, you can use the NSDictionary's alloc and initWithContentsOfFile method to directly create a NSDictionary instance.
There are tons of posts on how to do that if you do a little Google search!
Try this!! It's working fine.
NSMutableDictionary *testStore = [[NSMutableDictionary alloc] init];
[testStore setObject:#"vignesh" forKey:#"username"];
[testStore setObject:#"password" forKey:#"password"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:testStore // Here you can pass array or dictionary
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
NSString *jsonString;
if (jsonData) {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
//This is your JSON String
//NSUTF8StringEncoding encodes special characters using an escaping scheme
} else {
NSLog(#"Got an error: %#", error);
jsonString = #"";
}
[self writeStringToFile:jsonString];
NSLog(#"Your JSON String is %#", [self readStringFromFile]);
- (void)writeStringToFile:(NSString*)aString {
// Build the path, and create if needed.
NSString* filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* fileName = #"bookmark.json";
NSString* fileAtPath = [filePath stringByAppendingPathComponent:fileName];
if (![[NSFileManager defaultManager] fileExistsAtPath:fileAtPath]) {
[[NSFileManager defaultManager] createFileAtPath:fileAtPath contents:nil attributes:nil];
}
// Write to file
[[aString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:fileAtPath atomically:NO];
}
- (NSString*)readStringFromFile {
// Build the path...
NSString* filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* fileName = #"bookmark.json";
NSString* fileAtPath = [filePath stringByAppendingPathComponent:fileName];
// read from file
return [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:fileAtPath] encoding:NSUTF8StringEncoding];
}
static const char *dbPath = nil;
static sqlite3_stmt *ermsg = nil;
static sqlite3 *studs =nil;
static DatabaseOperation *_sharedInstances = nil;
#implementation DatabaseOperation
#synthesize databasePath;
+(DatabaseOperation*)sharedInstances{
if(!_sharedInstances){
_sharedInstances =[[super allocWithZone:nil]init];
}
return _sharedInstances;
}
+(id)allocWithZone:(struct _NSZone *)zone{
return [self sharedInstances];
}
-(id)init{
NSLog(#"Only first time Instances using Singleton:");
self =[super init];
if(self){
[self CreateDbpath];
}
return self;
}
-(BOOL)CreateDbpath{
NSArray *dbpaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docdir=[[NSString alloc]initWithString:[dbpaths objectAtIndex:0]];
self.databasePath =[[NSString alloc]initWithString:[docdir stringByAppendingPathComponent:#"Mindset.sqlite"]];
NSFileManager *flg = [NSFileManager defaultManager];
BOOL isSuccess = false;
if([flg fileExistsAtPath:databasePath]==NO){
char *ermsgss = nil;
char const *dbpathss =[self.databasePath UTF8String];
if(sqlite3_open(dbpathss, &studs)==SQLITE_OK){
char *sqlQuery ="create table if not exists emp(name text,city text,img blob)";
if(sqlite3_exec(studs, sqlQuery, nil, nil, &ermsgss)!=SQLITE_OK){
NSLog(#"Failed to create table:");
}
else{
NSLog(#"Successfully to create table:");
}
}
sqlite3_close(studs);
}
return isSuccess;
}
-(void)insertDatabaseValue:(DataManagers *)getInserted{
dbPath = [self.databasePath UTF8String];
if(sqlite3_open(dbPath, &studs)==SQLITE_OK){
NSString *sqlQuery=[[NSString alloc]initWithFormat:#"insert into emp values(?,?,?)"];
const char *_sqlQuery=[sqlQuery UTF8String];
if(sqlite3_prepare_v2(studs, _sqlQuery, -1, &ermsg, nil)==SQLITE_OK){
sqlite3_bind_text(ermsg, 1, [getInserted.userName UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(ermsg, 2, [getInserted.cityName UTF8String], -1, SQLITE_TRANSIENT);
NSData *jpegData =[[NSData alloc]init];
NSData *imgeData =UIImageJPEGRepresentation(getInserted.profileImg, 0.85f);
UIImage *imgesData =[UIImage imageWithData:imgeData];
CGRect rect = CGRectMake(0, 0, 185, 150);
UIGraphicsBeginImageContext(rect.size);
[imgesData drawInRect:rect];
UIImage *img =UIGraphicsGetImageFromCurrentImageContext()
;
UIGraphicsEndImageContext();
jpegData = UIImageJPEGRepresentation(img, 0.01f);
sqlite3_bind_blob(ermsg, 3, [jpegData bytes], [jpegData length], SQLITE_TRANSIENT);
if(sqlite3_step(ermsg)==SQLITE_DONE){
NSLog(#"Successfully inserted into db:");
}
else {
NSLog(#"Error %s",sqlite3_errmsg(studs));
}
}
sqlite3_close(studs);
sqlite3_finalize(ermsg);
}
}
-(NSMutableArray*)getAllData {
NSMutableArray *array =[[NSMutableArray alloc]init];
dbPath = [self.databasePath UTF8String];
if(sqlite3_open(dbPath, &studs)==SQLITE_OK){
NSString *sqlQuery =[[NSString alloc]initWithFormat:#"select * from emp"];
const char *_sqlQuery =[sqlQuery UTF8String];
if(sqlite3_prepare_v2(studs, _sqlQuery, -1, &ermsg, nil)==SQLITE_OK){
while (sqlite3_step(ermsg)==SQLITE_ROW) {
DataManagers *mgr =[[DataManagers alloc]init];
NSString *_Firstname = (const char*)sqlite3_column_text(ermsg, 0) ? [NSString stringWithUTF8String:(const char*)sqlite3_column_text(ermsg, 0)]:nil;
mgr.userName = _Firstname;
NSString *lastName =(const char*)sqlite3_column_text(ermsg, 1)?[NSString stringWithUTF8String:(const char*)sqlite3_column_text(ermsg, 1)]:nil;
mgr.cityName = lastName;
int imgBytes = sqlite3_column_bytes(ermsg, 2);
UIImage *img =[UIImage imageWithData:[NSData dataWithBytes:sqlite3_column_blob(ermsg, 2) length:imgBytes]];
mgr.profileImg = img;
[array addObject:mgr];
}
}
}
return array;
}

Browse for sandbox files iOS device

I am new to iOS sandbox. I am trying to list out all files within the device sandbox. I am not able to succeed it
My Code is
- (void)viewDidLoad {
NSLog(#"Files .. %#",[self showFiles]);
}
- (NSMutableArray *)showFiles
{
NSError *err = nil;
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *myPath = [myPathList objectAtIndex:0];
NSArray *dirContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:myPath error:&err];
if(err) NSLog(#"showFiles() - ERROR: %#",[err localizedDescription]);
NSMutableArray *filePaths = nil;
int count = (int)[dirContent count];
for(int i=0; i<count; i++)
{
[filePaths addObject:[dirContent objectAtIndex:i]];
}
return filePaths;
}
Thanks in advance
OK, you are getting nil as you are passing back an unallocated array object:
NSMutableArray *filePaths = nil;
You want:
NSMutableArray *filePaths = [NSMutableArray new];
However given you are copying the filenames into this array from dirContent, you may just as well return dirContent directly:
- (NSMutableArray *)showFiles
{
NSError *err = nil;
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *myPath = [myPathList objectAtIndex:0];
NSArray *dirContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:myPath error:&err];
if (!dirContent)
NSLog(#"showFiles() - ERROR: %#",[err localizedDescription]);
return dirContent;
}
One further note: You are getting the contents of the Caches folder, which will be empty by default, as far as I know.

File loop: read file into NSString, thats id is the filename ( without .txt)

I have a loop, that gets all files at a dir. Now I want to read every single file, each into a var, thats identifier is the filename without ending.
for example:
filename is text.txt
now read content into NSString *"text" .
Here is my code example: Can someone help?
// create loop to read all files:
NSFileManager* fileManager = [[NSFileManager alloc] init];
fileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator* en = [fileManager enumeratorAtPath:directoryTMP];
NSString* file;
while (file = [en nextObject])
{
NSLog(#"File To Read : %#",file);
if([file isEqualToString:#"do_not_read_this.txt"])
{
NSLog(#"Skip this file for reading");
}
else
{
// read file here:
NSString *fileNameToRead = [NSString stringWithFormat:#"%#/%#.txt",directoryTMPeJL,file];
NSString *fileNameWithoutEnd = [file stringByReplacingOccurrencesOfString:#".txt" withString: #""];
// Read data from Dir
NSString *<fileNameWithoutEnd> = [[NSString alloc] initWithContentsOfFile:fileNameToRead
usedEncoding:nil
error:nil];
}
}
Well you cannot create named variables at runtime, but you could read the files into a NSMutableDictionary where the key is the filename (without the extension) and the value (object) is the file data:
// create loop to read all files:
NSMutableDictionary *files = [NSMutableDictionary new];
NSFileManager* fileManager = [[NSFileManager alloc] init];
fileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator* en = [fileManager enumeratorAtPath:directoryTMP];
NSString* file;
while (file = [en nextObject])
{
NSLog(#"File To Read : %#",file);
if([file isEqualToString:#"do_not_read_this.txt"])
{
NSLog(#"Skip this file for reading");
}
else
{
// read file here:
NSString *fileNameToRead = [NSString stringWithFormat:#"%#/%#.txt",directoryTMPeJL,file];
NSString *fileNameWithoutEnd = [file stringByReplacingOccurrencesOfString:#".txt" withString: #""];
// Read data from Dir
NSError *error = nil;
NSString *data = [[NSString alloc] initWithContentsOfFile:fileNameToRead
encoding:NSUTF8StringEncoding
error:&error];
if (data) {
files[fileNameWithoutEnd] = data;
} else {
NSLog(#"Failed to read file '%#': %#", fileNameToRead, [error localizedDescription]);
}
}
}

Resources