Initial QSfera import
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
|
||||
#import "SyncClientProxy.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <FinderSync/FinderSync.h>
|
||||
|
||||
@interface FinderSync : FIFinderSync <SyncClientProxyDelegate> {
|
||||
SyncClientProxy *_syncClientProxy;
|
||||
NSMutableSet *_registeredDirectories;
|
||||
NSString *_shareMenuTitle;
|
||||
NSMutableDictionary *_strings;
|
||||
NSMutableArray *_menuItems;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
|
||||
#import "FinderSync.h"
|
||||
|
||||
|
||||
@implementation FinderSync
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
|
||||
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
|
||||
// This was added to the bundle's Info.plist to get it from the build system
|
||||
NSString *socketApiPrefix = [extBundle objectForInfoDictionaryKey:@"SocketApiPrefix"];
|
||||
|
||||
NSImage *ok = [extBundle imageForResource:@"ok.icns"];
|
||||
NSImage *ok_swm = [extBundle imageForResource:@"ok_swm.icns"];
|
||||
NSImage *sync = [extBundle imageForResource:@"sync.icns"];
|
||||
NSImage *warning = [extBundle imageForResource:@"warning.icns"];
|
||||
NSImage *error = [extBundle imageForResource:@"error.icns"];
|
||||
|
||||
[syncController setBadgeImage:ok label:@"Up to date" forBadgeIdentifier:@"OK"];
|
||||
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC"];
|
||||
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW"];
|
||||
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE"];
|
||||
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR"];
|
||||
[syncController setBadgeImage:ok_swm label:@"Shared" forBadgeIdentifier:@"OK+SWM"];
|
||||
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC+SWM"];
|
||||
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW+SWM"];
|
||||
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE+SWM"];
|
||||
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR+SWM"];
|
||||
|
||||
// The Mach port name needs to:
|
||||
// - Be prefixed with the code signing Team ID
|
||||
// - Then infixed with the sandbox App Group
|
||||
// - The App Group itself must be a prefix of (or equal to) the application bundle identifier
|
||||
// We end up in the official signed client with: 9B5WD74GWJ.eu.qsfera.desktop.socketApi
|
||||
// With ad-hoc signing (the '-' signing identity) we must drop the Team ID.
|
||||
// When the code isn't sandboxed (e.g. the OC client or the legacy overlay icon extension)
|
||||
// the OS doesn't seem to put any restriction on the port name, so we just follow what
|
||||
// the sandboxed App Extension needs.
|
||||
// https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
|
||||
NSString *serverName = [socketApiPrefix stringByAppendingString:@".socketApi"];
|
||||
// NSLog(@"FinderSync serverName %@", serverName);
|
||||
|
||||
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
|
||||
_registeredDirectories = [[NSMutableSet alloc] init];
|
||||
_strings = [[NSMutableDictionary alloc] init];
|
||||
|
||||
[_syncClientProxy start];
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Primary Finder Sync protocol methods
|
||||
|
||||
- (void)requestBadgeIdentifierForURL:(NSURL *)url
|
||||
{
|
||||
BOOL isDir;
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir] == NO) {
|
||||
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
|
||||
isDir = NO;
|
||||
}
|
||||
|
||||
NSString *normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
|
||||
[_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
|
||||
}
|
||||
|
||||
#pragma mark - Menu and toolbar item support
|
||||
|
||||
- (NSString *)selectedPathsSeparatedByRecordSeparator
|
||||
{
|
||||
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
|
||||
NSMutableString *string = [[NSMutableString alloc] init];
|
||||
[syncController.selectedItemURLs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if (string.length > 0) {
|
||||
[string appendString:@"\x1e"]; // record separator
|
||||
}
|
||||
NSString *normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
|
||||
[string appendString:normalizedPath];
|
||||
}];
|
||||
return string;
|
||||
}
|
||||
|
||||
- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
|
||||
{
|
||||
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
|
||||
NSMutableSet *rootPaths = [[NSMutableSet alloc] init];
|
||||
[syncController.directoryURLs enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { [rootPaths addObject:[obj path]]; }];
|
||||
|
||||
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
|
||||
// calling this IPC calls us back from client with several MENU_ITEM entries and then our askOnSocket returns again
|
||||
[_syncClientProxy askOnSocket:paths query:@"GET_MENU_ITEMS"];
|
||||
|
||||
id contextMenuTitle = [_strings objectForKey:@"CONTEXT_MENU_TITLE"];
|
||||
if (contextMenuTitle && _menuItems.count != 0) {
|
||||
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
|
||||
NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@""];
|
||||
NSMenuItem *subMenuItem = [menu addItemWithTitle:contextMenuTitle action:nil keyEquivalent:@""];
|
||||
subMenuItem.submenu = subMenu;
|
||||
subMenuItem.image = [[NSBundle mainBundle] imageForResource:@"app.icns"];
|
||||
|
||||
// There is an annoying bug in macOS (at least 10.13.3), it does not use/copy over the representedObject of a menu item
|
||||
// So we have to use tag instead.
|
||||
int idx = 0;
|
||||
for (NSArray *item in _menuItems) {
|
||||
NSMenuItem *actionItem = [subMenu addItemWithTitle:[item valueForKey:@"text"] action:@selector(subMenuActionClicked:) keyEquivalent:@""];
|
||||
[actionItem setTag:idx];
|
||||
[actionItem setTarget:self];
|
||||
NSString *flags = [item valueForKey:@"flags"]; // e.g. "d"
|
||||
if ([flags rangeOfString:@"d"].location != NSNotFound) {
|
||||
[actionItem setEnabled:false];
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)subMenuActionClicked:(id)sender
|
||||
{
|
||||
long idx = [(NSMenuItem *)sender tag];
|
||||
NSString *command = [[_menuItems objectAtIndex:idx] valueForKey:@"command"];
|
||||
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
|
||||
[_syncClientProxy askOnSocket:paths query:command];
|
||||
}
|
||||
|
||||
#pragma mark - SyncClientProxyDelegate implementation
|
||||
|
||||
- (void)setResultForPath:(NSString *)path result:(NSString *)result
|
||||
{
|
||||
NSString *normalizedPath = [path decomposedStringWithCanonicalMapping];
|
||||
[[FIFinderSyncController defaultController] setBadgeIdentifier:result forURL:[NSURL fileURLWithPath:normalizedPath]];
|
||||
}
|
||||
|
||||
- (void)reFetchFileNameCacheForPath:(NSString *)path
|
||||
{
|
||||
}
|
||||
|
||||
- (void)registerPath:(NSString *)path
|
||||
{
|
||||
assert(_registeredDirectories);
|
||||
[_registeredDirectories addObject:[NSURL fileURLWithPath:path]];
|
||||
[FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
|
||||
}
|
||||
|
||||
- (void)unregisterPath:(NSString *)path
|
||||
{
|
||||
[_registeredDirectories removeObject:[NSURL fileURLWithPath:path]];
|
||||
[FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
|
||||
}
|
||||
|
||||
- (void)setString:(NSString *)key value:(NSString *)value
|
||||
{
|
||||
[_strings setObject:value forKey:key];
|
||||
}
|
||||
|
||||
- (void)resetMenuItems
|
||||
{
|
||||
_menuItems = [[NSMutableArray alloc] init];
|
||||
}
|
||||
- (void)addMenuItem:(NSDictionary *)item
|
||||
{
|
||||
[_menuItems addObject:item];
|
||||
}
|
||||
|
||||
- (void)connectionDidDie
|
||||
{
|
||||
[_strings removeAllObjects];
|
||||
[_registeredDirectories removeAllObjects];
|
||||
// For some reason the FIFinderSync cache doesn't seem to be cleared for the root item when
|
||||
// we reset the directoryURLs (seen on macOS 10.12 at least).
|
||||
// First setting it to the FS root and then setting it to nil seems to work around the issue.
|
||||
[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:@"/"]];
|
||||
// This will tell Finder that this extension isn't attached to any directory
|
||||
// until we can reconnect to the sync client.
|
||||
[FIFinderSyncController defaultController].directoryURLs = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?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>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?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>SocketApiPrefix</key>
|
||||
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(OC_APPLICATION_NAME) Extensions</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict/>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.FinderSync</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>FinderSync</string>
|
||||
</dict>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@protocol SyncClientProxyDelegate <NSObject>
|
||||
- (void)setResultForPath:(NSString *)path result:(NSString *)result;
|
||||
- (void)reFetchFileNameCacheForPath:(NSString *)path;
|
||||
- (void)registerPath:(NSString *)path;
|
||||
- (void)unregisterPath:(NSString *)path;
|
||||
- (void)setString:(NSString *)key value:(NSString *)value;
|
||||
- (void)resetMenuItems;
|
||||
- (void)addMenuItem:(NSDictionary *)item;
|
||||
- (void)connectionDidDie;
|
||||
@end
|
||||
|
||||
@protocol ChannelProtocol <NSObject>
|
||||
- (void)sendMessage:(NSData *)msg;
|
||||
@end
|
||||
|
||||
@interface SyncClientProxy : NSObject <ChannelProtocol> {
|
||||
NSString *_serverName;
|
||||
NSDistantObject<ChannelProtocol> *_remoteEnd;
|
||||
}
|
||||
|
||||
@property (weak) id<SyncClientProxyDelegate> delegate;
|
||||
|
||||
- (instancetype)initWithDelegate:(id)arg1 serverName:(NSString *)serverName;
|
||||
- (void)start;
|
||||
- (void)askOnSocket:(NSString *)path query:(NSString *)verb;
|
||||
- (void)askForIcon:(NSString *)path isDirectory:(BOOL)isDir;
|
||||
@end
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#import "SyncClientProxy.h"
|
||||
|
||||
@protocol ServerProtocol <NSObject>
|
||||
- (void)registerClient:(id)client;
|
||||
@end
|
||||
|
||||
@interface SyncClientProxy ()
|
||||
- (void)registerTransmitter:(id)tx;
|
||||
@end
|
||||
|
||||
@implementation SyncClientProxy
|
||||
|
||||
- (instancetype)initWithDelegate:(id)arg1 serverName:(NSString *)serverName
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
self.delegate = arg1;
|
||||
_serverName = serverName;
|
||||
_remoteEnd = nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Connection setup
|
||||
|
||||
- (void)start
|
||||
{
|
||||
if (_remoteEnd)
|
||||
return;
|
||||
|
||||
// Lookup the server connection
|
||||
NSConnection *conn = [NSConnection connectionWithRegisteredName:_serverName host:nil];
|
||||
|
||||
if (!conn) {
|
||||
// Could not connect to the sync client
|
||||
[self scheduleRetry];
|
||||
return;
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectionDidDie:) name:NSConnectionDidDieNotification object:conn];
|
||||
|
||||
NSDistantObject<ServerProtocol> *server = (NSDistantObject<ServerProtocol> *)[conn rootProxy];
|
||||
assert(server);
|
||||
|
||||
// This saves a few Mach messages, enable "Distributed Objects" in the scheme's Run diagnostics to watch
|
||||
[server setProtocolForProxy:@protocol(ServerProtocol)];
|
||||
|
||||
// Send an object to the server to act as the channel rx, we'll receive the tx through registerTransmitter
|
||||
[server registerClient:self];
|
||||
}
|
||||
|
||||
- (void)registerTransmitter:(id)tx;
|
||||
{
|
||||
// The server replied with the distant object that we will use for tx
|
||||
_remoteEnd = (NSDistantObject<ChannelProtocol> *)tx;
|
||||
[_remoteEnd setProtocolForProxy:@protocol(ChannelProtocol)];
|
||||
|
||||
// Everything is set up, start querying
|
||||
[self askOnSocket:@"" query:@"GET_STRINGS"];
|
||||
}
|
||||
|
||||
- (void)scheduleRetry
|
||||
{
|
||||
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(start) userInfo:nil repeats:NO];
|
||||
}
|
||||
|
||||
- (void)connectionDidDie:(NSNotification *)notification
|
||||
{
|
||||
#pragma unused(notification)
|
||||
_remoteEnd = nil;
|
||||
[_delegate connectionDidDie];
|
||||
|
||||
[self scheduleRetry];
|
||||
}
|
||||
|
||||
#pragma mark - Communication logic
|
||||
|
||||
- (void)sendMessage:(NSData *)msg
|
||||
{
|
||||
NSString *answer = [[NSString alloc] initWithData:msg encoding:NSUTF8StringEncoding];
|
||||
|
||||
// Cut the trailing newline. We always only receive one line from the client.
|
||||
answer = [answer substringToIndex:[answer length] - 1];
|
||||
NSArray *chunks = [answer componentsSeparatedByString:@":"];
|
||||
|
||||
if ([[chunks objectAtIndex:0] isEqualToString:@"STATUS"]) {
|
||||
NSString *result = [chunks objectAtIndex:1];
|
||||
NSString *path = [chunks objectAtIndex:2];
|
||||
if ([chunks count] > 3) {
|
||||
for (int i = 2; i < [chunks count] - 1; i++) {
|
||||
path = [NSString stringWithFormat:@"%@:%@", path, [chunks objectAtIndex:i + 1]];
|
||||
}
|
||||
}
|
||||
[_delegate setResultForPath:path result:result];
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"UPDATE_VIEW"]) {
|
||||
NSString *path = [chunks objectAtIndex:1];
|
||||
[_delegate reFetchFileNameCacheForPath:path];
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"REGISTER_PATH"]) {
|
||||
NSString *path = [chunks objectAtIndex:1];
|
||||
[_delegate registerPath:path];
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"UNREGISTER_PATH"]) {
|
||||
NSString *path = [chunks objectAtIndex:1];
|
||||
[_delegate unregisterPath:path];
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"GET_STRINGS"]) {
|
||||
// BEGIN and END messages, do nothing.
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"STRING"]) {
|
||||
[_delegate setString:[chunks objectAtIndex:1] value:[chunks objectAtIndex:2]];
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"GET_MENU_ITEMS"]) {
|
||||
if ([[chunks objectAtIndex:1] isEqualToString:@"BEGIN"]) {
|
||||
[_delegate resetMenuItems];
|
||||
} else if ([[chunks objectAtIndex:1] isEqualToString:@"END"]) {
|
||||
// Don't do anything special, the askOnSocket call in FinderSync menuForMenuKind will return after this line
|
||||
}
|
||||
} else if ([[chunks objectAtIndex:0] isEqualToString:@"MENU_ITEM"]) {
|
||||
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
|
||||
[item setValue:[chunks objectAtIndex:1] forKey:@"command"]; // e.g. "COPY_PRIVATE_LINK"
|
||||
[item setValue:[chunks objectAtIndex:2] forKey:@"flags"]; // e.g. "d"
|
||||
[item setValue:[chunks objectAtIndex:3] forKey:@"text"]; // e.g. "Copy private link to clipboard"
|
||||
[_delegate addMenuItem:item];
|
||||
} else {
|
||||
NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)askOnSocket:(NSString *)path query:(NSString *)verb
|
||||
{
|
||||
NSString *query = [NSString stringWithFormat:@"%@:%@\n", verb, path];
|
||||
|
||||
@try {
|
||||
[_remoteEnd sendMessage:[query dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
} @catch (NSException *e) {
|
||||
// Do nothing and wait for connectionDidDie
|
||||
}
|
||||
}
|
||||
|
||||
- (void)askForIcon:(NSString *)path isDirectory:(BOOL)isDir
|
||||
{
|
||||
NSString *verb = isDir ? @"RETRIEVE_FOLDER_STATUS" : @"RETRIEVE_FILE_STATUS";
|
||||
[self askOnSocket:path query:verb];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user