Modify FinderSyncExt to move components into shared Framework that can be used in...
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 23 Dec 2022 17:24:05 +0000 (18:24 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 12 May 2023 05:21:08 +0000 (13:21 +0800)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
14 files changed:
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.h
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LineProcessor.h [deleted file]
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LineProcessor.m [deleted file]
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LocalSocketClient.h [deleted file]
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LocalSocketClient.m [deleted file]
shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h [new file with mode: 0644]
shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj
shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/xcshareddata/xcschemes/FinderSyncExt.xcscheme

index 4cf5765bd882d751578668b55ecbc9707325e998..8d73f92d3a8cd35669410fc72c5a1ba7db447607 100644 (file)
 
 #import <Cocoa/Cocoa.h>
 #import <FinderSync/FinderSync.h>
+#import <NCDesktopClientSocketKit/LocalSocketClient.h>
+
 #import "SyncClient.h"
-#import "LineProcessor.h"
-#import "LocalSocketClient.h"
+#import "FinderSyncSocketLineProcessor.h"
 
 @interface FinderSync : FIFinderSync <SyncClientDelegate>
 {
@@ -28,7 +29,7 @@
     NSCondition *_menuIsComplete;
 }
 
-@property LineProcessor *lineProcessor;
+@property FinderSyncSocketLineProcessor *lineProcessor;
 @property LocalSocketClient *localSocketClient;
 
 @end
index 6e9d38af57a678f2e892ca8dbf244cd9e6db46dc..a86c3f7327e56df4269dd2f3337ec1053fe76005 100644 (file)
@@ -62,7 +62,7 @@
         NSLog(@"Socket path: %@", socketPath.path);
 
         if (socketPath.path) {
-            self.lineProcessor = [[LineProcessor alloc] initWithDelegate:self];
+            self.lineProcessor = [[FinderSyncSocketLineProcessor alloc] initWithDelegate:self];
             self.localSocketClient = [[LocalSocketClient alloc] initWithSocketPath:socketPath.path
                                                                      lineProcessor:self.lineProcessor];
             [self.localSocketClient start];
diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h b/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.h
new file mode 100644 (file)
index 0000000..0ff77c8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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 <NCDesktopClientSocketKit/LineProcessor.h>
+
+#import "SyncClient.h"
+
+#ifndef FinderSyncSocketLineProcessor_h
+#define FinderSyncSocketLineProcessor_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 (UTF8 strings) acquired from the socket; look at the
+/// LocalSocketClient for more detail on how data is read from and written to the socket.
+
+@interface FinderSyncSocketLineProcessor : NSObject<LineProcessor>
+
+@property(nonatomic, weak) id<SyncClientDelegate> delegate;
+
+- (instancetype)initWithDelegate:(id<SyncClientDelegate>)delegate;
+
+@end
+#endif /* LineProcessor_h */
diff --git a/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m b/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncSocketLineProcessor.m
new file mode 100644 (file)
index 0000000..7952e5d
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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 "FinderSyncSocketLineProcessor.h"
+
+@implementation FinderSyncSocketLineProcessor
+
+-(instancetype)initWithDelegate:(id<SyncClientDelegate>)delegate
+{
+    NSLog(@"Init line processor with delegate.");
+    self = [super init];
+    if (self) {
+        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/NextcloudIntegration/FinderSyncExt/LineProcessor.h b/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LineProcessor.h
deleted file mode 100644 (file)
index 137ce62..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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/NextcloudIntegration/FinderSyncExt/LineProcessor.m b/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LineProcessor.m
deleted file mode 100644 (file)
index 56ec704..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 = [super init];
-    if (self) {
-        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/NextcloudIntegration/FinderSyncExt/LocalSocketClient.h b/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LocalSocketClient.h
deleted file mode 100644 (file)
index 72331d2..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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
-
-- (instancetype)initWithSocketPath:(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/NextcloudIntegration/FinderSyncExt/LocalSocketClient.m b/shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/LocalSocketClient.m
deleted file mode 100644 (file)
index ddaa1d3..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * 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>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stdio.h>
-#include <string.h>
-
-#import "LocalSocketClient.h"
-
-@interface LocalSocketClient()
-{
-    NSString* _socketPath;
-    LineProcessor* _lineProcessor;
-
-    int _sock;
-    dispatch_queue_t _localSocketQueue;
-    dispatch_source_t _readSource;
-    dispatch_source_t _writeSource;
-    NSMutableData* _inBuffer;
-    NSMutableData* _outBuffer;
-}
-@end
-
-@implementation LocalSocketClient
-
-- (instancetype)initWithSocketPath:(NSString*)socketPath lineProcessor:(LineProcessor*)lineProcessor
-{
-    NSLog(@"Initiating local socket client.");
-    self = [super init];
-    
-    if(self) {
-        _socketPath = socketPath;
-        _lineProcessor = lineProcessor;
-        
-        _sock = -1;
-        _localSocketQueue = dispatch_queue_create("localSocketQueue", DISPATCH_QUEUE_SERIAL);
-        
-        _inBuffer = [NSMutableData data];
-        _outBuffer = [NSMutableData data];
-    }
-        
-    return self;
-}
-
-- (BOOL)isConnected
-{
-    NSLog(@"Checking is connected: %@", _sock != -1 ? @"YES" : @"NO");
-    return _sock != -1;
-}
-
-- (void)start
-{
-    if([self isConnected]) {
-        NSLog(@"Socket client already connected. Not starting.");
-        return;
-    }
-    
-    struct sockaddr_un localSocketAddr;
-    unsigned long socketPathByteCount = [_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", _socketPath, maxByteCount, socketPathByteCount);
-        return;
-    }
-    
-    NSLog(@"Opening local socket...");
-    
-    // LOG THAT THE SOCKET IS BEING OPENED HERE
-    _sock = socket(AF_LOCAL, SOCK_STREAM, 0);
-    
-    if(_sock == -1) {
-        NSLog(@"Cannot open socket: '%@'", [self strErr]);
-        [self restart];
-        return;
-    }
-    
-    NSLog(@"Local socket opened. Connecting to '%@' ...", _socketPath);
-    
-    localSocketAddr.sun_family = AF_LOCAL & 0xff;
-    
-    const char* pathBytes = [_socketPath UTF8String];
-    strcpy(localSocketAddr.sun_path, pathBytes);
-    
-    int connectionStatus = connect(_sock, (struct sockaddr*)&localSocketAddr, sizeof(localSocketAddr));
-    
-    if(connectionStatus == -1) {
-        NSLog(@"Could not connect to '%@': '%@'", _socketPath, [self strErr]);
-        [self restart];
-        return;
-    }
-    
-    int flags = fcntl(_sock, F_GETFL, 0);
-    
-    if(fcntl(_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...");
-    
-    _readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, _sock, 0, _localSocketQueue);
-    dispatch_source_set_event_handler(_readSource, ^(void){ [self readFromSocket]; });
-    dispatch_source_set_cancel_handler(_readSource, ^(void){
-        self->_readSource = nil;
-        [self closeConnection];
-    });
-    
-    _writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, _sock, 0, _localSocketQueue);
-    dispatch_source_set_event_handler(_writeSource, ^(void){ [self writeToSocket]; });
-    dispatch_source_set_cancel_handler(_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(_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.");
-    
-    if(_readSource) {
-        // Since dispatch_source_cancel works asynchronously, if we deallocate the dispatch source here then we can
-        // cause a crash. So instead we strongly hold a reference to the read source and deallocate it asynchronously
-        // with the handler.
-        __block dispatch_source_t previousReadSource = _readSource;
-        dispatch_source_set_cancel_handler(_readSource, ^{
-            previousReadSource = nil;
-        });
-        dispatch_source_cancel(_readSource);
-        // The readSource is still alive due to the other reference and will be deallocated by the cancel handler
-        _readSource = nil;
-    }
-    
-    if(_writeSource) {
-        // Same deal with the write source
-        __block dispatch_source_t previousWriteSource = _writeSource;
-        dispatch_source_set_cancel_handler(_writeSource, ^{
-            previousWriteSource = nil;
-        });
-        dispatch_source_cancel(_writeSource);
-        _writeSource = nil;
-    }
-
-    [_inBuffer setLength:0];
-    [_outBuffer setLength: 0];
-    
-    if(_sock != -1) {
-        close(_sock);
-        _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\10", err];
-    }
-}
-
-- (void)askOnSocket:(NSString *)path query:(NSString *)verb
-{
-    NSString *line = [NSString stringWithFormat:@"%@:%@\n", verb, path];
-    dispatch_async(_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([_outBuffer length] == 0) {
-        NSLog(@"Empty out buffer, suspending write dispatch source.");
-        dispatch_suspend(_writeSource);
-        return;
-    }
-    
-    NSLog(@"About to write %li bytes from outbuffer to socket.", [_outBuffer length]);
-    
-    long bytesWritten = write(_sock, [_outBuffer bytes], [_outBuffer length]);
-    char lineWritten[[_outBuffer length]];
-    memcpy(lineWritten, [_outBuffer bytes], [_outBuffer length]);
-    NSLog(@"Wrote %li bytes to socket. Line written was: '%@'", bytesWritten, [NSString stringWithUTF8String:lineWritten]);
-    
-    if(bytesWritten == 0) {
-        // 0 means we reached "end of file" and thus the socket was closed\10. 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) {
-        [_outBuffer replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
-        
-        NSLog(@"Out buffer cleared. Now count is %li bytes.", [_outBuffer length]);
-        
-        if([_outBuffer length] == 0) {
-            NSLog(@"Out buffer has been emptied, suspending write dispatch source.");
-            dispatch_suspend(_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(_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\10. 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 {
-            [_inBuffer appendBytes:buffer length:bytesRead];
-            [self processInBuffer];
-        }
-    }
-}
-
-- (void)processInBuffer
-{
-    NSLog(@"Processing in buffer. In buffer length %li", [_inBuffer length]);
-    UInt8 separator[] = {0xa}; // Byte value for "\n"
-    while(true) {
-        NSRange firstSeparatorIndex = [_inBuffer rangeOfData:[NSData dataWithBytes:separator length:1] options:0 range:NSMakeRange(0, [_inBuffer length])];
-        
-        if(firstSeparatorIndex.location == NSNotFound) {
-            NSLog(@"No separator found. Stopping.");
-            return; // No separator, nope out
-        } else {
-            unsigned char *buffer = [_inBuffer mutableBytes];
-            buffer[firstSeparatorIndex.location] = 0; // Add NULL terminator, so we can use C string methods
-            
-            NSString *newLine = [NSString stringWithUTF8String:[_inBuffer bytes]];
-
-            [_inBuffer replaceBytesInRange:NSMakeRange(0, firstSeparatorIndex.location + 1) withBytes:NULL length:0];
-            [_lineProcessor process:newLine];
-        }
-    }
-}
-    
-@end
diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h b/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LineProcessor.h
new file mode 100644 (file)
index 0000000..75cf619
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#ifndef LineProcessor_h
+#define LineProcessor_h
+
+@protocol LineProcessor<NSObject>
+
+- (void)process:(NSString*)line;
+
+@end
+
+#endif /* LineProcessor_h */
diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h b/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.h
new file mode 100644 (file)
index 0000000..ce8ef4e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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 <NCDesktopClientSocketKit/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
+
+- (instancetype)initWithSocketPath:(NSString*)socketPath
+                     lineProcessor:(id<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/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m b/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/LocalSocketClient.m
new file mode 100644 (file)
index 0000000..f6a50b7
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * 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>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <string.h>
+
+#import "LocalSocketClient.h"
+
+@interface LocalSocketClient()
+{
+    NSString* _socketPath;
+    id<LineProcessor> _lineProcessor;
+
+    int _sock;
+    dispatch_queue_t _localSocketQueue;
+    dispatch_source_t _readSource;
+    dispatch_source_t _writeSource;
+    NSMutableData* _inBuffer;
+    NSMutableData* _outBuffer;
+}
+@end
+
+@implementation LocalSocketClient
+
+- (instancetype)initWithSocketPath:(NSString*)socketPath
+                     lineProcessor:(id<LineProcessor>)lineProcessor
+{
+    NSLog(@"Initiating local socket client.");
+    self = [super init];
+    
+    if(self) {
+        _socketPath = socketPath;
+        _lineProcessor = lineProcessor;
+        
+        _sock = -1;
+        _localSocketQueue = dispatch_queue_create("localSocketQueue", DISPATCH_QUEUE_SERIAL);
+        
+        _inBuffer = [NSMutableData data];
+        _outBuffer = [NSMutableData data];
+    }
+        
+    return self;
+}
+
+- (BOOL)isConnected
+{
+    NSLog(@"Checking is connected: %@", _sock != -1 ? @"YES" : @"NO");
+    return _sock != -1;
+}
+
+- (void)start
+{
+    if([self isConnected]) {
+        NSLog(@"Socket client already connected. Not starting.");
+        return;
+    }
+    
+    struct sockaddr_un localSocketAddr;
+    unsigned long socketPathByteCount = [_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", _socketPath, maxByteCount, socketPathByteCount);
+        return;
+    }
+    
+    NSLog(@"Opening local socket...");
+    
+    // LOG THAT THE SOCKET IS BEING OPENED HERE
+    _sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+    
+    if(_sock == -1) {
+        NSLog(@"Cannot open socket: '%@'", [self strErr]);
+        [self restart];
+        return;
+    }
+    
+    NSLog(@"Local socket opened. Connecting to '%@' ...", _socketPath);
+    
+    localSocketAddr.sun_family = AF_LOCAL & 0xff;
+    
+    const char* pathBytes = [_socketPath UTF8String];
+    strcpy(localSocketAddr.sun_path, pathBytes);
+    
+    int connectionStatus = connect(_sock, (struct sockaddr*)&localSocketAddr, sizeof(localSocketAddr));
+    
+    if(connectionStatus == -1) {
+        NSLog(@"Could not connect to '%@': '%@'", _socketPath, [self strErr]);
+        [self restart];
+        return;
+    }
+    
+    int flags = fcntl(_sock, F_GETFL, 0);
+    
+    if(fcntl(_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...");
+    
+    _readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, _sock, 0, _localSocketQueue);
+    dispatch_source_set_event_handler(_readSource, ^(void){ [self readFromSocket]; });
+    dispatch_source_set_cancel_handler(_readSource, ^(void){
+        self->_readSource = nil;
+        [self closeConnection];
+    });
+    
+    _writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, _sock, 0, _localSocketQueue);
+    dispatch_source_set_event_handler(_writeSource, ^(void){ [self writeToSocket]; });
+    dispatch_source_set_cancel_handler(_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(_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.");
+    
+    if(_readSource) {
+        // Since dispatch_source_cancel works asynchronously, if we deallocate the dispatch source here then we can
+        // cause a crash. So instead we strongly hold a reference to the read source and deallocate it asynchronously
+        // with the handler.
+        __block dispatch_source_t previousReadSource = _readSource;
+        dispatch_source_set_cancel_handler(_readSource, ^{
+            previousReadSource = nil;
+        });
+        dispatch_source_cancel(_readSource);
+        // The readSource is still alive due to the other reference and will be deallocated by the cancel handler
+        _readSource = nil;
+    }
+    
+    if(_writeSource) {
+        // Same deal with the write source
+        __block dispatch_source_t previousWriteSource = _writeSource;
+        dispatch_source_set_cancel_handler(_writeSource, ^{
+            previousWriteSource = nil;
+        });
+        dispatch_source_cancel(_writeSource);
+        _writeSource = nil;
+    }
+
+    [_inBuffer setLength:0];
+    [_outBuffer setLength: 0];
+    
+    if(_sock != -1) {
+        close(_sock);
+        _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\10", err];
+    }
+}
+
+- (void)askOnSocket:(NSString *)path query:(NSString *)verb
+{
+    NSString *line = [NSString stringWithFormat:@"%@:%@\n", verb, path];
+    dispatch_async(_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([_outBuffer length] == 0) {
+        NSLog(@"Empty out buffer, suspending write dispatch source.");
+        dispatch_suspend(_writeSource);
+        return;
+    }
+    
+    NSLog(@"About to write %li bytes from outbuffer to socket.", [_outBuffer length]);
+    
+    long bytesWritten = write(_sock, [_outBuffer bytes], [_outBuffer length]);
+    char lineWritten[[_outBuffer length]];
+    memcpy(lineWritten, [_outBuffer bytes], [_outBuffer length]);
+    NSLog(@"Wrote %li bytes to socket. Line written was: '%@'", bytesWritten, [NSString stringWithUTF8String:lineWritten]);
+    
+    if(bytesWritten == 0) {
+        // 0 means we reached "end of file" and thus the socket was closed\10. 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) {
+        [_outBuffer replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
+        
+        NSLog(@"Out buffer cleared. Now count is %li bytes.", [_outBuffer length]);
+        
+        if([_outBuffer length] == 0) {
+            NSLog(@"Out buffer has been emptied, suspending write dispatch source.");
+            dispatch_suspend(_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(_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\10. 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 {
+            [_inBuffer appendBytes:buffer length:bytesRead];
+            [self processInBuffer];
+        }
+    }
+}
+
+- (void)processInBuffer
+{
+    NSLog(@"Processing in buffer. In buffer length %li", [_inBuffer length]);
+    UInt8 separator[] = {0xa}; // Byte value for "\n"
+    while(true) {
+        NSRange firstSeparatorIndex = [_inBuffer rangeOfData:[NSData dataWithBytes:separator length:1] options:0 range:NSMakeRange(0, [_inBuffer length])];
+        
+        if(firstSeparatorIndex.location == NSNotFound) {
+            NSLog(@"No separator found. Stopping.");
+            return; // No separator, nope out
+        } else {
+            unsigned char *buffer = [_inBuffer mutableBytes];
+            buffer[firstSeparatorIndex.location] = 0; // Add NULL terminator, so we can use C string methods
+            
+            NSString *newLine = [NSString stringWithUTF8String:[_inBuffer bytes]];
+
+            [_inBuffer replaceBytesInRange:NSMakeRange(0, firstSeparatorIndex.location + 1) withBytes:NULL length:0];
+            [_lineProcessor process:newLine];
+        }
+    }
+}
+    
+@end
diff --git a/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h b/shell_integration/MacOSX/NextcloudIntegration/NCDesktopClientSocketKit/NCDesktopClientSocketKit.h
new file mode 100644 (file)
index 0000000..8626125
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  NCDesktopClientSocketKit.h
+//  NCDesktopClientSocketKit
+//
+//  Created by Claudio Cambra on 23/12/22.
+//
+
+#import <Foundation/Foundation.h>
+
+//! Project version number for NCDesktopClientSocketKit.
+FOUNDATION_EXPORT double NCDesktopClientSocketKitVersionNumber;
+
+//! Project version string for NCDesktopClientSocketKit.
+FOUNDATION_EXPORT const unsigned char NCDesktopClientSocketKitVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <NCDesktopClientSocketKit/PublicHeader.h>
+
+#import <NCDesktopClientSocketKit/LocalSocketClient.h>
+#import <NCDesktopClientSocketKit/LineProcessor.h>
index d7953cb7666ac85213abcfd9bb3ed737f51b7143..d8a9ba2bd7a2ec88b5a97f4ec3a30b566069f6d8 100644 (file)
                538E396F27F4765000FA63D5 /* FileProviderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E396E27F4765000FA63D5 /* FileProviderItem.swift */; };
                538E397127F4765000FA63D5 /* FileProviderEnumerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */; };
                538E397627F4765000FA63D5 /* FileProviderExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 538E396727F4765000FA63D5 /* FileProviderExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-               539158AC27BE71A900816F56 /* LineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* LineProcessor.m */; };
-               539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; };
+               53903D1E2956164F00D0B308 /* NCDesktopClientSocketKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 53903D0E2956164F00D0B308 /* NCDesktopClientSocketKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               53903D212956164F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; };
+               53903D222956164F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+               53903D2A295616F000D0B308 /* LocalSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158B227BEC98A00816F56 /* LocalSocketClient.m */; };
+               53903D2B2956173000D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; };
+               53903D2C2956173000D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+               53903D302956173F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; };
+               53903D312956173F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+               53903D352956184400D0B308 /* LocalSocketClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 539158B127BE891500816F56 /* LocalSocketClient.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               53903D37295618A400D0B308 /* LineProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 53903D36295618A400D0B308 /* LineProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+               539158AC27BE71A900816F56 /* FinderSyncSocketLineProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.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 */; };
                        remoteGlobalIDString = 538E396627F4765000FA63D5;
                        remoteInfo = FileProviderExt;
                };
+               53903D1F2956164F00D0B308 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = C2B573951B1CD88000303B36 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 53903D0B2956164F00D0B308;
+                       remoteInfo = NCDesktopClientSocketKit;
+               };
+               53903D2D2956173000D0B308 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = C2B573951B1CD88000303B36 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 53903D0B2956164F00D0B308;
+                       remoteInfo = NCDesktopClientSocketKit;
+               };
+               53903D322956173F00D0B308 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = C2B573951B1CD88000303B36 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = 53903D0B2956164F00D0B308;
+                       remoteInfo = NCDesktopClientSocketKit;
+               };
                C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = C2B573951B1CD88000303B36 /* Project object */;
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
+               53903D232956165000D0B308 /* Embed Frameworks */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = "";
+                       dstSubfolderSpec = 10;
+                       files = (
+                               53903D222956164F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */,
+                       );
+                       name = "Embed Frameworks";
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               53903D2F2956173000D0B308 /* Embed Frameworks */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = "";
+                       dstSubfolderSpec = 10;
+                       files = (
+                               53903D2C2956173000D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */,
+                       );
+                       name = "Embed Frameworks";
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               53903D342956173F00D0B308 /* Embed Frameworks */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = "";
+                       dstSubfolderSpec = 10;
+                       files = (
+                               53903D312956173F00D0B308 /* NCDesktopClientSocketKit.framework in Embed Frameworks */,
+                       );
+                       name = "Embed Frameworks";
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2B573E11B1CD9CE00303B36 /* Embed App Extensions */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                538E397027F4765000FA63D5 /* FileProviderEnumerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderEnumerator.swift; sourceTree = "<group>"; };
                538E397227F4765000FA63D5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
                538E397327F4765000FA63D5 /* FileProviderExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FileProviderExt.entitlements; sourceTree = "<group>"; };
-               539158A927BE606500816F56 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = "<group>"; };
+               53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NCDesktopClientSocketKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+               53903D0E2956164F00D0B308 /* NCDesktopClientSocketKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCDesktopClientSocketKit.h; sourceTree = "<group>"; };
+               53903D36295618A400D0B308 /* LineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LineProcessor.h; sourceTree = "<group>"; };
+               539158A927BE606500816F56 /* FinderSyncSocketLineProcessor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinderSyncSocketLineProcessor.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>"; };
+               539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FinderSyncSocketLineProcessor.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; };
                        buildActionMask = 2147483647;
                        files = (
                                538E396A27F4765000FA63D5 /* UniformTypeIdentifiers.framework in Frameworks */,
+                               53903D302956173F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               53903D092956164F00D0B308 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               53903D212956164F00D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               53903D2B2956173000D0B308 /* NCDesktopClientSocketKit.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        path = FileProviderExt;
                        sourceTree = "<group>";
                };
+               53903D0D2956164F00D0B308 /* NCDesktopClientSocketKit */ = {
+                       isa = PBXGroup;
+                       children = (
+                               53903D0E2956164F00D0B308 /* NCDesktopClientSocketKit.h */,
+                               539158B127BE891500816F56 /* LocalSocketClient.h */,
+                               539158B227BEC98A00816F56 /* LocalSocketClient.m */,
+                               53903D36295618A400D0B308 /* LineProcessor.h */,
+                       );
+                       path = NCDesktopClientSocketKit;
+                       sourceTree = "<group>";
+               };
                C2B573941B1CD88000303B36 = {
                        isa = PBXGroup;
                        children = (
                                C2B573B31B1CD91E00303B36 /* desktopclient */,
                                C2B573D81B1CD9CE00303B36 /* FinderSyncExt */,
                                538E396B27F4765000FA63D5 /* FileProviderExt */,
+                               53903D0D2956164F00D0B308 /* NCDesktopClientSocketKit */,
                                538E396827F4765000FA63D5 /* Frameworks */,
                                C2B573B21B1CD91E00303B36 /* Products */,
                        );
                                C2B573B11B1CD91E00303B36 /* desktopclient.app */,
                                C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */,
                                538E396727F4765000FA63D5 /* FileProviderExt.appex */,
+                               53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                539158AA27BE67CC00816F56 /* SyncClient.h */,
                                C2B573DC1B1CD9CE00303B36 /* FinderSync.h */,
                                C2B573DD1B1CD9CE00303B36 /* FinderSync.m */,
-                               539158A927BE606500816F56 /* LineProcessor.h */,
-                               539158AB27BE71A900816F56 /* LineProcessor.m */,
-                               539158B127BE891500816F56 /* LocalSocketClient.h */,
-                               539158B227BEC98A00816F56 /* LocalSocketClient.m */,
+                               539158A927BE606500816F56 /* FinderSyncSocketLineProcessor.h */,
+                               539158AB27BE71A900816F56 /* FinderSyncSocketLineProcessor.m */,
                                C2B573D91B1CD9CE00303B36 /* Supporting Files */,
                        );
                        path = FinderSyncExt;
                };
 /* End PBXGroup section */
 
+/* Begin PBXHeadersBuildPhase section */
+               53903D072956164F00D0B308 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               53903D352956184400D0B308 /* LocalSocketClient.h in Headers */,
+                               53903D37295618A400D0B308 /* LineProcessor.h in Headers */,
+                               53903D1E2956164F00D0B308 /* NCDesktopClientSocketKit.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXHeadersBuildPhase section */
+
 /* Begin PBXNativeTarget section */
                538E396627F4765000FA63D5 /* FileProviderExt */ = {
                        isa = PBXNativeTarget;
                                538E396327F4765000FA63D5 /* Sources */,
                                538E396427F4765000FA63D5 /* Frameworks */,
                                538E396527F4765000FA63D5 /* Resources */,
+                               53903D342956173F00D0B308 /* Embed Frameworks */,
                        );
                        buildRules = (
                        );
                        dependencies = (
+                               53903D332956173F00D0B308 /* PBXTargetDependency */,
                        );
                        name = FileProviderExt;
                        packageProductDependencies = (
                        productReference = 538E396727F4765000FA63D5 /* FileProviderExt.appex */;
                        productType = "com.apple.product-type.app-extension";
                };
+               53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 53903D282956165000D0B308 /* Build configuration list for PBXNativeTarget "NCDesktopClientSocketKit" */;
+                       buildPhases = (
+                               53903D072956164F00D0B308 /* Headers */,
+                               53903D082956164F00D0B308 /* Sources */,
+                               53903D092956164F00D0B308 /* Frameworks */,
+                               53903D0A2956164F00D0B308 /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = NCDesktopClientSocketKit;
+                       productName = NCDesktopClientSocketKit;
+                       productReference = 53903D0C2956164F00D0B308 /* NCDesktopClientSocketKit.framework */;
+                       productType = "com.apple.product-type.framework";
+               };
                C2B573B01B1CD91E00303B36 /* desktopclient */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */;
                                C2B573AE1B1CD91E00303B36 /* Frameworks */,
                                C2B573AF1B1CD91E00303B36 /* Resources */,
                                C2B573E11B1CD9CE00303B36 /* Embed App Extensions */,
+                               53903D232956165000D0B308 /* Embed Frameworks */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                                C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */,
                                538E397527F4765000FA63D5 /* PBXTargetDependency */,
+                               53903D202956164F00D0B308 /* PBXTargetDependency */,
                        );
                        name = desktopclient;
                        productName = desktopclient;
                                C2B573D41B1CD9CE00303B36 /* Frameworks */,
                                C2B573D51B1CD9CE00303B36 /* Resources */,
                                5B3335471CA058E200E11A45 /* ShellScript */,
+                               53903D2F2956173000D0B308 /* Embed Frameworks */,
                        );
                        buildRules = (
                        );
                        dependencies = (
+                               53903D2E2956173000D0B308 /* PBXTargetDependency */,
                        );
                        name = FinderSyncExt;
                        productName = FinderSyncExt;
                C2B573951B1CD88000303B36 /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastSwiftUpdateCheck = 1330;
+                               LastSwiftUpdateCheck = 1420;
                                LastUpgradeCheck = 1240;
                                TargetAttributes = {
                                        538E396627F4765000FA63D5 = {
                                                CreatedOnToolsVersion = 13.3;
                                                ProvisioningStyle = Manual;
                                        };
+                                       53903D0B2956164F00D0B308 = {
+                                               CreatedOnToolsVersion = 14.2;
+                                               ProvisioningStyle = Manual;
+                                       };
                                        C2B573B01B1CD91E00303B36 = {
                                                CreatedOnToolsVersion = 6.3.1;
                                                DevelopmentTeam = 9B5WD74GWJ;
                                C2B573B01B1CD91E00303B36 /* desktopclient */,
                                C2B573D61B1CD9CE00303B36 /* FinderSyncExt */,
                                538E396627F4765000FA63D5 /* FileProviderExt */,
+                               53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */,
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               53903D0A2956164F00D0B308 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2B573AF1B1CD91E00303B36 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               53903D082956164F00D0B308 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               53903D2A295616F000D0B308 /* LocalSocketClient.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                C2B573AD1B1CD91E00303B36 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               539158B327BEC98A00816F56 /* LocalSocketClient.m in Sources */,
-                               539158AC27BE71A900816F56 /* LineProcessor.m in Sources */,
+                               539158AC27BE71A900816F56 /* FinderSyncSocketLineProcessor.m in Sources */,
                                C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        target = 538E396627F4765000FA63D5 /* FileProviderExt */;
                        targetProxy = 538E397427F4765000FA63D5 /* PBXContainerItemProxy */;
                };
+               53903D202956164F00D0B308 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */;
+                       targetProxy = 53903D1F2956164F00D0B308 /* PBXContainerItemProxy */;
+               };
+               53903D2E2956173000D0B308 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */;
+                       targetProxy = 53903D2D2956173000D0B308 /* PBXContainerItemProxy */;
+               };
+               53903D332956173F00D0B308 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = 53903D0B2956164F00D0B308 /* NCDesktopClientSocketKit */;
+                       targetProxy = 53903D322956173F00D0B308 /* PBXContainerItemProxy */;
+               };
                C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */;
                                INFOPLIST_KEY_CFBundleDisplayName = FileProviderExt;
                                INFOPLIST_KEY_NSHumanReadableCopyright = "";
                                LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
-                               MACOSX_DEPLOYMENT_TARGET = 12.3;
+                               MACOSX_DEPLOYMENT_TARGET = 12.0;
                                MARKETING_VERSION = 1.0;
                                MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
                                MTL_FAST_MATH = YES;
                                INFOPLIST_KEY_CFBundleDisplayName = FileProviderExt;
                                INFOPLIST_KEY_NSHumanReadableCopyright = "";
                                LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
-                               MACOSX_DEPLOYMENT_TARGET = 12.3;
+                               MACOSX_DEPLOYMENT_TARGET = 12.0;
                                MARKETING_VERSION = 1.0;
                                MTL_ENABLE_DEBUG_INFO = NO;
                                MTL_FAST_MATH = YES;
                        };
                        name = Release;
                };
+               53903D242956165000D0B308 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               APPLICATION_EXTENSION_API_ONLY = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Manual;
+                               COPY_PHASE_STRIP = NO;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               DEFINES_MODULE = YES;
+                               DEVELOPMENT_TEAM = "";
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               DYLIB_INSTALL_NAME_BASE = "@rpath";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               INFOPLIST_KEY_NSHumanReadableCopyright = "";
+                               INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+                               IPHONEOS_DEPLOYMENT_TARGET = 16.2;
+                               LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks @loader_path/Frameworks";
+                               "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks @loader_path/Frameworks";
+                               MACOSX_DEPLOYMENT_TARGET = 10.14;
+                               MARKETING_VERSION = 1.0;
+                               MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                               MTL_FAST_MATH = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.NCDesktopClientSocketKit;
+                               PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+                               PROVISIONING_PROFILE_SPECIFIER = "";
+                               SDKROOT = auto;
+                               SKIP_INSTALL = YES;
+                               SUPPORTED_PLATFORMS = macosx;
+                               SUPPORTS_MACCATALYST = NO;
+                               SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+                               SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                               SWIFT_VERSION = 5.0;
+                               VERSIONING_SYSTEM = "apple-generic";
+                               VERSION_INFO_PREFIX = "";
+                       };
+                       name = Debug;
+               };
+               53903D252956165000D0B308 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               APPLICATION_EXTENSION_API_ONLY = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Manual;
+                               COPY_PHASE_STRIP = NO;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               DEFINES_MODULE = YES;
+                               DEVELOPMENT_TEAM = "";
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               DYLIB_INSTALL_NAME_BASE = "@rpath";
+                               ENABLE_NS_ASSERTIONS = NO;
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               INFOPLIST_KEY_NSHumanReadableCopyright = "";
+                               INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+                               IPHONEOS_DEPLOYMENT_TARGET = 16.2;
+                               LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks @loader_path/Frameworks";
+                               "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks @loader_path/Frameworks";
+                               MACOSX_DEPLOYMENT_TARGET = 10.14;
+                               MARKETING_VERSION = 1.0;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               MTL_FAST_MATH = YES;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.owncloud.NCDesktopClientSocketKit;
+                               PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+                               PROVISIONING_PROFILE_SPECIFIER = "";
+                               SDKROOT = auto;
+                               SKIP_INSTALL = YES;
+                               SUPPORTED_PLATFORMS = macosx;
+                               SUPPORTS_MACCATALYST = NO;
+                               SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+                               SWIFT_VERSION = 5.0;
+                               VERSIONING_SYSTEM = "apple-generic";
+                               VERSION_INFO_PREFIX = "";
+                       };
+                       name = Release;
+               };
                C2B573991B1CD88000303B36 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               53903D282956165000D0B308 /* Build configuration list for PBXNativeTarget "NCDesktopClientSocketKit" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               53903D242956165000D0B308 /* Debug */,
+                               53903D252956165000D0B308 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "NextcloudIntegration" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
index d3e945f94df46a4b2917678255eb87ee79eb6f9a..174aab5bb930ce29db3d54640a59a162863696c0 100644 (file)
          </BuildableReference>
       </MacroExpansion>
       <Testables>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "53903D142956164F00D0B308"
+               BuildableName = "NCDesktopClientSocketKitTests.xctest"
+               BlueprintName = "NCDesktopClientSocketKitTests"
+               ReferencedContainer = "container:NextcloudIntegration.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
       </Testables>
    </TestAction>
    <LaunchAction