Merge pull request #3347 from jturcotte/shell_integration_findersync

shell_i: Add a FinderSync-based implementation #2340
This commit is contained in:
Daniel Molkentin 2015-07-02 14:20:24 +02:00
Родитель ba613a152a 360a0eeee1
Коммит 0610d3ea8d
92 изменённых файлов: 1871 добавлений и 9444 удалений

Просмотреть файл

@ -118,6 +118,10 @@ if(OWNCLOUD_5XX_NO_BLACKLIST)
add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1)
endif()
if(APPLE)
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesigh key's TeamIdentifier/Organizational Unit" )
endif()
#### find libs
#find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest QtWebkit REQUIRED )
#if( UNIX AND NOT APPLE ) # Fdo notifications

Просмотреть файл

@ -1,12 +1,18 @@
#!/bin/sh -xe
[ "$#" -lt 2 ] && echo "Usage: sign_app.sh <app> <identity>" && exit
[ "$#" -lt 2 ] && echo "Usage: sign_app.sh <app> <identity> <team_identifier>" && exit
src_app="$1"
identity="$2"
team_identifier="$3"
codesign -s "$identity" --force --verbose=4 --deep "$src_app"
codesign -s "$identity" --force --preserve-metadata=entitlements --verbose=4 --deep "$src_app"
# Verify the signature
spctl -a -t exec -vv $src_app
codesign -dv $src_app
# Validate that the key used for signing the binary matches the expected TeamIdentifier
# needed to pass the SocketApi through the sandbox
codesign -dv $src_app 2>&1 | grep "TeamIdentifier=$team_identifier"
exit $?

Просмотреть файл

@ -5,9 +5,8 @@
#cmakedefine WITH_QTKEYCHAIN 1
#cmakedefine WITH_CRASHREPORTER
#cmakedefine CRASHREPORTER_EXECUTABLE "@CRASHREPORTER_EXECUTABLE@"
#define SOCKETAPI_TEAM_IDENTIFIER_PREFIX "@SOCKETAPI_TEAM_IDENTIFIER_PREFIX@"
#cmakedefine GIT_SHA1 "@GIT_SHA1@"
#cmakedefine APPLICATION_DOMAIN @APPLICATION_DOMAIN@
#cmakedefine THEME_CLASS @THEME_CLASS@
#cmakedefine THEME_INCLUDE @THEME_INCLUDE@

Просмотреть файл

@ -1,11 +1,28 @@
if(APPLE)
add_custom_target( mac_overlayplugin ALL
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
-scheme SyncStateFinder.osax SYMROOT=${CMAKE_CURRENT_BINARY_DIR} archive
COMMENT building Mac Overlay icons)
add_custom_target( legacy_mac_overlayplugin ALL
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
-scheme SyncStateFinder.osax -configuration Release SYMROOT=${CMAKE_CURRENT_BINARY_DIR}
OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}
COMMENT building Legacy Mac Overlay icons)
# The bundle identifier and application group need to have compatible values with the client
# to be able to open a Mach port across the extension's sandbox boundary.
# Pass the info through the xcodebuild command line and make sure that the project uses
# those user-defined settings to build the plist.
add_custom_target( mac_overlayplugin ALL
xcodebuild -project ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj
-target FinderSyncExt -configuration Release SYMROOT=${CMAKE_CURRENT_BINARY_DIR}
OC_APPLICATION_NAME=${APPLICATION_NAME}
OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}
COMMENT building Mac Overlay icons)
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/SyncStateFinder.osax/Contents
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/SyncStateFinder.osax/ )
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Plugins
USE_SOURCE_PERMISSIONS)
endif(APPLE)

Просмотреть файл

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj">
</FileRef>
<FileRef
location = "group:OwnCloudFinder/OwnCloudFinder.xcodeproj">
</FileRef>

Просмотреть файл

@ -10,29 +10,29 @@
<string>OwnCloud</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>09EE94AA-F410-4594-AB26-5A0220DEAEC7</key>
<key>D67321A19EF879CA55BF889202BA8C23AC9AA2B5</key>
<string>ssh://github.com/owncloud/client.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>shell_integration/MacOSX/OwnCloud.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>09EE94AA-F410-4594-AB26-5A0220DEAEC7</key>
<key>D67321A19EF879CA55BF889202BA8C23AC9AA2B5</key>
<string>../../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>ssh://github.com/owncloud/client.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>110</integer>
<integer>111</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>09EE94AA-F410-4594-AB26-5A0220DEAEC7</string>
<string>D67321A19EF879CA55BF889202BA8C23AC9AA2B5</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>09EE94AA-F410-4594-AB26-5A0220DEAEC7</string>
<string>D67321A19EF879CA55BF889202BA8C23AC9AA2B5</string>
<key>IDESourceControlWCCName</key>
<string>client</string>
</dict>

Просмотреть файл

@ -14,7 +14,7 @@
#import <Foundation/Foundation.h>
@interface ContentManager : NSObject
@interface OwnCloudFinderContentManager : NSObject
{
NSMutableDictionary* _fileNamesCache;
NSMutableDictionary* _oldFileNamesCache;
@ -31,7 +31,7 @@
NSNumber *_icnErrSwm;
}
+ (ContentManager*)sharedInstance;
+ (OwnCloudFinderContentManager*)sharedInstance;
- (void)enableFileIcons:(BOOL)enable;
- (NSNumber*)iconByPath:(NSString*)path isDirectory:(BOOL)isDir;
@ -42,6 +42,6 @@
- (void)reFetchFileNameCacheForPath:(NSString*)path;
- (void)repaintAllWindows;
- (void)loadIconResourcePath:(NSString*)path;
- (void)loadIconResources;
@end

Просмотреть файл

@ -20,9 +20,9 @@
#import "RequestManager.h"
#import "IconCache.h"
static ContentManager* sharedInstance = nil;
static OwnCloudFinderContentManager* sharedInstance = nil;
@implementation ContentManager
@implementation OwnCloudFinderContentManager
- init
{
self = [super init];
@ -33,6 +33,7 @@ static ContentManager* sharedInstance = nil;
_oldFileNamesCache = [[NSMutableDictionary alloc] init];
_fileIconsEnabled = TRUE;
_hasChangedContent = TRUE;
[self loadIconResources];
}
return self;
@ -48,7 +49,7 @@ static ContentManager* sharedInstance = nil;
[super dealloc];
}
+ (ContentManager*)sharedInstance
+ (OwnCloudFinderContentManager*)sharedInstance
{
@synchronized(self)
{
@ -61,20 +62,20 @@ static ContentManager* sharedInstance = nil;
return sharedInstance;
}
- (void)loadIconResourcePath:(NSString*)path
- (void)loadIconResources
{
NSString *base = path;
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
_icnOk = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"ok.icns"]];
_icnSync = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"sync.icns"]];
_icnWarn = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"warning.icns"]];
_icnErr = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"error.icns"]];
_icnOkSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"ok_swm.icns"]];
_icnSyncSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"sync_swm.icns"]];
_icnWarnSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"warning_swm.icns"]];
_icnErrSwm = [[IconCache sharedInstance] registerIcon:[base stringByAppendingPathComponent:@"error_swm.icns"]];
_icnOk = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"ok.icns"]];
_icnSync = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"sync.icns"]];
_icnWarn = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"warning.icns"]];
_icnErr = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"error.icns"]];
_icnOkSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"ok_swm.icns"]];
_icnSyncSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"sync_swm.icns"]];
_icnWarnSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"warning_swm.icns"]];
_icnErrSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"error_swm.icns"]];
// NSLog(@"Icon ok identifier: %d from %@", [_icnOk intValue], [base stringByAppendingString:@"ok.icns"]);
// NSLog(@"Icon ok: %@ identifier: %d from bundle %@", [extBundle imageForResource:@"ok.icns"], [_icnOk intValue], extBundle);
}
- (void)enableFileIcons:(BOOL)enable
@ -141,7 +142,7 @@ static ContentManager* sharedInstance = nil;
}
NSString* normalizedPath = [path decomposedStringWithCanonicalMapping];
if (![[RequestManager sharedInstance] isRegisteredPath:normalizedPath isDirectory:isDir]) {
if (![[OwnCloudFinderRequestManager sharedInstance] isRegisteredPath:normalizedPath isDirectory:isDir]) {
return [NSNumber numberWithInt:0];
}
@ -149,11 +150,11 @@ static ContentManager* sharedInstance = nil;
// NSLog(@"XXXXXXX Asking for icon for path %@ = %d",normalizedPath, [result intValue]);
if( result == nil ) {
// start the async call
[[RequestManager sharedInstance] askForIcon:normalizedPath isDirectory:isDir];
result = [NSNumber numberWithInt:0];
// Set 0 into the cache, meaning "don't have an icon, but already requested it"
[_fileNamesCache setObject:result forKey:normalizedPath];
// start the async call
[[OwnCloudFinderRequestManager sharedInstance] askForIcon:normalizedPath isDirectory:isDir];
}
if ([result intValue] == 0) {
// Show the old state while we wait for the new one
@ -222,7 +223,7 @@ static ContentManager* sharedInstance = nil;
}
MenuManager* menuManager = [MenuManager sharedInstance];
RequestManager* requestManager = [RequestManager sharedInstance];
OwnCloudFinderRequestManager* requestManager = [OwnCloudFinderRequestManager sharedInstance];
if ([[window className] isEqualToString:@"TBrowserWindow"])
{

Просмотреть файл

@ -51,7 +51,7 @@ static BOOL installed = NO;
// NSLog(@"SyncStateFinder: installing SyncState Shell extension");
[RequestManager sharedInstance];
[OwnCloudFinderRequestManager sharedInstance];
// Icons
[self hookMethod:@selector(drawImage:) inClass:@"IKImageBrowserCell" toCallToTheNewMethod:@selector(OCIconOverlayHandlers_IKImageBrowserCell_drawImage:)]; // 10.7 & 10.8 & 10.9 (Icon View arrange by name)
@ -95,11 +95,11 @@ static BOOL installed = NO;
// NSLog(@"SyncStateFinder: uninstalling");
[[ContentManager sharedInstance] dealloc];
[[OwnCloudFinderContentManager sharedInstance] dealloc];
[[IconCache sharedInstance] dealloc];
[[RequestManager sharedInstance] dealloc];
[[OwnCloudFinderRequestManager sharedInstance] dealloc];
// Icons
[self hookMethod:@selector(OCIconOverlayHandlers_drawImage:) inClass:@"TIconViewCell" toCallToTheNewMethod:@selector(drawImage:)]; // 10.7 & 10.8 & 10.9

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -17,13 +17,11 @@
@interface IconCache : NSObject {
int _currentIconId;
NSMutableDictionary* _iconIdDictionary;
NSMutableDictionary* _iconPathDictionary;
}
+ (IconCache*)sharedInstance;
- (NSImage*)getIcon:(NSNumber*)iconId;
- (NSNumber*)registerIcon:(NSString*)path;
- (void)unregisterIcon:(NSNumber*)iconId;
- (NSNumber*)registerIcon:(NSImage*)image;
@end

Просмотреть файл

@ -25,7 +25,6 @@ static IconCache* sharedInstance = nil;
if (self)
{
_iconIdDictionary = [[NSMutableDictionary alloc] init];
_iconPathDictionary = [[NSMutableDictionary alloc] init];
_currentIconId = 0;
}
@ -35,7 +34,6 @@ static IconCache* sharedInstance = nil;
- (void)dealloc
{
[_iconIdDictionary release];
[_iconPathDictionary release];
sharedInstance = nil;
[super dealloc];
@ -60,57 +58,15 @@ static IconCache* sharedInstance = nil;
return image;
}
- (NSNumber*)registerIcon:(NSString*)path
- (NSNumber*)registerIcon:(NSImage*)image
{
if (path == nil)
{
return [NSNumber numberWithInt:-1];
}
_currentIconId++;
NSImage* image = [[NSImage alloc]initWithContentsOfFile:path];
if (image == nil)
{
NSLog(@"%@ Could not load %@", NSStringFromSelector(_cmd), path);
return [NSNumber numberWithInt:-1];
}
NSNumber* iconId = [_iconPathDictionary objectForKey:path];
if (iconId == nil)
{
_currentIconId++;
iconId = [NSNumber numberWithInt:_currentIconId];
[_iconPathDictionary setObject:iconId forKey:path];
}
NSNumber* iconId = [NSNumber numberWithInt:_currentIconId];
[_iconIdDictionary setObject:image forKey:iconId];
[image release];
return iconId;
}
- (void)unregisterIcon:(NSNumber*)iconId
{
NSString* path = @"";
for (NSString* key in _iconPathDictionary)
{
NSNumber* value = [_iconPathDictionary objectForKey:key];
if ([value isEqualToNumber:iconId])
{
path = key;
break;
}
}
[_iconPathDictionary removeObjectForKey:path];
[_iconIdDictionary removeObjectForKey:iconId];
}
@end

Просмотреть файл

@ -33,7 +33,7 @@
isDir = NO;
}
NSNumber* imageIndex = [[ContentManager sharedInstance] iconByPath:[url path] isDirectory:isDir];
NSNumber* imageIndex = [[OwnCloudFinderContentManager sharedInstance] iconByPath:[url path] isDirectory:isDir];
//NSLog(@"1 The icon index is %d", [imageIndex intValue]);
if ([imageIndex intValue] > 0)
@ -76,7 +76,7 @@
isDir = NO;
}
NSNumber* imageIndex = [[ContentManager sharedInstance] iconByPath:[url path] isDirectory:isDir];
NSNumber* imageIndex = [[OwnCloudFinderContentManager sharedInstance] iconByPath:[url path] isDirectory:isDir];
//NSLog(@"2 The icon index is %d %@ %@", [imageIndex intValue], [url path], isDir ? @"isDir" : @"");
if ([imageIndex intValue] > 0)
@ -157,7 +157,7 @@
isDir = NO;
}
NSNumber* imageIndex = [[ContentManager sharedInstance] iconByPath:[url path] isDirectory:isDir];
NSNumber* imageIndex = [[OwnCloudFinderContentManager sharedInstance] iconByPath:[url path] isDirectory:isDir];
//NSLog(@"3 The icon index is %d", [imageIndex intValue]);
if ([imageIndex intValue] > 0)

