Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Cambra <claudio.cambra@gmail.com>2022-02-23 20:38:22 +0300
committerClaudio Cambra (Rebase PR Action) <claudio.cambra@gmail.com>2022-03-17 14:46:57 +0300
commit628ee10008917cc73d9ae1daaacde66285176698 (patch)
tree27d6cf999e81ac5f56c76353f140beec5229242f /shell_integration
parent6aefe8f2e36bb1f8c81647f736e7a05f6ddbab8e (diff)
Implement local socket to communicate with finder extension
Signed-off-by: Claudio Cambra <claudio.cambra@gmail.com>
Diffstat (limited to 'shell_integration')
-rw-r--r--shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist8
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h19
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m61
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h33
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m99
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h62
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m308
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClient.h27
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h45
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m161
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj76
-rw-r--r--shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme18
12 files changed, 674 insertions, 243 deletions
diff --git a/shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloud.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?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>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
index 803c5270f..4cf5765bd 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.h
@@ -15,15 +15,20 @@
#import <Cocoa/Cocoa.h>
#import <FinderSync/FinderSync.h>
-#import "SyncClientProxy.h"
+#import "SyncClient.h"
+#import "LineProcessor.h"
+#import "LocalSocketClient.h"
-@interface FinderSync : FIFinderSync <SyncClientProxyDelegate>
+@interface FinderSync : FIFinderSync <SyncClientDelegate>
{
- SyncClientProxy *_syncClientProxy;
- NSMutableSet *_registeredDirectories;
- NSString *_shareMenuTitle;
- NSMutableDictionary *_strings;
- NSMutableArray *_menuItems;
+ NSMutableSet *_registeredDirectories;
+ NSString *_shareMenuTitle;
+ NSMutableDictionary *_strings;
+ NSMutableArray *_menuItems;
+ NSCondition *_menuIsComplete;
}
+@property LineProcessor *lineProcessor;
+@property LocalSocketClient *localSocketClient;
+
@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
index a0f791882..1da21a9d3 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/FinderSync.m
@@ -48,21 +48,32 @@
// - 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.com.owncloud.desktopclient.socketApi
+ // We end up in the official signed client with: 9B5WD74GWJ.com.owncloud.desktopclient.socket
// 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;
+
+ NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:socketApiPrefix];
+ NSURL *socketPath = [container URLByAppendingPathComponent:@".socket" isDirectory:NO];
+
+ NSLog(@"Socket path: %@", socketPath.path);
+
+ if (socketPath.path) {
+ self.lineProcessor = [[LineProcessor alloc] initWithDelegate:self];
+ self.localSocketClient = [[LocalSocketClient alloc] init:socketPath.path
+ lineProcessor:self.lineProcessor];
+ [self.localSocketClient start];
+ } else {
+ NSLog(@"No socket path. Not initiating local socket client.");
+ self.localSocketClient = nil;
+ }
+ _registeredDirectories = [[NSMutableSet alloc] init];
+ _strings = [[NSMutableDictionary alloc] init];
+ _menuIsComplete = [[NSCondition alloc] init];
+
+ return self;
}
#pragma mark - Primary Finder Sync protocol methods
@@ -76,7 +87,7 @@
}
NSString* normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
- [_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
+ [self.localSocketClient askForIcon:normalizedPath isDirectory:isDir];
}
#pragma mark - Menu and toolbar item support
@@ -95,8 +106,19 @@
return string;
}
+- (void)waitForMenuToArrive
+{
+ [self->_menuIsComplete lock];
+ [self->_menuIsComplete wait];
+ [self->_menuIsComplete unlock];
+}
+
- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
{
+ if(![self.localSocketClient isConnected]) {
+ return nil;
+ }
+
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSMutableSet *rootPaths = [[NSMutableSet alloc] init];
[syncController.directoryURLs enumerateObjectsUsingBlock: ^(id obj, BOOL *stop) {
@@ -116,8 +138,11 @@
}];
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"];
+ [self.localSocketClient askOnSocket:paths query:@"GET_MENU_ITEMS"];
+
+ // Since the LocalSocketClient communicates asynchronously. wait here until the menu
+ // is delivered by another thread
+ [self waitForMenuToArrive];
id contextMenuTitle = [_strings objectForKey:@"CONTEXT_MENU_TITLE"];
if (contextMenuTitle && !onlyRootsSelected) {
@@ -151,7 +176,7 @@
long idx = [(NSMenuItem*)sender tag];
NSString *command = [[_menuItems objectAtIndex:idx] valueForKey:@"command"];
NSString *paths = [self selectedPathsSeparatedByRecordSeparator];
- [_syncClientProxy askOnSocket:paths query:command];
+ [self.localSocketClient askOnSocket:paths query:command];
}
#pragma mark - SyncClientProxyDelegate implementation
@@ -164,6 +189,7 @@
- (void)reFetchFileNameCacheForPath:(NSString*)path
{
+
}
- (void)registerPath:(NSString*)path
@@ -189,9 +215,16 @@
_menuItems = [[NSMutableArray alloc] init];
}
- (void)addMenuItem:(NSDictionary *)item {
+ NSLog(@"Adding menu item.");
[_menuItems addObject:item];
}
+- (void)menuHasCompleted
+{
+ NSLog(@"Emitting menu is complete signal now.");
+ [self->_menuIsComplete signal];
+}
+
- (void)connectionDidDie
{
[_strings removeAllObjects];
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h
new file mode 100644
index 000000000..137ce62de
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.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 "SyncClient.h"
+
+#ifndef LineProcessor_h
+#define LineProcessor_h
+
+/// This class is in charge of dispatching all work that must be done on the UI side of the extension.
+/// Tasks are dispatched on the main UI thread for this reason.
+///
+/// These tasks are parsed from byte data (UTF9 strings) acquired from the socket; look at the
+/// LocalSocketClient for more detail on how data is read from and written to the socket.
+
+@interface LineProcessor : NSObject
+@property(nonatomic, weak)id<SyncClientDelegate> delegate;
+
+- (instancetype)initWithDelegate:(id<SyncClientDelegate>)delegate;
+- (void)process:(NSString*)line;
+
+@end
+#endif /* LineProcessor_h */
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m
new file mode 100644
index 000000000..f67642e7c
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LineProcessor.m
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.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>
+#import "LineProcessor.h"
+
+@implementation LineProcessor
+
+-(instancetype)initWithDelegate:(id<SyncClientDelegate>)delegate
+{
+ NSLog(@"Init line processor with delegate.");
+ self.delegate = delegate;
+ return self;
+}
+
+-(void)process:(NSString*)line
+{
+ NSLog(@"Processing line: %@", line);
+ NSArray *split = [line componentsSeparatedByString:@":"];
+ NSString *command = [split objectAtIndex:0];
+
+ NSLog(@"Command: %@", command);
+
+ if([command isEqualToString:@"STATUS"]) {
+ NSString *result = [split objectAtIndex:1];
+ NSArray *pathSplit = [split subarrayWithRange:NSMakeRange(2, [split count] - 2)]; // Get everything after location 2
+ NSString *path = [pathSplit componentsJoinedByString:@":"];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Setting result %@ for path %@", result, path);
+ [self.delegate setResultForPath:path result:result];
+ });
+ } else if([command isEqualToString:@"UPDATE_VIEW"]) {
+ NSString *path = [split objectAtIndex:1];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Re-fetching filename cache for path %@", path);
+ [self.delegate reFetchFileNameCacheForPath:path];
+ });
+ } else if([command isEqualToString:@"REGISTER_PATH"]) {
+ NSString *path = [split objectAtIndex:1];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Registering path %@", path);
+ [self.delegate registerPath:path];
+ });
+ } else if([command isEqualToString:@"UNREGISTER_PATH"]) {
+ NSString *path = [split objectAtIndex:1];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Unregistering path %@", path);
+ [self.delegate unregisterPath:path];
+ });
+ } else if([command isEqualToString:@"GET_STRINGS"]) {
+ // BEGIN and END messages, do nothing.
+ return;
+ } else if([command isEqualToString:@"STRING"]) {
+ NSString *key = [split objectAtIndex:1];
+ NSString *value = [split objectAtIndex:2];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Setting string %@ to value %@", key, value);
+ [self.delegate setString:key value:value];
+ });
+ } else if([command isEqualToString:@"GET_MENU_ITEMS"]) {
+ if([[split objectAtIndex:1] isEqualToString:@"BEGIN"]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Resetting menu items.");
+ [self.delegate resetMenuItems];
+ });
+ } else {
+ NSLog(@"Emitting menu has completed signal.");
+ [self.delegate menuHasCompleted];
+ }
+ } else if([command isEqualToString:@"MENU_ITEM"]) {
+ NSDictionary *item = @{@"command": [split objectAtIndex:1], @"flags": [split objectAtIndex:2], @"text": [split objectAtIndex:3]};
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"Adding menu item with command %@, flags %@, and text %@", [split objectAtIndex:1], [split objectAtIndex:2], [split objectAtIndex:3]);
+ [self.delegate addMenuItem:item];
+ });
+ } else {
+ // LOG UNKOWN COMMAND
+ NSLog(@"Unkown command: %@", command);
+ }
+}
+
+@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h
new file mode 100644
index 000000000..4a858cda2
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.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 "LineProcessor.h"
+
+#ifndef LocalSocketClient_h
+#define LocalSocketClient_h
+#define BUF_SIZE 4096
+
+/// Class handling asynchronous communication with a server over a local UNIX socket.
+///
+/// The implementation uses a `DispatchQueue` and `DispatchSource`s to handle asynchronous communication and thread
+/// safety. The delegate that handles the line-decoding is **not invoked on the UI thread**, but the (random) thread associated
+/// with the `DispatchQueue`.
+///
+/// If any UI work needs to be done, the `LineProcessor` class dispatches this work on the main queue (so the UI thread) itself.
+///
+/// Other than the `init(withSocketPath:, lineProcessor)` and the `start()` method, all work is done "on the dispatch
+/// queue". The `localSocketQueue` is a serial dispatch queue (so a maximum of 1, and only 1, task is run at any
+/// moment), which guarantees safe access to instance variables. Both `askOnSocket(_:, query:)` and
+/// `askForIcon(_:, isDirectory:)` will internally dispatch the work on the `DispatchQueue`.
+///
+/// Sending and receiving data to and from the socket, is handled by two `DispatchSource`s. These will run an event
+/// handler when data can be read from resp. written to the socket. These handlers will also be run on the
+/// `DispatchQueue`.
+
+@interface LocalSocketClient : NSObject
+
+@property NSString* socketPath;
+@property LineProcessor* lineProcessor;
+@property int sock;
+@property dispatch_queue_t localSocketQueue;
+@property dispatch_source_t readSource;
+@property dispatch_source_t writeSource;
+@property NSMutableData* inBuffer;
+@property NSMutableData* outBuffer;
+
+- (instancetype)init:(NSString*)socketPath lineProcessor:(LineProcessor*)lineProcessor;
+- (BOOL)isConnected;
+- (void)start;
+- (void)restart;
+- (void)closeConnection;
+- (NSString*)strErr;
+- (void)askOnSocket:(NSString*)path query:(NSString*)verb;
+- (void)askForIcon:(NSString*)path isDirectory:(BOOL)isDirectory;
+- (void)readFromSocket;
+- (void)writeToSocket;
+- (void)processInBuffer;
+
+@end
+#endif /* LocalSocketClient_h */
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m
new file mode 100644
index 000000000..ad3cc1cde
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/LocalSocketClient.m
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2022 by Claudio Cambra <claudio.cambra@nextcloud.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>
+#import "LocalSocketClient.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <string.h>
+
+@implementation LocalSocketClient
+
+- (instancetype)init:(NSString*)socketPath lineProcessor:(LineProcessor*)lineProcessor
+{
+ NSLog(@"Initiating local socket client.");
+ self = [super init];
+
+ if(self) {
+ self.socketPath = socketPath;
+ self.lineProcessor = lineProcessor;
+
+ self.sock = -1;
+ self.localSocketQueue = dispatch_queue_create("localSocketQueue", DISPATCH_QUEUE_SERIAL);
+
+ self.inBuffer = [NSMutableData data];
+ self.outBuffer = [NSMutableData data];
+ }
+
+ return self;
+}
+
+- (BOOL)isConnected
+{
+ NSLog(@"Checking is connected: %@", self.sock != -1 ? @"YES" : @"NO");
+ return self.sock != -1;
+}
+
+- (void)start
+{
+ if([self isConnected]) {
+ NSLog(@"Socket client already connected. Not starting.");
+ return;
+ }
+
+ struct sockaddr_un localSocketAddr;
+ unsigned long socketPathByteCount = [self.socketPath lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; // add 1 for the NUL terminator char
+ int maxByteCount = sizeof(localSocketAddr.sun_path);
+
+ if(socketPathByteCount > maxByteCount) {
+ // LOG THAT THE SOCKET PATH IS TOO LONG HERE
+ NSLog(@"Socket path '%@' is too long: maximum socket path length is %i, this path is of length %lu", self.socketPath, maxByteCount, socketPathByteCount);
+ return;
+ }
+
+ NSLog(@"Opening local socket...");
+
+ // LOG THAT THE SOCKET IS BEING OPENED HERE
+ self.sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+
+ if(self.sock == -1) {
+ NSLog(@"Cannot open socket: '%@'", [self strErr]);
+ [self restart];
+ return;
+ }
+
+ NSLog(@"Local socket opened. Connecting to '%@' ...", self.socketPath);
+
+ localSocketAddr.sun_family = AF_LOCAL & 0xff;
+
+ const char* pathBytes = [self.socketPath UTF8String];
+ strcpy(localSocketAddr.sun_path, pathBytes);
+
+ int connectionStatus = connect(self.sock, (struct sockaddr*)&localSocketAddr, sizeof(localSocketAddr));
+
+ if(connectionStatus == -1) {
+ NSLog(@"Could not connect to '%@': '%@'", self.socketPath, [self strErr]);
+ [self restart];
+ return;
+ }
+
+ int flags = fcntl(self.sock, F_GETFL, 0);
+
+ if(fcntl(self.sock, F_SETFL, flags | O_NONBLOCK) == -1) {
+ NSLog(@"Could not set socket to non-blocking mode: '%@'", [self strErr]);
+ [self restart];
+ return;
+ }
+
+ NSLog(@"Connected to socket. Setting up dispatch sources...");
+
+ self.readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, self.sock, 0, self.localSocketQueue);
+ dispatch_source_set_event_handler(self.readSource, ^(void){ [self readFromSocket]; });
+ dispatch_source_set_cancel_handler(self.readSource, ^(void){
+ self.readSource = nil;
+ [self closeConnection];
+ });
+
+ self.writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, self.sock, 0, self.localSocketQueue);
+ dispatch_source_set_event_handler(self.writeSource, ^(void){ [self writeToSocket]; });
+ dispatch_source_set_cancel_handler(self.writeSource, ^(void){
+ self.writeSource = nil;
+ [self closeConnection];
+ });
+
+ // These dispatch sources are suspended upon creation.
+ // We resume the writeSource when we actually have something to write, suspending it again once our outBuffer is empty.
+ // We start the readSource now.
+
+ NSLog(@"Starting to read from socket");
+
+ dispatch_resume(self.readSource);
+ [self askOnSocket:@"" query:@"GET_STRINGS"];
+}
+
+- (void)restart
+{
+ NSLog(@"Restarting connection to socket.");
+ [self closeConnection];
+ dispatch_async(dispatch_get_main_queue(), ^(void){
+ [NSTimer scheduledTimerWithTimeInterval:5 repeats:NO block:^(NSTimer* timer) {
+ [self start];
+ }];
+ });
+}
+
+- (void)closeConnection
+{
+ NSLog(@"Closing connection.");
+ dispatch_source_cancel(self.readSource);
+ dispatch_source_cancel(self.writeSource);
+ self.readSource = nil;
+ self.writeSource = nil;
+ [self.inBuffer setLength:0];
+ [self.outBuffer setLength: 0];
+
+ if(self.sock != -1) {
+ close(self.sock);
+ self.sock = -1;
+ }
+}
+
+- (NSString*)strErr
+{
+ int err = errno;
+ const char *errStr = strerror(err);
+ NSString *errorStr = [NSString stringWithUTF8String:errStr];
+
+ if([errorStr length] == 0) {
+ return errorStr;
+ } else {
+ return [NSString stringWithFormat:@"Unknown error code: %i", err];
+ }
+}
+
+- (void)askOnSocket:(NSString *)path query:(NSString *)verb
+{
+ NSString *line = [NSString stringWithFormat:@"%@:%@\n", verb, path];
+ dispatch_async(self.localSocketQueue, ^(void) {
+ if(![self isConnected]) {
+ return;
+ }
+
+ BOOL writeSourceIsSuspended = [self.outBuffer length] == 0;
+
+ [self.outBuffer appendData:[line dataUsingEncoding:NSUTF8StringEncoding]];
+
+ NSLog(@"Writing to out buffer: '%@'", line);
+ NSLog(@"Out buffer now %li bytes", [self.outBuffer length]);
+
+ if(writeSourceIsSuspended) {
+ NSLog(@"Resuming write dispatch source.");
+ dispatch_resume(self.writeSource);
+ }
+ });
+}
+
+- (void)writeToSocket
+{
+ if(![self isConnected]) {
+ return;
+ }
+
+ if([self.outBuffer length] == 0) {
+ NSLog(@"Empty out buffer, suspending write dispatch source.");
+ dispatch_suspend(self.writeSource);
+ return;
+ }
+
+ NSLog(@"About to write %li bytes from outbuffer to socket.", [self.outBuffer length]);
+
+ long bytesWritten = write(self.sock, [self.outBuffer bytes], [self.outBuffer length]);
+ char lineWritten[4096];
+ memcpy(lineWritten, [self.outBuffer bytes], [self.outBuffer length]);
+ NSLog(@"Wrote %li bytes to socket. Line was: '%@'", bytesWritten, [NSString stringWithUTF8String:lineWritten]);
+
+ if(bytesWritten == 0) {
+ // 0 means we reached "end of file" and thus the socket was closed. So let's restart it
+ NSLog(@"Socket was closed. Restarting...");
+ [self restart];
+ } else if(bytesWritten == -1) {
+ int err = errno; // Make copy before it gets nuked by something else
+
+ if(err == EAGAIN || err == EWOULDBLOCK) {
+ // No free space in the OS' buffer, nothing to do here
+ NSLog(@"No free space in OS buffer. Ending write.");
+ return;
+ } else {
+ NSLog(@"Error writing to local socket: '%@'", [self strErr]);
+ [self restart];
+ }
+ } else if(bytesWritten > 0) {
+ [self.outBuffer replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
+
+ NSLog(@"Out buffer cleared. Now count is %li bytes.", [self.outBuffer length]);
+
+ if([self.outBuffer length] == 0) {
+ NSLog(@"Out buffer has been emptied, suspending write dispatch source.");
+ dispatch_suspend(self.writeSource);
+ }
+ }
+}
+
+- (void)askForIcon:(NSString*)path isDirectory:(BOOL)isDirectory;
+{
+ NSLog(@"Asking for icon.");
+
+ NSString *verb;
+ if(isDirectory) {
+ verb = @"RETRIEVE_FOLDER_STATUS";
+ } else {
+ verb = @"RETRIEVE_FILE_STATUS";
+ }
+
+ [self askOnSocket:path query:verb];
+}
+
+- (void)readFromSocket
+{
+ if(![self isConnected]) {
+ return;
+ }
+
+ NSLog(@"Reading from socket.");
+
+ int bufferLength = BUF_SIZE / 2;
+ char buffer[bufferLength];
+
+ while(true) {
+ long bytesRead = read(self.sock, buffer, bufferLength);
+
+ NSLog(@"Read %li bytes from socket.", bytesRead);
+
+ if(bytesRead == 0) {
+ // 0 means we reached "end of file" and thus the socket was closed. So let's restart it
+ NSLog(@"Socket was closed. Restarting...");
+ [self restart];
+ return;
+ } else if(bytesRead == -1) {
+ int err = errno;
+ if(err == EAGAIN) {
+ NSLog(@"No error and no data. Stopping.");
+ return; // No error, no data, so let's stop
+ } else {
+ NSLog(@"Error reading from local socket: '%@'", [self strErr]);
+ [self closeConnection];
+ return;
+ }
+ } else {
+ [self.inBuffer appendBytes:buffer length:bytesRead];
+ [self processInBuffer];
+ }
+ }
+}
+
+- (void)processInBuffer
+{
+ NSLog(@"Processing in buffer. In buffer length %li", [self.inBuffer length]);
+ UInt8 separator[] = {0xa}; // Byte value for "\n"
+ while(true) {
+ NSRange firstSeparatorIndex = [self.inBuffer rangeOfData:[NSData dataWithBytes:separator length:1] options:0 range:NSMakeRange(0, [self.inBuffer length])];
+
+ if(firstSeparatorIndex.location == NSNotFound) {
+ NSLog(@"No separator found. Stopping.");
+ return; // No separator, nope out
+ } else {
+ unsigned char *buffer = [self.inBuffer mutableBytes];
+ buffer[firstSeparatorIndex.location] = 0; // Add NULL terminator, so we can use C string methods
+
+ NSString *newLine = [NSString stringWithUTF8String:[self.inBuffer bytes]];
+
+ [self.inBuffer replaceBytesInRange:NSMakeRange(0, firstSeparatorIndex.location + 1) withBytes:NULL length:0];
+ [self.lineProcessor process:newLine];
+ }
+ }
+}
+
+@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClient.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClient.h
new file mode 100644
index 000000000..f8c495a6c
--- /dev/null
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClient.h
@@ -0,0 +1,27 @@
+/*
+ * 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 SyncClientDelegate <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)menuHasCompleted;
+- (void)connectionDidDie;
+@end
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h
deleted file mode 100644
index 1d0fd74b8..000000000
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m b/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m
deleted file mode 100644
index 656f77003..000000000
--- a/shell_integration/MacOSX/OwnCloudFinderSync/FinderSyncExt/SyncClientProxy.m
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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
-
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj
index 5d987c86f..c055182bb 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 539158AC27BE71A900816F56 /* LineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* LineProcessor.m */; };
+ 539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; };
C2B573BA1B1CD91E00303B36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
C2B573D21B1CD94B00303B36 /* main.m in Resources */ = {isa = PBXBuildFile; fileRef = C2B573B91B1CD91E00303B36 /* main.m */; };
C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573DD1B1CD9CE00303B36 /* FinderSync.m */; };
@@ -16,7 +18,6 @@
C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573ED1B1DAD6400303B36 /* ok.iconset */; };
C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EF1B1DAD6400303B36 /* sync.iconset */; };
C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573F11B1DAD6400303B36 /* warning.iconset */; };
- C2C932F01F0BFC6700C8BCB3 /* SyncClientProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C2C932EF1F0BFC6700C8BCB3 /* SyncClientProxy.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -44,6 +45,11 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 539158A927BE606500816F56 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = "<group>"; };
+ 539158AA27BE67CC00816F56 /* SyncClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyncClient.h; sourceTree = "<group>"; };
+ 539158AB27BE71A900816F56 /* LineProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LineProcessor.m; sourceTree = "<group>"; };
+ 539158B127BE891500816F56 /* LocalSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalSocketClient.h; sourceTree = "<group>"; };
+ 539158B227BEC98A00816F56 /* LocalSocketClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalSocketClient.m; sourceTree = "<group>"; };
C2B573B11B1CD91E00303B36 /* desktopclient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktopclient.app; sourceTree = BUILT_PRODUCTS_DIR; };
C2B573B51B1CD91E00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C2B573B91B1CD91E00303B36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -57,8 +63,6 @@
C2B573ED1B1DAD6400303B36 /* ok.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok.iconset; path = ../../icons/nopadding/ok.iconset; sourceTree = SOURCE_ROOT; };
C2B573EF1B1DAD6400303B36 /* sync.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = sync.iconset; path = ../../icons/nopadding/sync.iconset; sourceTree = SOURCE_ROOT; };
C2B573F11B1DAD6400303B36 /* warning.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = warning.iconset; path = ../../icons/nopadding/warning.iconset; sourceTree = SOURCE_ROOT; };
- C2C932EE1F0BFC6700C8BCB3 /* SyncClientProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyncClientProxy.h; sourceTree = "<group>"; };
- C2C932EF1F0BFC6700C8BCB3 /* SyncClientProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SyncClientProxy.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -117,10 +121,13 @@
C2B573D81B1CD9CE00303B36 /* FinderSyncExt */ = {
isa = PBXGroup;
children = (
- C2C932EE1F0BFC6700C8BCB3 /* SyncClientProxy.h */,
- C2C932EF1F0BFC6700C8BCB3 /* SyncClientProxy.m */,
+ 539158AA27BE67CC00816F56 /* SyncClient.h */,
C2B573DC1B1CD9CE00303B36 /* FinderSync.h */,
C2B573DD1B1CD9CE00303B36 /* FinderSync.m */,
+ 539158A927BE606500816F56 /* LineProcessor.h */,
+ 539158AB27BE71A900816F56 /* LineProcessor.m */,
+ 539158B127BE891500816F56 /* LocalSocketClient.h */,
+ 539158B227BEC98A00816F56 /* LocalSocketClient.m */,
C2B573D91B1CD9CE00303B36 /* Supporting Files */,
);
path = FinderSyncExt;
@@ -186,7 +193,7 @@
C2B573951B1CD88000303B36 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0630;
+ LastUpgradeCheck = 1240;
TargetAttributes = {
C2B573B01B1CD91E00303B36 = {
CreatedOnToolsVersion = 6.3.1;
@@ -208,6 +215,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
+ English,
en,
Base,
);
@@ -275,7 +283,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- C2C932F01F0BFC6700C8BCB3 /* SyncClientProxy.m in Sources */,
+ 539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */,
+ 539158AC27BE71A900816F56 /* LineProcessor.m in Sources */,
C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -294,12 +303,65 @@
C2B573991B1CD88000303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
};
name = Debug;
};
C2B5739A1B1CD88000303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
};
name = Release;
};
diff --git a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme
index 785a0da3a..3c65bbe5e 100644
--- a/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme
+++ b/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0630"
+ LastUpgradeVersion = "1240"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
@@ -38,12 +38,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
+ buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Debug">
- <Testables>
- </Testables>
+ shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -53,15 +51,19 @@
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</MacroExpansion>
+ <Testables>
+ </Testables>
</TestAction>
<LaunchAction
+ buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
+ askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
@@ -74,14 +76,12 @@
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
- <AdditionalOptions>
- </AdditionalOptions>
</LaunchAction>
<ProfileAction
+ buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable