Get dropped mail message from Apple Mail in Cocoa - objective-c

I googled and read docs. Searched on SO, found answers that propose usage of Applescript, but I can't use Applescript because of sandbox.
I am working on Cocoa application (written in Objective-C and sandboxed). I am implementing drag-and-drop from Apple Mail application. App should receive or copy eml mail message as Finder does.
I tried looking at NSPromisedFilesPboardType but hardly could figure out how I should work with it. I tried such code in - (BOOL)acceptDrop:(id<NSDraggingInfo>)info method:
if ([info.draggingPasteboard.types containsObject:#"MV Super-secret message transfer pasteboard type"]) {
NSURL *tempFolder = [FM createTempFolderInFolder:AppDataDir()];
NSArray *filenames = [info namesOfPromisedFilesDroppedAtDestination:tempFolder];
// tempFolder is filepath of generated temp folder in appdata directory so it is accessible for sandboxed app
// filenames becomes nil
return YES;
}
When I try iterating through all types in pasteboard, that what I see:
Dropped types are:
Type: dyn.ah62d4rv4gu8y4zvanr41a3pwfz30n25wqz4ca5pfsr30c35feb4he2pssrxgn6vasbu1g7dfqm10c6xeeb4hw6df (null)
Type: MV Super-secret message transfer pasteboard type (null)
Type: dyn.ah62d4rv4gu8zg7puqz3c465fqr3gn7bakf41k55rqf4g86vasbu1g7dfqm10c6xeeb4hw6df (
{
account = Gmail;
id = 6622;
mailbox = INBOX;
subject = "got SUV?";
}
)
Type: Super-secret Automator pasteboard type (
{
account = Gmail;
id = 6622;
mailbox = INBOX;
subject = "got SUV?";
}
)
Type: dyn.ah62d4rv4gu8yc6durvwwa3xmrvw1gkdusm1044pxqyuha2pxsvw0e55bsmwca7d3sbwu (
eml
)
Type: Apple files promise pasteboard type (
eml
)
Type: public.url (null)
Type: CorePasteboardFlavorType 0x75726C20 (null)
Type: dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu (
"message:%3C1a392cb9-b78c-402d-8d7f-dbd1d4a9ec42#Neptune.do.losaltos.k12.ca.us%3E",
""
)
Type: Apple URL pasteboard type (
"message:%3C1a392cb9-b78c-402d-8d7f-dbd1d4a9ec42#Neptune.do.losaltos.k12.ca.us%3E",
""
)
Type: public.url-name (null)
Type: CorePasteboardFlavorType 0x75726C6E (null)
Type: com.apple.pasteboard.promised-file-content-type com.apple.mail.email
Type: com.apple.pasteboard.promised-file-url (null)
Type: dyn.ah62d4rv4gu8y6y4usm1044pxqzb085xyqz1hk64uqm10c6xenv61a3k (null)
Type: NSPromiseContentsPboardType (null)
Anyone could help me?

I just went through this process and it was pretty easy actually.
Look for "com.apple.pasteboard.promised-file-content-type = com.apple.mail.email" in the pasteboard types and if found simply call namesOfPromisedFilesDroppedAtDestination (from NSDraggingInfo) with the drop destination URL and the file will be created when the drag is finished.

Related

How to read file comment field

In OS X Finder there is 'Comment' file property. It can be checked in finder by adding 'Comment' column or edited/checked after right clicking on file or folder and selecting 'Get info'.
How to read this value in swift or objective-c?
I checked already NSURL and none of them seems to be the right ones
Do not use the low-level extended attributes API to read Spotlight metadata. There's a proper Spotlight API for that. (It's called the File Metadata API.) Not only is it a pain in the neck, there's no guarantee that Apple will keep using the same extended attribute to store this information.
Use MDItemCreateWithURL() to create an MDItem for the file. Use MDItemCopyAttribute() with kMDItemFinderComment to obtain the Finder comment for the item.
Putting the pieces together (Ken Thomases reading answer above and writing answer link) you can extend URL with a computed property with a getter and a setter to read/write comments to your files:
update: Xcode 8.2.1 • Swift 3.0.2
extension URL {
var finderComment: String? {
get {
guard isFileURL else { return nil }
return MDItemCopyAttribute(MDItemCreateWithURL(kCFAllocatorDefault, self as CFURL), kMDItemFinderComment) as? String
}
set {
guard isFileURL, let newValue = newValue else { return }
let script = "tell application \"Finder\"\n" +
String(format: "set filePath to \"%#\" as posix file \n", absoluteString) +
String(format: "set comment of (filePath as alias) to \"%#\" \n", newValue) +
"end tell"
guard let appleScript = NSAppleScript(source: script) else { return }
var error: NSDictionary?
appleScript.executeAndReturnError(&error)
if let error = error {
print(error[NSAppleScript.errorAppName] as! String)
print(error[NSAppleScript.errorBriefMessage] as! String)
print(error[NSAppleScript.errorMessage] as! String)
print(error[NSAppleScript.errorNumber] as! NSNumber)
print(error[NSAppleScript.errorRange] as! NSRange)
}
}
}
}
As explained in the various answers to Mac OS X : add a custom meta data field to any file,
Finder comments can be read and set programmatically with getxattr() and setxattr(). They are stored as extended attribute
"com.apple.metadata:kMDItemFinderComment", and the value is a property
list.
This works even for files not indexed by Spotlight, such as those on a network server volume.
From the Objective-C code here
and here I made this simple Swift function
to read the Finder comment (now updated for Swift 4 and later):
func finderComment(url : URL) -> String? {
let XAFinderComment = "com.apple.metadata:kMDItemFinderComment"
let data = url.withUnsafeFileSystemRepresentation { fileSystemPath -> Data? in
// Determine attribute size:
let length = getxattr(fileSystemPath, XAFinderComment, nil, 0, 0, 0)
guard length >= 0 else { return nil }
// Create buffer with required size:
var data = Data(count: length)
// Retrieve attribute:
let result = data.withUnsafeMutableBytes { [count = data.count] in
getxattr(fileSystemPath, XAFinderComment, $0.baseAddress, count, 0, 0)
}
guard result >= 0 else { return nil }
return data
}
// Deserialize to String:
guard let data = data, let comment = try? PropertyListSerialization.propertyList(from: data,
options: [], format: nil) as? String else {
return nil
}
return comment
}
Example usage:
let url = URL(fileURLWithPath: "/path/to/file")
if let comment = finderComment(url: url) {
print(comment)
}
The function returns an optional string which is nil if the file
has no Finder comment, or if anything went wrong while retrieving it.