Просмотреть файл

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SocketApiPrefix</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>

Просмотреть файл

@ -73,7 +73,7 @@ static MenuManager* sharedInstance = nil;
- (void)addItemsToMenu:(TContextMenu*)menu forFiles:(NSArray*)files
{
RequestManager *requestManager = [RequestManager sharedInstance];
OwnCloudFinderRequestManager *requestManager = [OwnCloudFinderRequestManager sharedInstance];
NSString *shareItemTitle = [requestManager shareItemTitle];
if (!shareItemTitle || shareItemTitle.length == 0) {
return;
@ -157,7 +157,7 @@ static MenuManager* sharedInstance = nil;
- (void)menuItemClicked:(id)param
{
[[RequestManager sharedInstance] menuItemClicked:[param representedObject]];
[[OwnCloudFinderRequestManager sharedInstance] menuItemClicked:[param representedObject]];
}
- (NSArray*)pathsForNodes:(const struct TFENodeVector*)nodes

Просмотреть файл

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
0B13ECAE173C687400548DA1 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
0B13ECAF173C687900548DA1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BFC9ACB173C57E400CDD329 /* Security.framework */; };
5BB74A8719DBF9BB001BAAAC /* FinishedIconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */; };
692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */; };
@ -21,13 +20,20 @@
8C99F6941622D145002D2135 /* IconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C99F6931622D145002D2135 /* IconCache.m */; };
8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; };
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; };
C220057B1B31B04C00A4FB37 /* error_swm.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005731B31B04C00A4FB37 /* error_swm.icns */; };
C220057C1B31B04C00A4FB37 /* error.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005741B31B04C00A4FB37 /* error.icns */; };
C220057D1B31B04C00A4FB37 /* ok_swm.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005751B31B04C00A4FB37 /* ok_swm.icns */; };
C220057E1B31B04C00A4FB37 /* ok.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005761B31B04C00A4FB37 /* ok.icns */; };
C220057F1B31B04C00A4FB37 /* sync_swm.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005771B31B04C00A4FB37 /* sync_swm.icns */; };
C22005801B31B04C00A4FB37 /* sync.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005781B31B04C00A4FB37 /* sync.icns */; };
C22005811B31B04C00A4FB37 /* warning_swm.icns in Resources */ = {isa = PBXBuildFile; fileRef = C22005791B31B04C00A4FB37 /* warning_swm.icns */; };
C22005821B31B04C00A4FB37 /* warning.icns in Resources */ = {isa = PBXBuildFile; fileRef = C220057A1B31B04C00A4FB37 /* warning.icns */; };
C2B573831B1CD5AE00303B36 /* SyncClientProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573821B1CD5AE00303B36 /* SyncClientProxy.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
0B13ECAC173C686900548DA1 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; };
0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; };
0B2BF60B176A43DB001246CD /* Finder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Finder.h; sourceTree = "<group>"; };
0BFC9ACB173C57E400CDD329 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
5BB74A8519DBF9BB001BAAAC /* FinishedIconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishedIconCache.h; sourceTree = "<group>"; };
@ -50,6 +56,16 @@
8C99F6931622D145002D2135 /* IconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IconCache.m; sourceTree = "<group>"; };
8D576316048677EA00EA77CD /* SyncStateFinder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SyncStateFinder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C22005731B31B04C00A4FB37 /* error_swm.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = error_swm.icns; path = ../../icons/icns/error_swm.icns; sourceTree = "<group>"; };
C22005741B31B04C00A4FB37 /* error.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = error.icns; path = ../../icons/icns/error.icns; sourceTree = "<group>"; };
C22005751B31B04C00A4FB37 /* ok_swm.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ok_swm.icns; path = ../../icons/icns/ok_swm.icns; sourceTree = "<group>"; };
C22005761B31B04C00A4FB37 /* ok.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = ok.icns; path = ../../icons/icns/ok.icns; sourceTree = "<group>"; };
C22005771B31B04C00A4FB37 /* sync_swm.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = sync_swm.icns; path = ../../icons/icns/sync_swm.icns; sourceTree = "<group>"; };
C22005781B31B04C00A4FB37 /* sync.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = sync.icns; path = ../../icons/icns/sync.icns; sourceTree = "<group>"; };
C22005791B31B04C00A4FB37 /* warning_swm.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = warning_swm.icns; path = ../../icons/icns/warning_swm.icns; sourceTree = "<group>"; };
C220057A1B31B04C00A4FB37 /* warning.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = warning.icns; path = ../../icons/icns/warning.icns; sourceTree = "<group>"; };
C2B573811B1CD5AE00303B36 /* SyncClientProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyncClientProxy.h; sourceTree = "<group>"; };
C2B573821B1CD5AE00303B36 /* SyncClientProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SyncClientProxy.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -70,6 +86,7 @@
089C166AFE841209C02AAC07 /* SyncStateFinder */ = {
isa = PBXGroup;
children = (
C2B573801B1CD5AE00303B36 /* common */,
08FB77AFFE84173DC02AAC07 /* Source */,
089C167CFE841241C02AAC07 /* Resources */,
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */,
@ -93,6 +110,14 @@
089C167CFE841241C02AAC07 /* Resources */ = {
isa = PBXGroup;
children = (
C22005731B31B04C00A4FB37 /* error_swm.icns */,
C22005741B31B04C00A4FB37 /* error.icns */,
C22005751B31B04C00A4FB37 /* ok_swm.icns */,
C22005761B31B04C00A4FB37 /* ok.icns */,
C22005771B31B04C00A4FB37 /* sync_swm.icns */,
C22005781B31B04C00A4FB37 /* sync.icns */,
C22005791B31B04C00A4FB37 /* warning_swm.icns */,
C220057A1B31B04C00A4FB37 /* warning.icns */,
8D576317048677EA00EA77CD /* Info.plist */,
8D5B49A704867FD3000E48DA /* InfoPlist.strings */,
);
@ -103,7 +128,6 @@
isa = PBXGroup;
children = (
0B2BF60A176A43DB001246CD /* Finder */,
0B08BAC21759627700C8351E /* GCDAsyncSocket */,
8C37DD99161593BD00016A95 /* FinderHook.h */,
8C37DD9A161593BD00016A95 /* FinderHook.m */,
692C18A316660C4600BF6A53 /* ContextMenuHandlers.h */,
@ -124,15 +148,6 @@
name = Source;
sourceTree = "<group>";
};
0B08BAC21759627700C8351E /* GCDAsyncSocket */ = {
isa = PBXGroup;
children = (
0B13ECAC173C686900548DA1 /* GCDAsyncSocket.h */,
0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */,
);
name = GCDAsyncSocket;
sourceTree = "<group>";
};
0B2BF60A176A43DB001246CD /* Finder */ = {
isa = PBXGroup;
children = (
@ -149,6 +164,16 @@
name = Products;
sourceTree = "<group>";
};
C2B573801B1CD5AE00303B36 /* common */ = {
isa = PBXGroup;
children = (
C2B573811B1CD5AE00303B36 /* SyncClientProxy.h */,
C2B573821B1CD5AE00303B36 /* SyncClientProxy.m */,
);
name = common;
path = ../common;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -178,7 +203,7 @@
attributes = {
LastUpgradeCheck = 0460;
};
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "SyncStateFinder" */;
buildConfigurationList = 1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
@ -188,7 +213,7 @@
French,
German,
);
mainGroup = 089C166AFE841209C02AAC07 /* SyncStateFinder` */;
mainGroup = 089C166AFE841209C02AAC07 /* SyncStateFinder */;
projectDirPath = "";
projectRoot = "";
targets = (
@ -202,7 +227,15 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C220057E1B31B04C00A4FB37 /* ok.icns in Resources */,
C22005821B31B04C00A4FB37 /* warning.icns in Resources */,
C220057F1B31B04C00A4FB37 /* sync_swm.icns in Resources */,
C220057C1B31B04C00A4FB37 /* error.icns in Resources */,
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */,
C22005801B31B04C00A4FB37 /* sync.icns in Resources */,
C220057D1B31B04C00A4FB37 /* ok_swm.icns in Resources */,
C220057B1B31B04C00A4FB37 /* error_swm.icns in Resources */,
C22005811B31B04C00A4FB37 /* warning_swm.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -213,10 +246,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B13ECAE173C687400548DA1 /* GCDAsyncSocket.m in Sources */,
8C37DD9F161593BD00016A95 /* FinderHook.m in Sources */,
8C99F6941622D145002D2135 /* IconCache.m in Sources */,
69948B361636D50E0093B6CE /* ContentManager.m in Sources */,
C2B573831B1CD5AE00303B36 /* SyncClientProxy.m in Sources */,
6993878616494C000044E4DF /* RequestManager.m in Sources */,
5BB74A8719DBF9BB001BAAAC /* FinishedIconCache.m in Sources */,
692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */,
@ -252,6 +285,8 @@
GCC_OPTIMIZATION_LEVEL = 0;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient;
OC_TEAM_IDENTIFIER_PREFIX = "";
PRODUCT_NAME = SyncStateFinder;
WRAPPER_EXTENSION = bundle;
};
@ -269,6 +304,8 @@
GCC_MODEL_TUNING = G5;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient;
OC_TEAM_IDENTIFIER_PREFIX = "";
PRODUCT_NAME = SyncStateFinder;
WRAPPER_EXTENSION = bundle;
};
@ -317,7 +354,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "SyncStateFinder" */ = {
1DEB911E08733D790010E9CD /* Build configuration list for PBXProject "OwnCloudFinder" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB911F08733D790010E9CD /* Debug */,

Просмотреть файл

@ -13,31 +13,27 @@
*/
#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"
#import "RequestManager.h"
#import "SyncClientProxy.h"
@interface RequestManager : NSObject
@interface OwnCloudFinderRequestManager : NSObject <SyncClientProxyDelegate>
{
GCDAsyncSocket* _socket;
SyncClientProxy *_syncClientProxy;
NSMutableArray* _requestQueue;
NSMutableDictionary* _registeredPathes;
NSMutableSet* _requestedPaths;
NSString *_shareMenuTitle;
BOOL _isConnected;
}
@property (nonatomic, retain) NSString* filterFolder;
+ (RequestManager*)sharedInstance;
+ (OwnCloudFinderRequestManager*)sharedInstance;
- (BOOL)isRegisteredPath:(NSString*)path isDirectory:(BOOL)isDir;
- (void)askOnSocket:(NSString*)path query:(NSString*)verb;
- (void)askForIcon:(NSString*)path isDirectory:(BOOL)isDir;
- (void)menuItemClicked:(NSDictionary*)actionDictionary;
- (void)start;
- (NSString*) shareItemTitle;

Просмотреть файл

@ -16,26 +16,32 @@
#import "IconCache.h"
#import "RequestManager.h"
#define READ_TAG 2422
static OwnCloudFinderRequestManager* sharedInstance = nil;
static RequestManager* sharedInstance = nil;
@implementation RequestManager
@implementation OwnCloudFinderRequestManager
- (id)init
{
if ((self = [super init]))
{
_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
// For the sake of allowing both the legacy and the FinderSync extensions to work with the same
// client build, use the same server name including the Team ID even though we won't be sandboxed.
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
// This was added to the bundle's Info.plist to get it from the build system
NSString *socketApiPrefix = [extBundle objectForInfoDictionaryKey:@"SocketApiPrefix"];
NSString *serverName = [socketApiPrefix stringByAppendingString:@".socketApi"];
// NSLog(@"OwnCloudFinderRequestManager serverName %@", serverName);
_isConnected = NO;
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
_registeredPathes = [[NSMutableDictionary alloc] init];
_requestedPaths = [[NSMutableSet alloc] init];
_shareMenuTitle = nil;
[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(start) userInfo:nil repeats:YES];
// The NSConnection will block until the distant object came back and this creates a loop hanging Finder.
// Start from a timer to have time to unwind the stack first.
[NSTimer scheduledTimerWithTimeInterval:0 target:_syncClientProxy selector:@selector(start) userInfo:nil repeats:NO];
}
return self;
@ -43,16 +49,14 @@ static RequestManager* sharedInstance = nil;
- (void)dealloc
{
[_socket setDelegate:nil delegateQueue:NULL];
[_socket disconnect];
[_socket release];
[_syncClientProxy release];
sharedInstance = nil;
[super dealloc];
}
+ (RequestManager*)sharedInstance
+ (OwnCloudFinderRequestManager*)sharedInstance
{
@synchronized(self)
{
@ -65,20 +69,6 @@ static RequestManager* sharedInstance = nil;
return sharedInstance;
}
- (void)askOnSocket:(NSString*)path query:(NSString*)verb
{
NSString *query = [NSString stringWithFormat:@"%@:%@\n", verb,path];
// NSLog(@"Query: %@", query);
NSData* data = [query dataUsingEncoding:NSUTF8StringEncoding];
[_socket writeData:data withTimeout:5 tag:4711];
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
[_socket readDataToData:stop withTimeout:-1 tag:READ_TAG];
}
- (BOOL)isRegisteredPath:(NSString*)path isDirectory:(BOOL)isDir
{
// check if the file in question is underneath a registered directory
@ -104,215 +94,71 @@ static RequestManager* sharedInstance = nil;
- (void)askForIcon:(NSString*)path isDirectory:(BOOL)isDir
{
NSString *verb = @"RETRIEVE_FILE_STATUS";
if( [self isRegisteredPath:path isDirectory:isDir] ) {
[_requestedPaths addObject:path];
if( _isConnected ) {
if(isDir) {
verb = @"RETRIEVE_FOLDER_STATUS";
}
[self askOnSocket:path query:verb];
} else {
[_requestQueue addObject:path];
[self start]; // try again to connect
}
[_syncClientProxy askForIcon:path isDirectory:isDir];
}
}
- (void)socket:(GCDAsyncSocket*)socket didReadData:(NSData*)data withTag:(long)tag
- (void)setResultForPath:(NSString*)path result:(NSString*)result
{
NSString *answer = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *chunks = nil;
if (answer != nil && [answer length] > 0) {
// cut a trailing newline
answer = [answer substringToIndex:[answer length] - 1];
chunks = [answer componentsSeparatedByString: @":"];
// The client will broadcast all changes, do not fill the cache for paths that Finder didn't ask for.
if ([_requestedPaths containsObject:path]) {
[[OwnCloudFinderContentManager sharedInstance] setResultForPath:path result:result];
}
ContentManager *contentman = [ContentManager sharedInstance];
if( chunks && [chunks count] > 0 && tag == READ_TAG ) {
// NSLog(@"READ from socket (%ld): <%@>", tag, answer);
if( [[chunks objectAtIndex:0] isEqualToString:@"STATUS"] ) {
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] ];
}
}
// The client will broadcast all changes, do not fill the cache for paths that Finder didn't ask for.
if ([_requestedPaths containsObject:path]) {
[contentman setResultForPath:path result:[chunks objectAtIndex:1]];
}
} else if( [[chunks objectAtIndex:0] isEqualToString:@"UPDATE_VIEW"] ) {
NSString *path = [chunks objectAtIndex:1];
[_requestedPaths removeAllObjects];
[contentman reFetchFileNameCacheForPath:path];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"REGISTER_PATH"] ) {
NSNumber *one = [NSNumber numberWithInt:1];
NSString *path = [chunks objectAtIndex:1];
// NSLog(@"Registering path: %@", path);
[_registeredPathes setObject:one forKey:path];
[contentman repaintAllWindows];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"UNREGISTER_PATH"] ) {
NSString *path = [chunks objectAtIndex:1];
[_registeredPathes removeObjectForKey:path];
[contentman repaintAllWindows];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"ICON_PATH"] ) {
NSString *path = [chunks objectAtIndex:1];
[[ContentManager sharedInstance] loadIconResourcePath:path];
} else if( [[chunks objectAtIndex:0 ] isEqualToString:@"SHARE_MENU_TITLE"] ) {
_shareMenuTitle = [[chunks objectAtIndex:1] copy];
// NSLog(@"Received shar menu title: %@", _shareMenuTitle);
} else {
NSLog(@"SyncState: Unknown command %@", [chunks objectAtIndex:0]);
}
} else if (tag != READ_TAG) {
NSLog(@"SyncState: Received unknown tag %ld <%@>", tag, answer);
}
// Read on and on
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
[_socket readDataToData:stop withTimeout:-1 tag:READ_TAG];
}
- (NSTimeInterval)socket:(GCDAsyncSocket*)socket shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length
- (void)reFetchFileNameCacheForPath:(NSString*)path
{
// Called if a read operation has reached its timeout without completing.
return 0.0;
[_requestedPaths removeAllObjects];
[[OwnCloudFinderContentManager sharedInstance] reFetchFileNameCacheForPath:path];
}
-(void)socket:(GCDAsyncSocket*)socket didConnectToUrl:(NSURL *)url {
// NSLog( @"Connected to sync client successfully on %@", url);
_isConnected = YES;
[self askOnSocket:@"" query:@"SHARE_MENU_TITLE"];
if( [_requestQueue count] > 0 ) {
// NSLog( @"We have to empty the queue");
for( NSString *path in _requestQueue ) {
[self askOnSocket:path query:@"RETRIEVE_FILE_STATUS"];
}
[_requestQueue removeAllObjects];
}
ContentManager *contentman = [ContentManager sharedInstance];
[contentman clearFileNameCache];
[contentman repaintAllWindows];
// Read for the UPDATE_VIEW requests
NSData* stop = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
[_socket readDataToData:stop withTimeout:-1 tag:READ_TAG];
- (void)registerPath:(NSString*)path
{
NSNumber *one = [NSNumber numberWithInt:1];
[_registeredPathes setObject:one forKey:path];
[[OwnCloudFinderContentManager sharedInstance] repaintAllWindows];
}
- (void)socketDidDisconnect:(GCDAsyncSocket*)socket withError:(NSError*)err
- (void)unregisterPath:(NSString*)path
{
[_registeredPathes removeObjectForKey:path];
[[OwnCloudFinderContentManager sharedInstance] repaintAllWindows];
}
- (void)setShareMenuTitle:(NSString*)title
{
_shareMenuTitle = title;
}
- (void)connectionDidDie
{
// NSLog(@"Socket DISconnected! %@", [err localizedDescription]);
_isConnected = NO;
// clear the registered pathes.
[_registeredPathes release];
_registeredPathes = [[NSMutableDictionary alloc] init];
[_requestedPaths removeAllObjects];
// clear the caches in conent manager
ContentManager *contentman = [ContentManager sharedInstance];
OwnCloudFinderContentManager *contentman = [OwnCloudFinderContentManager sharedInstance];
[contentman clearFileNameCache];
[contentman repaintAllWindows];
}
- (NSDate*)fileDate:(NSString*)fn
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = 0;
NSDictionary *oneAttributes = [fileManager attributesOfItemAtPath:fn error:&error];
if (!error) {
return [oneAttributes valueForKey:NSFileModificationDate];
}
return nil;
}
- (NSString*) getNewerFileOne:(NSString*)one two:(NSString*)two
{
if (!one) {
return two;
}
NSDate *oneDate = [self fileDate:one];
NSDate *twoDate = [self fileDate:two];
if (oneDate && twoDate) {
if ([oneDate compare:twoDate] == NSOrderedDescending) {
return one;
} else if ([oneDate compare:twoDate] == NSOrderedAscending) {
return two;
} else {
return two;
}
}
return one;
}
- (void)start
{
if (!_isConnected && ![_socket isConnected])
{
NSError *err = nil;
NSURL *url = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
if ([paths count])
{
// e.g file:///Users/guruz/Library/Caches/SyncStateHelper/ownCloud.socket
NSString *syncStateHelperDir = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"SyncStateHelper"];
NSError *pnsError = NULL;
NSArray *paths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:syncStateHelperDir error:&pnsError];
if (!pnsError && paths && [paths count] > 0) {
NSString *currentLatestPath = nil;
if (paths.count > 1) {
// NSLog(@"Possible paths: %@", paths);
}
for (int i = 0; i < paths.count; i++) {
NSString *currentPath = [syncStateHelperDir stringByAppendingPathComponent:[paths objectAtIndex:i]];
if (![currentPath hasSuffix:@".socket"]) {
continue;
}
currentLatestPath = [self getNewerFileOne:currentLatestPath two:currentPath];
}
// FIXME Instead of connecting to the newest socket we could go multi-socket to support multiple instances
if (currentLatestPath) {
url = [NSURL fileURLWithPath:currentLatestPath];
}
}
}
if (url) {
// NSLog(@"Connect Socket to %@", url);
[_socket connectToUrl:url withTimeout:1 error:&err];
}
}
}
- (void)menuItemClicked:(NSDictionary*)actionDictionary
{
// NSLog(@"RequestManager menuItemClicked %@", actionDictionary);
NSArray *filePaths = [actionDictionary valueForKey:@"files"];
for (int i = 0; i < filePaths.count; i++) {
[self askOnSocket:[filePaths objectAtIndex:i] query:@"SHARE"];
[_syncClientProxy askOnSocket:[filePaths objectAtIndex:i] query:@"SHARE"];
}
}
- (NSString*) shareItemTitle
{
if (_socket && _socket.isConnected && _shareMenuTitle) {
return _shareMenuTitle;
}
return nil;
return _shareMenuTitle;
}
@end

Просмотреть файл

@ -0,0 +1,28 @@
/*
* Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#import <Cocoa/Cocoa.h>
#import <FinderSync/FinderSync.h>
#import "SyncClientProxy.h"
@interface FinderSync : FIFinderSync <SyncClientProxyDelegate>
{
SyncClientProxy *_syncClientProxy;
NSMutableSet *_registeredDirectories;
NSMutableSet *_requestedUrls;
NSString *_shareMenuTitle;
}
@end

Просмотреть файл

@ -0,0 +1,170 @@
/*
* Copyright (C) by Jocelyn Turcotte <jturcotte@woboq.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#import "FinderSync.h"
@implementation FinderSync
- (instancetype)init
{
self = [super init];
FIFinderSyncController *syncController = [FIFinderSyncController defaultController];
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
// This was added to the bundle's Info.plist to get it from the build system
NSString *socketApiPrefix = [extBundle objectForInfoDictionaryKey:@"SocketApiPrefix"];
NSImage *ok = [extBundle imageForResource:@"ok.icns"];
NSImage *ok_swm = [extBundle imageForResource:@"ok_swm.icns"];
NSImage *sync = [extBundle imageForResource:@"sync.icns"];
NSImage *warning = [extBundle imageForResource:@"warning.icns"];
NSImage *error = [extBundle imageForResource:@"error.icns"];
[syncController setBadgeImage:ok label:@"Up to date" forBadgeIdentifier:@"OK"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW"];
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE"];
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR"];
[syncController setBadgeImage:ok_swm label:@"Shared" forBadgeIdentifier:@"OK+SWM"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"SYNC+SWM"];
[syncController setBadgeImage:sync label:@"Synchronizing" forBadgeIdentifier:@"NEW+SWM"];
[syncController setBadgeImage:warning label:@"Ignored" forBadgeIdentifier:@"IGNORE+SWM"];
[syncController setBadgeImage:error label:@"Error" forBadgeIdentifier:@"ERROR+SWM"];
// The Mach port name needs to:
// - Be prefixed with the code signing Team ID
// - Then infixed with the sandbox App Group
// - The App Group itself must be a prefix of (or equal to) the application bundle identifier
// We end up in the official signed client with: 9B5WD74GWJ.com.owncloud.desktopclient.socketApi
// With ad-hoc signing (the '-' signing identity) we must drop the Team ID.
// When the code isn't sandboxed (e.g. the OC client or the legacy overlay icon extension)
// the OS doesn't seem to put any restriction on the port name, so we just follow what
// the sandboxed App Extension needs.
// https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24
NSString *serverName = [socketApiPrefix stringByAppendingString:@".socketApi"];
// NSLog(@"FinderSync serverName %@", serverName);
_syncClientProxy = [[SyncClientProxy alloc] initWithDelegate:self serverName:serverName];
_registeredDirectories = [[NSMutableSet alloc] init];
_requestedUrls = [[NSMutableSet alloc] init];
_shareMenuTitle = nil;
[_syncClientProxy start];
return self;
}
#pragma mark - Primary Finder Sync protocol methods
- (void)endObservingDirectoryAtURL:(NSURL *)url
{
// The user is no longer seeing the container's contents.
// At this point we know that the status of any file as a direct child of url.filePathURL
// won't be displayed. Filter our _requestedUrls to get rid of them.
NSString *observedDirectoryPath = [url.filePathURL path];
[_requestedUrls filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSURL *requestedUrl = (NSURL *)evaluatedObject;
NSString *parentDir = [[requestedUrl path] stringByDeletingLastPathComponent];
return [parentDir isEqualToString:observedDirectoryPath];
}]];
}
- (void)requestBadgeIdentifierForURL:(NSURL *)url
{
[_requestedUrls addObject:url.filePathURL];
BOOL isDir;
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory: &isDir] == NO) {
NSLog(@"ERROR: Could not determine file type of %@", [url path]);
isDir = NO;
}
NSString* normalizedPath = [[url path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askForIcon:normalizedPath isDirectory:isDir];
}
#pragma mark - Menu and toolbar item support
- (NSMenu *)menuForMenuKind:(FIMenuKind)whichMenu
{
if (_shareMenuTitle) {
NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
[menu addItemWithTitle:_shareMenuTitle action:@selector(shareMenuAction:) keyEquivalent:@"title"];
return menu;
}
return nil;
}
- (IBAction)shareMenuAction:(id)sender
{
NSArray* items = [[FIFinderSyncController defaultController] selectedItemURLs];
[items enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
NSString* normalizedPath = [[obj path] decomposedStringWithCanonicalMapping];
[_syncClientProxy askOnSocket:normalizedPath query:@"SHARE"];
}];
}
#pragma mark - SyncClientProxyDelegate implementation
- (void)setResultForPath:(NSString*)path result:(NSString*)result
{
NSString *normalizedPath = [path decomposedStringWithCanonicalMapping];
[[FIFinderSyncController defaultController] setBadgeIdentifier:result forURL:[NSURL fileURLWithPath:normalizedPath]];
}
- (void)reFetchFileNameCacheForPath:(NSString*)path
{
// This shouldn't be necessary, and will be a problem when we
// filter values of _requestedUrls even though Finder might still
// have an old status in its cache (and therefore won't re-request it)
// but will do OK until we get the socket API to re-push the status of everything needed.
[_requestedUrls enumerateObjectsUsingBlock: ^(id url, BOOL *stop) {
if ([[url path] hasPrefix:path])
[self requestBadgeIdentifierForURL: url];
}];
}
- (void)registerPath:(NSString*)path
{
assert(_registeredDirectories);
[_registeredDirectories addObject:[NSURL fileURLWithPath:path]];
[FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
}
- (void)unregisterPath:(NSString*)path
{
[_registeredDirectories removeObject:[NSURL fileURLWithPath:path]];
[FIFinderSyncController defaultController].directoryURLs = _registeredDirectories;
}
- (void)setShareMenuTitle:(NSString*)title
{
_shareMenuTitle = title;
}
- (void)connectionDidDie
{
_shareMenuTitle = nil;
// This will tell Finder that this extension isn't attached to any directory
// until we can reconnect to the sync client.
[_registeredDirectories removeAllObjects];
[FIFinderSyncController defaultController].directoryURLs = nil;
}
@end

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
</array>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SocketApiPrefix</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>$(OC_APPLICATION_NAME) Extensions</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict/>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.FinderSync</string>
<key>NSExtensionPrincipalClass</key>
<string>FinderSync</string>
</dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,520 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
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 */; };
C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C2B573E91B1DA1FB00303B36 /* SyncClientProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B573E81B1DA1FB00303B36 /* SyncClientProxy.m */; };
C2B573F31B1DAD6400303B36 /* error.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EB1B1DAD6400303B36 /* error.iconset */; };
C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */ = {isa = PBXBuildFile; fileRef = C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */; };
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 */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C2B573951B1CD88000303B36 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C2B573D61B1CD9CE00303B36;
remoteInfo = FinderSyncExt;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
C2B573E11B1CD9CE00303B36 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
C2B573E21B1CD9CE00303B36 /* FinderSyncExt.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
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>"; };
C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = FinderSyncExt.appex; sourceTree = BUILT_PRODUCTS_DIR; };
C2B573DA1B1CD9CE00303B36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = FinderSyncExt.entitlements; sourceTree = "<group>"; };
C2B573DC1B1CD9CE00303B36 /* FinderSync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FinderSync.h; sourceTree = "<group>"; };
C2B573DD1B1CD9CE00303B36 /* FinderSync.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FinderSync.m; sourceTree = "<group>"; };
C2B573E71B1DA1FB00303B36 /* SyncClientProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyncClientProxy.h; sourceTree = "<group>"; };
C2B573E81B1DA1FB00303B36 /* SyncClientProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SyncClientProxy.m; sourceTree = "<group>"; };
C2B573EB1B1DAD6400303B36 /* error.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = error.iconset; path = ../../icons/nopadding/error.iconset; sourceTree = SOURCE_ROOT; };
C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; name = ok_swm.iconset; path = ../../icons/nopadding/ok_swm.iconset; sourceTree = SOURCE_ROOT; };
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; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
C2B573AE1B1CD91E00303B36 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573D41B1CD9CE00303B36 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
C2B573941B1CD88000303B36 = {
isa = PBXGroup;
children = (
C2B573E61B1DA1FB00303B36 /* common */,
C2B573B31B1CD91E00303B36 /* desktopclient */,
C2B573D81B1CD9CE00303B36 /* FinderSyncExt */,
C2B573B21B1CD91E00303B36 /* Products */,
);
sourceTree = "<group>";
};
C2B573B21B1CD91E00303B36 /* Products */ = {
isa = PBXGroup;
children = (
C2B573B11B1CD91E00303B36 /* desktopclient.app */,
C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */,
);
name = Products;
sourceTree = "<group>";
};
C2B573B31B1CD91E00303B36 /* desktopclient */ = {
isa = PBXGroup;
children = (
C2B573B41B1CD91E00303B36 /* Supporting Files */,
);
path = desktopclient;
sourceTree = "<group>";
};
C2B573B41B1CD91E00303B36 /* Supporting Files */ = {
isa = PBXGroup;
children = (
C2B573B51B1CD91E00303B36 /* Info.plist */,
C2B573B91B1CD91E00303B36 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
C2B573D81B1CD9CE00303B36 /* FinderSyncExt */ = {
isa = PBXGroup;
children = (
C2B573DC1B1CD9CE00303B36 /* FinderSync.h */,
C2B573DD1B1CD9CE00303B36 /* FinderSync.m */,
C2B573D91B1CD9CE00303B36 /* Supporting Files */,
);
path = FinderSyncExt;
sourceTree = "<group>";
};
C2B573D91B1CD9CE00303B36 /* Supporting Files */ = {
isa = PBXGroup;
children = (
C2B573EB1B1DAD6400303B36 /* error.iconset */,
C2B573EC1B1DAD6400303B36 /* ok_swm.iconset */,
C2B573ED1B1DAD6400303B36 /* ok.iconset */,
C2B573EF1B1DAD6400303B36 /* sync.iconset */,
C2B573F11B1DAD6400303B36 /* warning.iconset */,
C2B573DA1B1CD9CE00303B36 /* Info.plist */,
C2B573DB1B1CD9CE00303B36 /* FinderSyncExt.entitlements */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
C2B573E61B1DA1FB00303B36 /* common */ = {
isa = PBXGroup;
children = (
C2B573E71B1DA1FB00303B36 /* SyncClientProxy.h */,
C2B573E81B1DA1FB00303B36 /* SyncClientProxy.m */,
);
name = common;
path = ../common;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
C2B573B01B1CD91E00303B36 /* desktopclient */ = {
isa = PBXNativeTarget;
buildConfigurationList = C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */;
buildPhases = (
C2B573AD1B1CD91E00303B36 /* Sources */,
C2B573AE1B1CD91E00303B36 /* Frameworks */,
C2B573AF1B1CD91E00303B36 /* Resources */,
C2B573E11B1CD9CE00303B36 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */,
);
name = desktopclient;
productName = desktopclient;
productReference = C2B573B11B1CD91E00303B36 /* desktopclient.app */;
productType = "com.apple.product-type.application";
};
C2B573D61B1CD9CE00303B36 /* FinderSyncExt */ = {
isa = PBXNativeTarget;
buildConfigurationList = C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */;
buildPhases = (
C2B573D31B1CD9CE00303B36 /* Sources */,
C2B573D41B1CD9CE00303B36 /* Frameworks */,
C2B573D51B1CD9CE00303B36 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = FinderSyncExt;
productName = FinderSyncExt;
productReference = C2B573D71B1CD9CE00303B36 /* FinderSyncExt.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
C2B573951B1CD88000303B36 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
TargetAttributes = {
C2B573B01B1CD91E00303B36 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 9B5WD74GWJ;
};
C2B573D61B1CD9CE00303B36 = {
CreatedOnToolsVersion = 6.3.1;
DevelopmentTeam = 9B5WD74GWJ;
SystemCapabilities = {
com.apple.ApplicationGroups.Mac = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "OwnCloudFinderSync" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = C2B573941B1CD88000303B36;
productRefGroup = C2B573B21B1CD91E00303B36 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C2B573B01B1CD91E00303B36 /* desktopclient */,
C2B573D61B1CD9CE00303B36 /* FinderSyncExt */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
C2B573AF1B1CD91E00303B36 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573D21B1CD94B00303B36 /* main.m in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573D51B1CD9CE00303B36 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573F91B1DAD6400303B36 /* warning.iconset in Resources */,
C2B573F31B1DAD6400303B36 /* error.iconset in Resources */,
C2B573F71B1DAD6400303B36 /* sync.iconset in Resources */,
C2B573F41B1DAD6400303B36 /* ok_swm.iconset in Resources */,
C2B573F51B1DAD6400303B36 /* ok.iconset in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
C2B573AD1B1CD91E00303B36 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573BA1B1CD91E00303B36 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C2B573D31B1CD9CE00303B36 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C2B573E91B1DA1FB00303B36 /* SyncClientProxy.m in Sources */,
C2B573DE1B1CD9CE00303B36 /* FinderSync.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
C2B573E01B1CD9CE00303B36 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C2B573D61B1CD9CE00303B36 /* FinderSyncExt */;
targetProxy = C2B573DF1B1CD9CE00303B36 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
C2B573991B1CD88000303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Debug;
};
C2B5739A1B1CD88000303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
};
name = Release;
};
C2B573CD1B1CD91E00303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = desktopclient/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
};
name = Debug;
};
C2B573CE1B1CD91E00303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = desktopclient/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
};
name = Release;
};
C2B573E41B1CD9CE00303B36 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = FinderSyncExt/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
OC_APPLICATION_NAME = ownCloud;
OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient;
OC_TEAM_IDENTIFIER_PREFIX = "";
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Debug;
};
C2B573E51B1CD9CE00303B36 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = FinderSyncExt/FinderSyncExt.entitlements;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = FinderSyncExt/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
OC_APPLICATION_NAME = ownCloud;
OC_APPLICATION_REV_DOMAIN = com.owncloud.desktopclient;
OC_TEAM_IDENTIFIER_PREFIX = "";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SDKROOT = macosx;
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
C2B573981B1CD88000303B36 /* Build configuration list for PBXProject "OwnCloudFinderSync" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2B573991B1CD88000303B36 /* Debug */,
C2B5739A1B1CD88000303B36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C2B573CC1B1CD91E00303B36 /* Build configuration list for PBXNativeTarget "desktopclient" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2B573CD1B1CD91E00303B36 /* Debug */,
C2B573CE1B1CD91E00303B36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C2B573E31B1CD9CE00303B36 /* Build configuration list for PBXNativeTarget "FinderSyncExt" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C2B573E41B1CD9CE00303B36 /* Debug */,
C2B573E51B1CD9CE00303B36 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = C2B573951B1CD88000303B36 /* Project object */;
}