How to retrieve vCard in xmpp , which delegate method and flow is use for get vCard in cocoa os x app?

I have implement xmpp framework in my cocoa os x application. currently am working on vCard. i have done work on set all required field's data of login user and it stored successfully, but i have no proper solution for how to get login user's stored vcard and am not aware of it. Please give me solution for this problem. i have been suffering for this from last 3 days. help me as soon as
Thanx in advance
i have used below code to set vCard field
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
dispatch_async(queue, ^
{
XMPPvCardCoreDataStorage *xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
XMPPvCardTempModule *xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
[xmppvCardTempModule activate:[self xmppStream]];
XMPPvCardTemp *myvCardTemp = [xmppvCardTempModule myvCardTemp];
if (!myvCardTemp)
{
NSXMLElement *vCardXML = [NSXMLElement elementWithName:#"vCard" xmlns:#"vcard-temp"];
XMPPvCardTemp *newvCardTemp = [XMPPvCardTemp vCardTempFromElement:vCardXML];
[newvCardTemp setName:#"vCard"];
[newvCardTemp setNickname:lbl.stringValue];
[newvCardTemp setFormattedName:#"abc"];
[newvCardTemp setDesc:lbl_abt.stringValue];
[xmppvCardTempModule updateMyvCardTemp:newvCardTemp];
}
else
{
[myvCardTemp setName:#"vCard"];
[myvCardTemp setNickname:lbl.stringValue];
[myvCardTemp setFormattedName:#"abc"];
[myvCardTemp setDesc:lbl_abt.stringValue];
[xmppvCardTempModule updateMyvCardTemp:myvCardTemp];
}
});
}
And i also tried below code to retrieve vCard
/* XMPPvCardTempModule *xmppvCardTempModule;
XMPPvCardTemp *vCard =[xmppvCardTempModule vCardTempForJID:[XMPPJID jidWithString:#"xxxx"] shouldFetch:YES];
NSLog(#"V CARD :%#",vCard.nickname);*/
XMPPvCardCoreDataStorage* xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
XMPPvCardTempModule* m = [[XMPPvCardTempModule alloc]initWithvCardStorage:xmppvCardStorage];
[m fetchvCardTempForJID:[XMPPJID jidWithString:#"xxxx"]ignoreStorage:YES];
NSLog(#"%#",xmppvCardStorage.description);
Please suggest me proper way to solve this problem :

Lotus/Domino User creation flag fREGExtMailReplicasUsingAdminp: How to specify replication details

I need to program a client to Domino Server using Notes C API which registers a new Lotus Notes user. Using REGNewUser (see http://www-12.lotus.com/ldd/doc/domino_notes/8.5.3/api853ref.nsf/ef2467c10609eaa8852561cc0067a76f/0326bfa2438ebe9985256678006a6ff2?OpenDocument&Highlight=0,REGNew*) and it looks promising except for the fact that I need to make the user's mail file replicate from the specified mail server to the mail server's cluster partner. There is the flag
fREGExtMailReplicasUsingAdminp
and the documentation is very brief about it:
"Create mail replicas via the administration process"
If I google the flag I get 4 (!) hits.
How do I specify where the mail file replica is created? Does anyone have any more information about what this flag is actually doing?
Thanks
Kai
After 3 weeks of research in the Notes C API reference I found:
In REGNewPerson there are 2 structures REG_MAIL_INFO_EXT and REG_PERSON_INFO and if you set the above mentioned flag in REG_PERSON_INFO then you have to provide a list of replica servers in REG_MAIL_INFO_EXT like this:
REG_MAIL_INFO_EXT mail_info, *pmail_info;
REG_PERSON_INFO person_info, *pperson_info;
...
pmail_info = &mail_info;
pperson_info = &person_info;
...
// pmail_info->pMailForwardAddress = NULL; // brauchen wir nicht.
pmail_info->pMailServerName = mailserver;
pmail_info->pMailTemplateName = mailfiletemplate;
// do the list crap for replica servers
if (error = ListAllocate (0, 0, FALSE, &hReplicaServers, &pList, &list_size)) {
goto __error;
}
OSUnlock (hReplicaServers);
pList = NULL;
if (error = ListAddEntry (hReplicaServers, // handle to list
FALSE, // do not include data type
&list_size, // pass list size in memory
0, // index to add
replicationserver, // value to add
(WORD) strlen(replicationserver))) // size of value to add
{
goto __error;
}
// now we can add the handle to the structure
pmail_info->hReplicaServers = hReplicaServers;
...
pperson_info->MailInfo = pmail_info;
...
pperson_info->Flags = fREGCreateIDFileNow | fREGCreateAddrBookEntry | fREGCreateMailFileUsingAdminp;
pperson_info->FlagsExt = fREGExtEnforceUniqueShortName | fREGExtMailReplicasUsingAdminp;
In my case this did the trick.

How to turn a Rails JSON object into readable JSON using Objective -c

I'm using NSRails in Objective -c:
NSError *error;
posts = [NSMutableArray arrayWithArray:[Post remoteAll:&error]];
NSLog(#"%#", posts);
I'm getting this back:
2013-10-07 22:03:11.377 MyBlog[19411:303] [NSRails][OUT] ===> GET to http://localhost:3000/posts
2013-10-07 22:03:11.813 MyBlogr[19411:303] (
"<Post: 0x101a0eb80>"
)
How would I take something like this "<Post: 0x101a0eb80>" and turn it into normal JSON?
It's weird because when I go to http://localhost:3000/posts.json (or without the ext. ".json"), I get this:
{
id: 1,
created_at: "2013-10-06T22:18:24.219Z",
updated_at: "2013-10-06T22:18:24.219Z",
galleries: [
{
id: 1,
name: "my gallery",
user_id: 1,
post_id: 1,
created_at: "2013-10-06T22:20:54.446Z",
updated_at: "2013-10-06T22:20:54.446Z"
},
Calling NSLog like:
NSLog(#"%#", posts);
Is not going to serialize your object into JSON. It's simply going to try and display a description of the object. In this case, a description of an NSArray.
It is not clear to me why you're trying to get the JSON back. Are you simply trying to verify that your object is properly instantiated and contains the data you expect?
Set a breakpoint on your NSLog statement. Once the debugger stops, try:
po [posts objectAtIndex:0].name
This should confirm that the name property is "my gallery". However, if you really want to get JSON back from your object you'll want to look at NSJson.

NSManaged object sometimes is null and causes crash

I am using coredata and often my app crashes because one of the properties of a managed object turn out null. For example when i set text of a UILabel to a text property of the managed object it displays NULL
To find the problem I overrode the setter which assigns the NSManagedObject to a instance variable. In the setter I use NSLog to print the object:
NSLog(#"TSC: setting segment: %#", segment);
its output:
2012-11-05 21:01:56.758 JetLagged[4505:907] TSC: setting segment: <Segment: 0x1d0ab790> (entity: Segment; id: 0x1d0a7f60 <x-coredata://BF6F2D98-0658-4005-8BEF-9FE6B398AF86/Segment/p8> ; data: {
arrivalDate = "2012-11-11 05:00:17 +0000";
arrivalLeg = "0x1d0abba0 <x-coredata://BF6F2D98-0658-4005-8BEF-9FE6B398AF86/IteneryLeg/p11>";
departureDate = "2012-11-10 19:00:17 +0000";
departureLeg = "0x1d0abba0 <x-coredata://BF6F2D98-0658-4005-8BEF-9FE6B398AF86/IteneryLeg/p11>";
iteneryLegs = (
"0x1d0abba0 <x-coredata://BF6F2D98-0658-4005-8BEF-9FE6B398AF86/IteneryLeg/p11>"
);
trip = "0x1c58add0 <x-coredata://BF6F2D98-0658-4005-8BEF-9FE6B398AF86/Trip/p5>";
})
All looks fine, however app still displayes null in some places or crashes. I catch the problem I added some NSAsserts and when I ran the code below in the same run as the output above it failed the assertion. Here is the assert code (segmentToCheck is segment from above).
NSSet *legs = [segmentToCheck valueForKey:#"iteneryLegs"];
NSAssert([legs count] != 0, #"Error: nolegs %#", legs);
its output:
2012-11-05 21:01:56.763 JetLagged[4505:907] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error: nolegs (null)'
When i run the app again (without any data modification) it works fine. Any idea what it might be?
Looks like a typo: #"itineryLegs" instead of #"iteneryLegs".