Просмотреть файл

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0630"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573D61B1CD9CE00303B36"
BuildableName = "FinderSyncExt.appex"
BlueprintName = "FinderSyncExt"
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573B01B1CD91E00303B36"
BuildableName = "desktopclient.app"
BlueprintName = "desktopclient"
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573D61B1CD9CE00303B36"
BuildableName = "FinderSyncExt.appex"
BlueprintName = "FinderSyncExt"
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573B01B1CD91E00303B36"
BuildableName = "desktopclient.app"
BlueprintName = "desktopclient"
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "C2B573B01B1CD91E00303B36"
BuildableName = "desktopclient.app"
BlueprintName = "desktopclient"
ReferencedContainer = "container:OwnCloudFinderSync.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

Просмотреть файл

@ -0,0 +1,30 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.owncloud.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,16 @@
//
// main.m
// desktopclient
//
// Created by Jocelyn Turcotte on 01/06/15.
//
//
// This is fake application bundle with the same bundle ID as the real desktop client.
// Xcode needs a wrapping application to allow the extension to be debugged.
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
}

Просмотреть файл

@ -0,0 +1,43 @@
/*
* 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)setShareMenuTitle:(NSString*)title;
- (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

Просмотреть файл

@ -0,0 +1,147 @@
/*
* 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 querrying
[self askOnSocket:@"" query:@"SHARE_MENU_TITLE"];
}
- (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
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:@"SHARE_MENU_TITLE"] ) {
[_delegate setShareMenuTitle:[chunks objectAtIndex:1]];
} 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

Просмотреть файл

@ -1,4 +1,10 @@
#!/bin/sh
echo "Not used anymore, please do (from build dir) (this is <= 10.9 only)"
echo sudo cp -r ./shell_integration/MacOSX/Release/SyncStateFinder.osax /Library/ScriptingAdditions/
echo killall Finder
exit 1
SELFPATH=`dirname $0`
# osascript $SELFPATH/unload.scpt

Двоичные данные
shell_integration/icons/128x128/.DS_Store поставляемый

Двоичный файл не отображается.

Двоичные данные
shell_integration/icons/32x32/.DS_Store поставляемый

Двоичный файл не отображается.

Двоичные данные
shell_integration/icons/512x512/.DS_Store поставляемый

Двоичный файл не отображается.

Просмотреть файл

@ -1,12 +1,3 @@
# Install the Mac icon container into the Mac Bundle.
if( BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY )
set (ICON_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/icons)
file(GLOB mac_icons "icns/*icns")
install(FILES ${mac_icons} DESTINATION ${ICON_DIR})
endif()
if( UNIX AND NOT APPLE )
SET(ICON_DIR ${DATADIR}/icons/hicolor)
@ -22,6 +13,3 @@ if( UNIX AND NOT APPLE )
ENDFOREACH(size)
endif()

Просмотреть файл

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Sync" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g>
<g>
<g>
<circle fill="#E0D92D" cx="64" cy="64" r="61.9"/>
<path fill="#8E7409" d="M64,128C28.7,128,0,99.3,0,64S28.7,0,64,0s64,28.7,64,64S99.3,128,64,128z M64,4.1C31,4.1,4.1,31,4.1,64
c0,33,26.9,59.9,59.9,59.9c33,0,59.9-26.9,59.9-59.9C123.9,31,97,4.1,64,4.1z"/>
</g>
</g>
<g>
<g>
<g>
<path fill="#FFFFFF" d="M64,107.4c-5.6,0-10.2-4.6-10.2-10.2C53.8,91.6,58.4,87,64,87c5.6,0,10.2,4.6,10.2,10.2
C74.2,102.8,69.6,107.4,64,107.4z M64,81.3c-8.3,0-8.3-7.3-8.3-10.2L52,30.9v-0.1c0-5.6,5.4-10.2,12-10.2c6.6,0,12,4.6,12,10.2
v0.1l-3.7,40.3C72.3,74,72.3,81.3,64,81.3z"/>
</g>
<g>
<path fill="#8E7409" d="M64,21.9c5.9,0,10.7,4,10.7,8.8l-3.7,40.3c0,4.9-1.1,8.8-7,8.8c-5.9,0-6.9-4-6.9-8.8l-3.7-40.3
C53.3,25.9,58.1,21.9,64,21.9 M64,88.3c4.9,0,8.9,4,8.9,8.8c0,4.9-4,8.9-8.9,8.9c-4.9,0-8.9-4-8.9-8.9
C55.1,92.3,59.1,88.3,64,88.3 M64,19.2c-3.5,0-6.8,1.1-9.3,3.2c-2.7,2.2-4.1,5.2-4.1,8.4v0.1l0,0.1l3.7,40.1
c0,2.3,0.2,5.2,1.7,7.6c1.6,2.6,4.3,3.9,8,3.9c3.7,0,6.4-1.3,8-3.9c1.5-2.3,1.7-5.3,1.7-7.6L77.4,31l0-0.1v-0.1
c0-3.2-1.5-6.2-4.1-8.4C70.8,20.3,67.5,19.2,64,19.2L64,19.2z M64,85.6c-6.4,0-11.6,5.2-11.6,11.6c0,6.4,5.2,11.6,11.6,11.6
c6.4,0,11.6-5.2,11.6-11.6C75.6,90.8,70.4,85.6,64,85.6L64,85.6z"/>
</g>
</g>
</g>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.7 KiB

Просмотреть файл

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Sync" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g>
<g>
<g>
<circle fill="#B23015" cx="64" cy="64" r="61.9"/>
<path fill="#981D05" d="M64,128C28.7,128,0,99.3,0,64S28.7,0,64,0s64,28.7,64,64S99.3,128,64,128z M64,4.1C31,4.1,4.1,31,4.1,64
S31,123.9,64,123.9c33,0,59.9-26.9,59.9-59.9S97,4.1,64,4.1z"/>
</g>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M41.8,95.2c-2.4,0-4.4-0.9-6.2-2.6c-1.7-1.7-2.7-3.9-2.8-6.4c-0.1-2.6,0.7-4.8,2.5-6.8L50.8,64L35.4,48.6
c-1.9-1.9-2.7-4-2.5-6.5c0.2-2.3,1.1-4.5,2.7-6.3l0,0l0,0c1.9-1.9,4-2.9,6.3-2.9c0.2,0,0.4,0,0.6,0c2.4,0.2,4.5,1.1,6.4,2.8l0,0
L64,50.7l15.4-15.2c1.8-1.8,3.9-2.7,6.3-2.7c0.1,0,0.1,0,0.2,0c2.4,0.1,4.6,1,6.5,2.8l0,0c1.7,1.7,2.6,3.9,2.6,6.5
c0,2.6-0.9,4.8-2.6,6.6L77.4,64l15.1,15.2c1.7,1.7,2.6,3.9,2.7,6.5c0.1,2.6-0.8,5-2.7,6.9c-1.7,1.7-4,2.6-6.6,2.6
c-2.6,0-4.9-1-6.8-3L64,77.4L48.9,92.6l0,0c-1.7,1.5-3.8,2.4-6.4,2.6C42.3,95.2,42,95.2,41.8,95.2z"/>
</g>
<g>
<path fill="#981D05" d="M41.9,34.1c0.2,0,0.3,0,0.5,0c2,0.2,3.9,1,5.5,2.5l16,16l16.4-16.2c1.5-1.5,3.3-2.3,5.3-2.3
c0.1,0,0.1,0,0.2,0c2.1,0,4,0.8,5.6,2.4c1.5,1.5,2.2,3.3,2.2,5.6c0,2.2-0.7,4.1-2.2,5.7L75.4,64l16,16.2c1.5,1.5,2.3,3.3,2.3,5.6
c0.1,2.3-0.7,4.2-2.3,5.9c-1.5,1.5-3.3,2.2-5.6,2.2c-2.3,0-4.2-0.9-5.9-2.6L64,75.5l-16,16.2c-1.5,1.3-3.3,2.1-5.5,2.2
c-0.2,0-0.4,0-0.6,0c-2,0-3.7-0.7-5.2-2.2c-1.5-1.5-2.3-3.3-2.4-5.5c-0.1-2.2,0.6-4.1,2.2-5.7L52.7,64L36.3,47.6
c-1.6-1.6-2.3-3.4-2.1-5.4c0.2-2.1,0.9-3.9,2.3-5.6C38.3,35,40,34.1,41.9,34.1 M41.9,31.4c-2.6,0-5,1.1-7.2,3.3l-0.1,0.1
l-0.1,0.1c-1.8,2.1-2.8,4.5-3,7.1c-0.2,2.9,0.8,5.5,2.9,7.6L48.9,64L34.4,78.5l0,0l0,0c-2.1,2.2-3.1,4.8-2.9,7.8
c0.2,2.9,1.2,5.3,3.2,7.3c2,2,4.4,3,7.2,3c0.3,0,0.5,0,0.8,0c2.8-0.2,5.2-1.2,7.2-2.9l0.1-0.1l0.1-0.1L64,79.4L78,93.2
c2.2,2.3,4.8,3.4,7.8,3.4c3,0,5.6-1,7.6-3c2.2-2.2,3.3-4.9,3.1-7.9c-0.1-3-1.2-5.5-3.1-7.5L79.3,64l14.1-14.2l0,0l0,0
c2-2.1,3-4.6,3-7.6c0-3-1-5.5-3-7.5l0,0l0,0c-2.2-2-4.7-3.1-7.4-3.2c-0.1,0-0.1,0-0.2,0c-2.8,0-5.2,1-7.3,3.1L64,48.8L49.9,34.7
l0-0.1l-0.1-0.1c-2.1-1.9-4.5-2.9-7.2-3.2C42.4,31.4,42.1,31.4,41.9,31.4L41.9,31.4z"/>
</g>
</g>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 2.5 KiB

Просмотреть файл

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Sync" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g>
<g>
<path fill="#5EB220" d="M64,2.1c34.2,0,61.9,27.7,61.9,61.9S98.2,125.9,64,125.9C29.8,125.9,2.1,98.2,2.1,64S29.8,2.1,64,2.1z"/>
<path fill="#3A9804" d="M64,128C28.7,128,0,99.3,0,64S28.7,0,64,0s64,28.7,64,64S99.3,128,64,128z M64,4.1C31,4.1,4.1,31,4.1,64
S31,123.9,64,123.9c33,0,59.9-26.9,59.9-59.9S97,4.1,64,4.1z"/>
</g>
<g>
<g>
<polygon fill="#FFFFFF" points="25.7,76.8 35.9,63.8 53,77.3 87.1,31 100.3,40.7 61.3,93.9 56.2,100.7 "/>
</g>
<g>
<path fill="#3A9804" d="M87.3,32.4L98.9,41l-4.3,5.8L60.4,93.2l-4.4,6l-5.8-4.6L32.8,81.1l-5.7-4.4L36,65.3l5.7,4.4l11.5,9
L83,38.2L87.3,32.4 M86.8,29.5l-1.2,1.7L81.3,37L52.8,75.8L43,68.1l-5.7-4.4l-1.6-1.3L34.4,64l-8.9,11.4L24.3,77l1.6,1.3l5.7,4.4
l17.4,13.6l5.8,4.6l1.7,1.3l1.3-1.7l4.4-6L96.3,48l4.3-5.8l1.2-1.7l-1.7-1.2l-11.6-8.5L86.8,29.5L86.8,29.5z"/>
</g>
</g>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Просмотреть файл

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Sync" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g>
<g>
<g>
<g>
<path fill="#5EB220" d="M64,2.1c34.2,0,61.9,27.7,61.9,61.9S98.2,125.9,64,125.9C29.8,125.9,2.1,98.2,2.1,64S29.8,2.1,64,2.1z"
/>
</g>
<g>
<path fill="#3A9804" d="M64,128C28.7,128,0,99.3,0,64S28.7,0,64,0s64,28.7,64,64S99.3,128,64,128z M64,4.1C31,4.1,4.1,31,4.1,64
S31,123.9,64,123.9c33,0,59.9-26.9,59.9-59.9S97,4.1,64,4.1z"/>
</g>
</g>
</g>
<g transform="translate(0 -1036.4)">
<g>
<g>
<path fill="#FFFFFF" d="M83.9,1059.9c-7.9,0-14.2,6.4-14.2,14.2c0,0.4,0,0.9,0.1,1.3l-27.4,14c-2.5-2.1-5.7-3.4-9.2-3.4
c-7.9,0-14.2,6.4-14.2,14.2c0,7.9,6.4,14.2,14.2,14.2c3.2,0,6.1-1,8.5-2.8l28.2,14.3c0,0.2-0.1,0.5-0.1,0.8
c0,7.9,6.4,14.2,14.2,14.2c7.8,0,14.2-6.4,14.2-14.2c0-7.9-6.4-14.2-14.2-14.2c-3.7,0-7.1,1.4-9.6,3.7l-27.2-13.9
c0.1-0.7,0.2-1.4,0.2-2.2c0-0.4-0.1-0.8-0.1-1.2l27.5-14c2.5,2.1,5.7,3.4,9.2,3.4c7.9,0,14.2-6.4,14.2-14.2
C98.1,1066.2,91.7,1059.8,83.9,1059.9L83.9,1059.9z"/>
<path fill="#3A9804" d="M83.9,1141.9c-8.4,0-15.2-6.8-15.2-15.1c0-0.1,0-0.2,0-0.2l-27.1-13.8c-2.5,1.7-5.4,2.6-8.5,2.6
c-8.3,0-15.1-6.8-15.1-15.1c0-8.3,6.8-15.1,15.1-15.1c3.4,0,6.7,1.1,9.4,3.2l26.3-13.4c0-0.3,0-0.5,0-0.8
c0-8,6.2-14.6,14.1-15.1l0,0l1-0.1c8.3,0,15.1,6.8,15.1,15.1c0,8.4-6.8,15.2-15.1,15.2c-3.4,0-6.7-1.1-9.3-3.2l-26.4,13.4
c0,0.2,0,0.5,0,0.7c0,0.6-0.1,1.1-0.1,1.7l26.1,13.3c2.7-2.3,6.2-3.5,9.7-3.5c8.3,0,15.1,6.8,15.1,15.2
C99,1135.1,92.2,1141.9,83.9,1141.9z M41.4,1110.6l29.2,14.9l-0.1,0.9c0,0.1,0,0.3,0,0.4c0,7.3,6,13.3,13.3,13.3
c7.3,0,13.3-6,13.3-13.3c0-7.3-6-13.3-13.3-13.3c-3.3,0-6.5,1.2-9,3.5l-0.5,0.4l-28.3-14.5l0.1-0.6c0.1-0.7,0.2-1.4,0.2-2.1
c0-0.3,0-0.5,0-0.8l-0.1-1l28.5-14.5l0.5,0.4c2.4,2,5.5,3.2,8.6,3.2c7.3,0,13.3-6,13.3-13.3c0-7.1-5.6-12.9-12.6-13.3l-0.7,0
c-7.3,0-13.3,6-13.3,13.3c0,0.4,0,0.7,0.1,1.1l0.1,0.6l-0.5,0.4l-28,14.3l-0.5-0.4c-2.4-2-5.5-3.2-8.6-3.2
c-7.3,0-13.3,6-13.3,13.3c0,7.3,6,13.3,13.3,13.3c2.9,0,5.6-0.9,7.9-2.6L41.4,1110.6z"/>
</g>
<g>
<path fill="#FFFFFF" d="M83.9,1141.2c-8,0-14.4-6.5-14.4-14.4c0-0.2,0-0.3,0-0.5c0-0.1,0-0.1,0-0.2l-28-14.2
c-2.4,1.8-5.4,2.7-8.5,2.7c-7.9,0-14.4-6.5-14.4-14.4c0-7.9,6.5-14.4,14.4-14.4c3.4,0,6.7,1.2,9.3,3.4l27.2-13.9l0-0.1
c0-0.4-0.1-0.7-0.1-1.1c0-7.9,6.4-14.3,14.2-14.4l0-0.1h0.2c7.9,0,14.4,6.5,14.4,14.4c0,8-6.5,14.4-14.4,14.4
c-3.4,0-6.6-1.2-9.2-3.3L47.4,1099l0,0.2c0,0.3,0.1,0.6,0.1,0.9c0,0.7-0.1,1.4-0.2,2.1l27,13.8c2.6-2.4,6.1-3.7,9.6-3.7
c7.9,0,14.4,6.5,14.4,14.4C98.3,1134.7,91.8,1141.2,83.9,1141.2z M41.5,1111.4L41.5,1111.4l28.4,14.4l0,0.1c0,0.1,0,0.2,0,0.3
c0,0.2,0,0.3,0,0.5c0,7.7,6.3,14,14.1,14c7.7,0,14-6.3,14-14c0-7.8-6.3-14.1-14-14.1c-3.5,0-6.9,1.3-9.5,3.7l-0.1,0.1l-0.1-0.1
l-27.3-14l0-0.1c0.1-0.7,0.2-1.4,0.2-2.2c0-0.3,0-0.6-0.1-0.9c0-0.1,0-0.2,0-0.3l0-0.1l0.1-0.1l27.6-14l0.1,0.1
c2.5,2.1,5.8,3.3,9.1,3.3c7.7,0,14-6.3,14-14.1c0-7.7-6.2-13.9-13.8-14l0,0.1h-0.2c-7.8,0-14.1,6.3-14.1,14c0,0.4,0,0.7,0.1,1
l0,0.3l-0.1,0.1l-27.5,14l-0.1-0.1c-2.5-2.2-5.8-3.3-9.1-3.3c-7.7,0-14,6.3-14,14c0,7.7,6.3,14,14,14
C36.1,1114.2,39,1113.3,41.5,1111.4L41.5,1111.4z"/>
<path fill="#3A9804" d="M83.9,1142.1c-8.5,0-15.3-6.9-15.3-15.3c0,0,0-0.1,0-0.1l-26.9-13.7c-2.5,1.7-5.5,2.6-8.6,2.6
c-8.4,0-15.3-6.9-15.3-15.3c0-8.4,6.9-15.3,15.3-15.3c3.4,0,6.7,1.1,9.4,3.2l26.1-13.3c0-0.2,0-0.4,0-0.7
c0-8,6.2-14.6,14.1-15.3l0,0l1-0.1c8.6,0,15.5,6.9,15.5,15.3c0,8.5-6.9,15.3-15.3,15.3c-3.4,0-6.7-1.1-9.3-3.2l-26.2,13.3
c0,0.2,0,0.4,0,0.6c0,0.5,0,1-0.1,1.6l25.8,13.2c2.7-2.3,6.2-3.5,9.7-3.5c8.4,0,15.3,6.9,15.3,15.3
C99.2,1135.2,92.3,1142.1,83.9,1142.1z M41.3,1110.4l0.7,0.3l28.8,14.7l-0.1,1.1c0,0.1,0,0.2,0,0.4c0,7.2,5.9,13.1,13.1,13.1
c7.2,0,13.1-5.9,13.1-13.1c0-7.2-5.9-13.1-13.1-13.1c-3.3,0-6.4,1.2-8.8,3.4l-0.5,0.4l-0.6-0.2l-28-14.3l0.1-0.6
c0.1-0.8,0.2-1.5,0.2-2.2c0-0.3,0-0.5,0-0.8l-0.1-1l0.5-0.4l28.2-14.4l0.5,0.4c2.5,2.1,5.5,3.2,8.6,3.2
c7.2,0,13.1-5.9,13.1-13.1c0-6.9-5.5-12.7-12.3-13.1l-0.6,0c-7.5,0-13.4,5.9-13.4,13.1c0,0.3,0,0.7,0.1,1l0.1,1l-0.5,0.3
l-28.2,14.4l-0.5-0.4c-2.4-2.1-5.5-3.2-8.6-3.2c-7.2,0-13.1,5.9-13.1,13.1c0,7.2,5.9,13.1,13.1,13.1c2.9,0,5.6-0.9,7.8-2.5
L41.3,1110.4z"/>
</g>
</g>
</g>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 4.6 KiB

Просмотреть файл

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Sync" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
<g>
<g>
<circle fill="#2268AB" cx="64" cy="64" r="61.934"/>
<path fill="#114999" d="M64,128C28.711,128,0,99.289,0,64S28.711,0,64,0s64,28.711,64,64S99.289,128,64,128z M64,4.132
C30.989,4.132,4.132,30.987,4.132,64S30.989,123.868,64,123.868S123.868,97.013,123.868,64S97.011,4.132,64,4.132z"/>
</g>
<g>
<g>
<g>
<path fill="#FFFFFF" d="M85.311,53.564c-3.957-8.111-12.221-13.307-21.264-13.307c-1.375,0-2.764,0.121-4.125,0.364
c-8.236,1.448-15.172,7.237-18.111,15.105l-0.264,0.705l-14.818,2.616l0.346-1.871c2.836-15.363,15.068-27.507,30.436-30.216
c2.164-0.38,4.361-0.575,6.543-0.575c12.025,0,23.222,5.73,30.3,15.411l4.771-6.193l1.889,21.721l0.325,1.479l-0.046,0.004
v0.007l-23.129,4.048L85.311,53.564z"/>
</g>
<g>
<path fill="#114999" d="M64.053,27.711c12.314,0,23.643,6.318,30.25,16.325l3.8-4.938l1.6,18.411
c0.007,0.048,0.025,0.111,0.036,0.159l-0.025,0.003l0.014,0.074l-18.446,3.232l5.568-7.243
c-3.996-8.916-12.936-14.798-22.803-14.798c-1.436,0-2.889,0.125-4.353,0.38c-9.054,1.595-16.114,7.893-19.121,15.948
l-12.197,2.152c2.672-14.457,14.061-26.452,29.368-29.152C59.861,27.891,61.971,27.711,64.053,27.711 M64.053,25.064
c-2.257,0-4.536,0.2-6.768,0.595c-7.957,1.405-15.164,5.177-20.846,10.911c-5.55,5.605-9.239,12.65-10.664,20.368l-0.693,3.745
l3.754-0.661l12.196-2.152l1.49-0.264l0.528-1.415c1.343-3.602,3.6-6.819,6.525-9.307c3.014-2.557,6.668-4.273,10.575-4.962
c1.289-0.225,2.596-0.343,3.896-0.343c8.264,0,15.839,4.602,19.704,11.845l-4.564,5.941l-4.143,5.386l6.697-1.168l18.443-3.232
l1.371-0.24l1.393-0.173l-0.625-2.82l-1.582-18.248l-0.593-6.761l-4.143,5.377l-1.65,2.145
c-3.222-3.998-7.236-7.363-11.775-9.832C76.9,26.702,70.489,25.064,64.053,25.064L64.053,25.064z"/>
</g>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M64.032,101.541c-11.982,0-23.157-5.701-30.254-15.341l-4.825,6.289l-1.918-21.98
c-0.007-0.032-0.011-0.063-0.014-0.087l-0.147-1.245l13.597-2.398l0.018,0.096l9.422-1.653l-7.093,9.234
c3.979,8.048,12.221,13.207,21.211,13.207c1.368,0,2.761-0.12,4.125-0.362c8.154-1.439,15.068-7.148,18.036-14.902l0.268-0.704
l14.857-2.62l-0.361,1.884C99.543,78.37,95.968,85.127,90.618,90.5c-5.475,5.498-12.411,9.121-20.057,10.466
C68.404,101.348,66.207,101.541,64.032,101.541z"/>
</g>
<g>
<path fill="#114999" d="M46.793,67.111l-5.518,7.182c4.021,8.855,12.918,14.691,22.754,14.691c1.432,0,2.89-0.123,4.353-0.384
c8.975-1.581,15.997-7.784,19.043-15.732l12.232-2.159c-2.743,14.366-14.086,26.268-29.325,28.957
c-2.118,0.37-4.221,0.554-6.3,0.554c-12.278,0-23.582-6.291-30.204-16.255l-3.85,5.019l-1.632-18.652
c-0.007-0.025-0.007-0.052-0.011-0.073l11.054-1.948c0.004,0.029,0.018,0.059,0.025,0.095L46.793,67.111 M53.032,63.332
l-6.697,1.173l-4.764,0.834l-0.014-0.093l-2.629,0.463l-11.05,1.948l-2.471,0.432l0.304,2.487
c0.004,0.029,0.007,0.059,0.011,0.095l1.622,18.545l0.589,6.779l4.143-5.398l1.711-2.23c3.225,3.986,7.239,7.329,11.761,9.784
c5.675,3.084,12.068,4.713,18.486,4.713c2.25,0,4.525-0.2,6.761-0.591c7.914-1.398,15.097-5.145,20.765-10.841
c5.535-5.559,9.232-12.555,10.696-20.223l0.718-3.768l-3.775,0.668l-12.232,2.156l-1.475,0.259l-0.536,1.402
c-1.361,3.55-3.618,6.723-6.529,9.173c-2.996,2.522-6.629,4.218-10.503,4.902c-1.29,0.225-2.6,0.343-3.893,0.343
c-8.214,0-15.764-4.564-19.65-11.746l4.511-5.872L53.032,63.332L53.032,63.332z"/>
</g>
</g>
</g>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 3.8 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_128x128.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.4 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_128x128@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_16x16.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 603 B

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_16x16@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_256x256.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_256x256@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 25 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_32x32.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
shell_integration/icons/nopadding/error.iconset/icon_32x32@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.4 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_128x128.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.5 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_128x128@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_16x16.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 615 B

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_16x16@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_256x256.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_256x256@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 31 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_32x32.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
shell_integration/icons/nopadding/ok.iconset/icon_32x32@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.7 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_128x128.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.3 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_128x128@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_16x16.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 647 B

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_16x16@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_256x256.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_256x256@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 34 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_32x32.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
shell_integration/icons/nopadding/ok_swm.iconset/icon_32x32@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.2 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_128x128.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.5 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_128x128@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_16x16.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 694 B

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_16x16@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_256x256.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_256x256@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 35 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_32x32.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичные данные
shell_integration/icons/nopadding/sync.iconset/icon_32x32@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.4 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_128x128.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.9 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_128x128@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_16x16.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 523 B

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_16x16@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_256x256.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_256x256@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_32x32.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
shell_integration/icons/nopadding/warning.iconset/icon_32x32@2x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.5 KiB

Просмотреть файл

@ -34,7 +34,6 @@
#include "theme.h"
#include "netrcparser.h"
#include "version.h"
#include "config.h"
#ifdef Q_OS_WIN32

Просмотреть файл

@ -94,6 +94,7 @@ set(updater_SRCS
IF( APPLE )
list(APPEND client_SRCS cocoainitializer_mac.mm)
list(APPEND client_SRCS settingsdialogmac.cpp)
list(APPEND client_SRCS socketapisocket_mac.mm)
list(APPEND client_SRCS systray.mm)
if(SPARKLE_FOUND)

Просмотреть файл

@ -569,6 +569,7 @@ void Folder::slotWatchedPathChanged(const QString& path)
// the sync is doing to filter out our own changes.
bool ownChange = false;
#ifdef Q_OS_MAC
Q_UNUSED(path)
// On OSX the folder watcher does not report changes done by our
// own process. Therefore nothing needs to be done here!
#else

Просмотреть файл

@ -47,11 +47,15 @@ static void callback(
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
Q_UNUSED(streamRef)
Q_UNUSED(eventFlags)
Q_UNUSED(eventIds)
qDebug() << "FolderWatcherPrivate::callback by OS X";
QStringList paths;
CFArrayRef eventPaths = (CFArrayRef)eventPathsVoid;
for (int i = 0; i < numEvents; ++i) {
for (int i = 0; i < static_cast<int>(numEvents); ++i) {
CFStringRef path = reinterpret_cast<CFStringRef>(CFArrayGetValueAtIndex(eventPaths, i));
QString qstring;

Просмотреть файл

@ -107,29 +107,33 @@ ownCloudGui::ownCloudGui(Application *parent) :
void ownCloudGui::setupOverlayIcons()
{
#ifdef Q_OS_MAC
const QLatin1String finderExtension("/Library/ScriptingAdditions/SyncStateFinder.osax");
if(QFile::exists(finderExtension) ) {
QString aScript = QString::fromUtf8("tell application \"Finder\"\n"
" try\n"
" «event OWNCload»\n"
" end try\n"
"end tell\n");
// Make sure that we only send the load event to the legacy plugin when
// using OS X <= 10.9 since 10.10 starts using the new FinderSync one.
if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) {
const QLatin1String finderExtension("/Library/ScriptingAdditions/SyncStateFinder.osax");
if (QFile::exists(finderExtension)) {
QString aScript = QString::fromUtf8("tell application \"Finder\"\n"
" try\n"
" «event OWNCload»\n"
" end try\n"
"end tell\n");
QString osascript = "/usr/bin/osascript";
QStringList processArguments;
// processArguments << "-l" << "AppleScript";
QString osascript = "/usr/bin/osascript";
QStringList processArguments;
// processArguments << "-l" << "AppleScript";
QProcess p;
p.start(osascript, processArguments);
p.write(aScript.toUtf8());
p.closeWriteChannel();
p.waitForReadyRead(-1);
QByteArray result = p.readAll();
QString resultAsString(result); // if appropriate
qDebug() << "Laod Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode()
<< (p.exitCode() != 0 ? p.errorString() : QString::null);
} else {
qDebug() << finderExtension << "does not exist! Finder Overlay Plugin loading failed";
QProcess p;
p.start(osascript, processArguments);
p.write(aScript.toUtf8());
p.closeWriteChannel();
p.waitForReadyRead(-1);
QByteArray result = p.readAll();
QString resultAsString(result); // if appropriate
qDebug() << "Laod Finder Overlay-Plugin: " << resultAsString << ": " << p.exitCode()
<< (p.exitCode() != 0 ? p.errorString() : QString::null);
} else {
qDebug() << finderExtension << "does not exist! Finder Overlay Plugin loading failed";
}
}
#endif
}

Просмотреть файл

@ -16,6 +16,7 @@
#include "socketapi.h"
#include "config.h"
#include "configfile.h"
#include "folderman.h"
#include "folder.h"
@ -84,13 +85,10 @@ SocketApi::SocketApi(QObject* parent)
// See issue #2388
// + Theme::instance()->appName();
} else if (Utility::isMac()) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
// Always using Qt5 on OS X
QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
socketPath = runtimeDir + "/SyncStateHelper/" + Theme::instance()->appName() + ".socket";
// We use the generic SyncStateHelper name on OS X since the different branded clients
// should unfortunately not mention that they are ownCloud :-)
#endif
// This must match the code signing Team setting of the extension
// Example for developer builds (with ad-hoc signing identity): "" "com.owncloud.desktopclient" ".socketApi"
// Example for official signed packages: "9B5WD74GWJ." "com.owncloud.desktopclient" ".socketApi"
socketPath = SOCKETAPI_TEAM_IDENTIFIER_PREFIX APPLICATION_REV_DOMAIN ".socketApi";
} else if( Utility::isLinux() || Utility::isBSD() ) {
QString runtimeDir;
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
@ -108,7 +106,7 @@ SocketApi::SocketApi(QObject* parent)
DEBUG << "An unexpected system detected";
}
QLocalServer::removeServer(socketPath);
SocketApiServer::removeServer(socketPath);
QFileInfo info(socketPath);
if (!info.dir().exists()) {
bool result = info.dir().mkpath(".");
@ -167,7 +165,7 @@ void SocketApi::slotReadExcludes()
void SocketApi::slotNewConnection()
{
QLocalSocket* socket = _localServer.nextPendingConnection();
QIODevice* socket = _localServer.nextPendingConnection();
if( ! socket ) {
return;
@ -179,16 +177,6 @@ void SocketApi::slotNewConnection()
_listeners.append(socket);
#ifdef Q_OS_MAC
// We want to tell our location so it can load the icons
// e.g. "/Users/guruz/woboq/owncloud/client/buildmirall/owncloud.app/Contents/MacOS/"
QString iconPath = qApp->applicationDirPath() + "/../Resources/icons/";
if (!QDir(iconPath).exists()) {
DEBUG << "Icon path " << iconPath << " does not exist, did you forget make install?";
}
broadcastMessage(QLatin1String("ICON_PATH"), iconPath );
#endif
foreach( Folder *f, FolderMan::instance()->map() ) {
QString message = buildRegisterPathMessage(f->path());
sendMessage(socket, message);
@ -199,7 +187,7 @@ void SocketApi::onLostConnection()
{
DEBUG << "Lost connection " << sender();
QLocalSocket* socket = qobject_cast<QLocalSocket*>(sender());
QIODevice* socket = qobject_cast<QIODevice*>(sender());
_listeners.removeAll(socket);
socket->deleteLater();
}
@ -207,7 +195,7 @@ void SocketApi::onLostConnection()
void SocketApi::slotReadSocket()
{
QLocalSocket* socket = qobject_cast<QLocalSocket*>(sender());
QIODevice* socket = qobject_cast<QIODevice*>(sender());
Q_ASSERT(socket);
while(socket->canReadLine()) {
@ -215,12 +203,12 @@ void SocketApi::slotReadSocket()
QString command = line.split(":").first();
QString function = QString(QLatin1String("command_")).append(command);
QString functionWithArguments = function + QLatin1String("(QString,QLocalSocket*)");
QString functionWithArguments = function + QLatin1String("(QString,QIODevice*)");
int indexOfMethod = this->metaObject()->indexOfMethod(functionWithArguments.toAscii());
QString argument = line.remove(0, command.length()+1).trimmed();
if(indexOfMethod != -1) {
QMetaObject::invokeMethod(this, function.toAscii(), Q_ARG(QString, argument), Q_ARG(QLocalSocket*, socket));
QMetaObject::invokeMethod(this, function.toAscii(), Q_ARG(QString, argument), Q_ARG(QIODevice*, socket));
} else {
DEBUG << "The command is not supported by this version of the client:" << command << "with argument:" << argument;
}
@ -232,7 +220,7 @@ void SocketApi::slotRegisterPath( const QString& alias )
Folder *f = FolderMan::instance()->folder(alias);
if (f) {
QString message = buildRegisterPathMessage(f->path());
foreach(QLocalSocket *socket, _listeners) {
foreach(QIODevice *socket, _listeners) {
sendMessage(socket, message);
}
}
@ -336,7 +324,7 @@ void SocketApi::slotSyncItemDiscovered(const QString &folder, const SyncFileItem
void SocketApi::sendMessage(QLocalSocket *socket, const QString& message, bool doWait)
void SocketApi::sendMessage(QIODevice *socket, const QString& message, bool doWait)
{
DEBUG << "Sending message: " << message;
QString localMessage = message;
@ -369,14 +357,12 @@ void SocketApi::broadcastMessage( const QString& verb, const QString& path, cons
msg.append(QDir::toNativeSeparators(fi.absoluteFilePath()));
}
// sendMessage already has a debug output
//DEBUG << "Broadcasting to" << _listeners.count() << "listeners: " << msg;
foreach(QLocalSocket *socket, _listeners) {
foreach(QIODevice *socket, _listeners) {
sendMessage(socket, msg, doWait);
}
}
void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSocket* socket)
void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QIODevice* socket)
{
// This command is the same as RETRIEVE_FILE_STATUS
@ -384,7 +370,7 @@ void SocketApi::command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSo
command_RETRIEVE_FILE_STATUS(argument, socket);
}
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSocket* socket)
void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice* socket)
{
if( !socket ) {
qDebug() << "No valid socket object.";
@ -412,7 +398,7 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSock
sendMessage(socket, message);
}
void SocketApi::command_SHARE(const QString& localFile, QLocalSocket* socket)
void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
{
if (!socket) {
qDebug() << Q_FUNC_INFO << "No valid socket object.";
@ -450,12 +436,12 @@ void SocketApi::command_SHARE(const QString& localFile, QLocalSocket* socket)
}
}
void SocketApi::command_VERSION(const QString&, QLocalSocket* socket)
void SocketApi::command_VERSION(const QString&, QIODevice* socket)
{
sendMessage(socket, QLatin1String("VERSION:" MIRALL_VERSION_STRING ":" MIRALL_SOCKET_API_VERSION));
}
void SocketApi::command_SHARE_MENU_TITLE(const QString &, QLocalSocket* socket)
void SocketApi::command_SHARE_MENU_TITLE(const QString &, QIODevice* socket)
{
sendMessage(socket, QLatin1String("SHARE_MENU_TITLE:") + tr("Share with %1", "parameter is ownCloud").arg(Theme::instance()->appNameGUI()));
}

Просмотреть файл

@ -20,17 +20,17 @@ extern "C" {
#include <std/c_string.h>
}
#include <sqlite3.h>
#include <QWeakPointer>
#include <QTcpSocket>
#include <QTcpServer>
#include <QLocalServer>
#include "syncfileitem.h"
#include "syncjournalfilerecord.h"
#include "ownsql.h"
#if defined(Q_OS_MAC)
#include "socketapisocket_mac.h"
#else
#include <QLocalServer>
typedef QLocalServer SocketApiServer;
#endif
class QUrl;
class QLocalSocket;
class QStringList;
@ -74,20 +74,20 @@ private:
SyncJournalFileRecord dbFileRecord_capi( Folder *folder, QString fileName );
SqlQuery *getSqlQuery( Folder *folder );
void sendMessage(QLocalSocket* socket, const QString& message, bool doWait = false);
void sendMessage(QIODevice* socket, const QString& message, bool doWait = false);
void broadcastMessage(const QString& verb, const QString &path, const QString &status = QString::null, bool doWait = false);
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_SHARE(const QString& localFile, QLocalSocket* socket);
Q_INVOKABLE void command_RETRIEVE_FOLDER_STATUS(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_SHARE(const QString& localFile, QIODevice* socket);
Q_INVOKABLE void command_VERSION(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_VERSION(const QString& argument, QIODevice* socket);
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QLocalSocket* socket);
Q_INVOKABLE void command_SHARE_MENU_TITLE(const QString& argument, QIODevice* socket);
QString buildRegisterPathMessage(const QString& path);
QList<QLocalSocket*> _listeners;
QLocalServer _localServer;
QList<QIODevice*> _listeners;
SocketApiServer _localServer;
c_strlist_t *_excludes;
QHash<Folder*, QSharedPointer<SqlQuery>> _dbQueries;
QHash<Folder*, QSharedPointer<SqlDatabase>> _openDbs;

Просмотреть файл

@ -0,0 +1,69 @@
/*
* 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.
*/
#ifndef SOCKETAPISOCKET_OSX_H
#define SOCKETAPISOCKET_OSX_H
#include <QAbstractSocket>
#include <QIODevice>
class SocketApiServerPrivate;
class SocketApiSocketPrivate;
class SocketApiSocket : public QIODevice
{
Q_OBJECT
public:
SocketApiSocket(QObject *parent, SocketApiSocketPrivate *p);
~SocketApiSocket();
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
bool isSequential() const override { return true; }
qint64 bytesAvailable() const override;
bool canReadLine() const override;
signals:
void disconnected();
private:
// Use Qt's p-impl system to hide objective-c types from C++ code including this file
Q_DECLARE_PRIVATE(SocketApiSocket)
QScopedPointer<SocketApiSocketPrivate> d_ptr;
friend class SocketApiServerPrivate;
};
class SocketApiServer : public QObject
{
Q_OBJECT
public:
SocketApiServer();
~SocketApiServer();
void close();
bool listen(const QString &name);
SocketApiSocket *nextPendingConnection();
static bool removeServer(const QString &) { return false; }
signals:
void newConnection();
private:
Q_DECLARE_PRIVATE(SocketApiServer)
QScopedPointer<SocketApiServerPrivate> d_ptr;
};
#endif // SOCKETAPISOCKET_OSX_H

Просмотреть файл

@ -0,0 +1,225 @@
/*
* 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.
*/
#include "socketapisocket_mac.h"
#import <Cocoa/Cocoa.h>
@protocol ChannelProtocol <NSObject>
- (void)sendMessage:(NSData*)msg;
@end
@protocol RemoteEndProtocol <NSObject, ChannelProtocol>
- (void)registerTransmitter:(id)tx;
@end
@interface LocalEnd : NSObject <ChannelProtocol>
@property SocketApiSocketPrivate *wrapper;
- (instancetype)initWithWrapper:(SocketApiSocketPrivate *)wrapper;
@end
@interface Server : NSObject
@property SocketApiServerPrivate *wrapper;
- (instancetype)initWithWrapper:(SocketApiServerPrivate *)wrapper;
- (void)registerClient:(NSDistantObject <RemoteEndProtocol> *)remoteEnd;
@end
class SocketApiSocketPrivate
{
public:
SocketApiSocket *q_ptr;
SocketApiSocketPrivate(NSDistantObject <ChannelProtocol> *remoteEnd);
~SocketApiSocketPrivate();
NSDistantObject <ChannelProtocol> *remoteEnd;
LocalEnd *localEnd;
QByteArray inBuffer;
};
class SocketApiServerPrivate
{
public:
SocketApiServer *q_ptr;
SocketApiServerPrivate();
~SocketApiServerPrivate();
QList<SocketApiSocket*> pendingConnections;
NSConnection *connection;
Server *server;
};
@implementation LocalEnd
- (instancetype)initWithWrapper:(SocketApiSocketPrivate *)wrapper
{
self = [super init];
self->_wrapper = wrapper;
return self;
}
- (void)sendMessage:(NSData*)msg
{
if (_wrapper) {
_wrapper->inBuffer += QByteArray::fromRawNSData(msg);
emit _wrapper->q_ptr->readyRead();
}
}
- (void)connectionDidDie:(NSNotification*)notification
{
#pragma unused(notification)
if (_wrapper)
emit _wrapper->q_ptr->disconnected();
}
@end
@implementation Server
- (instancetype)initWithWrapper:(SocketApiServerPrivate *)wrapper
{
self = [super init];
self->_wrapper = wrapper;
return self;
}
- (void)registerClient:(NSDistantObject <RemoteEndProtocol> *)remoteEnd
{
// This saves a few mach messages that would otherwise be needed to query the interface
[remoteEnd setProtocolForProxy:@protocol(RemoteEndProtocol)];
SocketApiServer *server = _wrapper->q_ptr;
SocketApiSocketPrivate *socketPrivate = new SocketApiSocketPrivate(remoteEnd);
SocketApiSocket *socket = new SocketApiSocket(server, socketPrivate);
_wrapper->pendingConnections.append(socket);
emit server->newConnection();
[remoteEnd registerTransmitter:socketPrivate->localEnd];
}
@end
SocketApiSocket::SocketApiSocket(QObject *parent, SocketApiSocketPrivate *p)
: QIODevice(parent)
, d_ptr(p)
{
Q_D(SocketApiSocket);
d->q_ptr = this;
open(ReadWrite);
}
SocketApiSocket::~SocketApiSocket()
{
}
qint64 SocketApiSocket::readData(char *data, qint64 maxlen)
{
Q_D(SocketApiSocket);
qint64 len = std::min(maxlen, static_cast<qint64>(d->inBuffer.size()));
memcpy(data, d->inBuffer.constData(), len);
d->inBuffer.remove(0, len);
return len;
}
qint64 SocketApiSocket::writeData(const char *data, qint64 len)
{
@try {
Q_D(SocketApiSocket);
// FIXME: The NSConnection will make this block unless the function is marked as "oneway"
// in the protocol. This isn't async and reduces our performances but this currectly avoids
// a Mach queue deadlock during requests bursts of the legacy OwnCloudFinder extension.
// Since FinderSync already runs in a separate process, blocking isn't too critical.
[d->remoteEnd sendMessage:[NSData dataWithBytesNoCopy:const_cast<char *>(data) length:len freeWhenDone:NO]];
return len;
} @catch(NSException* e) {
// connectionDidDie can be notified too late, also interpret any sending exception as a disconnection.
emit disconnected();
return -1;
}
}
qint64 SocketApiSocket::bytesAvailable() const
{
Q_D(const SocketApiSocket);
return d->inBuffer.size() + QIODevice::bytesAvailable();
}
bool SocketApiSocket::canReadLine() const
{
Q_D(const SocketApiSocket);
return d->inBuffer.indexOf('\n', int(pos())) != -1 || QIODevice::canReadLine();
}
SocketApiSocketPrivate::SocketApiSocketPrivate(NSDistantObject <ChannelProtocol> *remoteEnd)
: remoteEnd(remoteEnd)
, localEnd([[LocalEnd alloc] initWithWrapper:this])
{
[remoteEnd retain];
// (Ab)use our objective-c object just to catch the notification
[[NSNotificationCenter defaultCenter] addObserver:localEnd
selector:@selector(connectionDidDie:)
name:NSConnectionDidDieNotification
object:[remoteEnd connectionForProxy]];
}
SocketApiSocketPrivate::~SocketApiSocketPrivate()
{
[remoteEnd release];
// The DO vended localEnd might still be referenced by the connection
localEnd.wrapper = nil;
[localEnd release];
}
SocketApiServer::SocketApiServer()
: d_ptr(new SocketApiServerPrivate)
{
Q_D(SocketApiServer);
d->q_ptr = this;
}
SocketApiServer::~SocketApiServer()
{
}
void SocketApiServer::close()
{
// Assume we'll be destroyed right after
}
bool SocketApiServer::listen(const QString &name)
{
Q_D(SocketApiServer);
// Set the name of the root object
return [d->connection registerName:name.toNSString()];
}
SocketApiSocket *SocketApiServer::nextPendingConnection()
{
Q_D(SocketApiServer);
return d->pendingConnections.takeFirst();
}
SocketApiServerPrivate::SocketApiServerPrivate()
{
// Create the connection and server object to vend over Disributed Objects
connection = [[NSConnection alloc] init];
server = [[Server alloc] initWithWrapper:this];
[connection setRootObject:server];
}
SocketApiServerPrivate::~SocketApiServerPrivate()
{
[connection release];
server.wrapper = nil;
[server release];
}

Просмотреть файл

@ -13,7 +13,6 @@
*/
#include "theme.h"
#include "version.h"
#include "configfile.h"
#include "utility.h"
#include "accessmanager.h"

Просмотреть файл

@ -183,6 +183,7 @@ void Utility::setLaunchOnStartup(const QString &appName, const QString& guiName,
qint64 Utility::freeDiskSpace(const QString &path, bool *ok)
{
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) || defined(Q_OS_FREEBSD_KERNEL) || defined(Q_OS_NETBSD)
Q_UNUSED(ok)
struct statvfs stat;
statvfs(path.toUtf8().data(), &stat);
return (qint64) stat.f_bavail * stat.f_frsize;

Просмотреть файл

@ -69,6 +69,7 @@ bool hasLaunchOnStartup_private(const QString &)
void setLaunchOnStartup_private(const QString &appName, const QString& guiName, bool enable)
{
Q_UNUSED(appName)
Q_UNUSED(guiName)
QString filePath = QDir(QCoreApplication::applicationDirPath()+QLatin1String("/../..")).absolutePath();
CFStringRef folderCFStr = CFStringCreateWithCString(0, filePath.toUtf8().data(), kCFStringEncodingUTF8);

Просмотреть файл

@ -15,6 +15,8 @@
#ifndef VERSION_H
#define VERSION_H
#cmakedefine GIT_SHA1 "@GIT_SHA1@"
#define MIRALL_STRINGIFY(s) MIRALL_TOSTRING(s)
#define MIRALL_TOSTRING(s) #s