Browse Source

CocoaShare Start

master
GRMrGecko 12 years ago
commit
e44743fbae
  1. 10
      .gitignore
  2. 32
      About.rtf
  3. 19
      Classes/CocoaShare/MGMAddons.h
  4. 115
      Classes/CocoaShare/MGMAddons.m
  5. 15
      Classes/CocoaShare/MGMAutoUpdateField.h
  6. 15
      Classes/CocoaShare/MGMAutoUpdateField.m
  7. 116
      Classes/CocoaShare/MGMController.h
  8. 684
      Classes/CocoaShare/MGMController.m
  9. 22
      Classes/CocoaShare/MGMFileManager.h
  10. 73
      Classes/CocoaShare/MGMFileManager.m
  11. 24
      Classes/CocoaShare/MGMLoginItems.h
  12. 89
      Classes/CocoaShare/MGMLoginItems.m
  13. 33
      Classes/CocoaShare/MGMMenuItem.h
  14. 87
      Classes/CocoaShare/MGMMenuItem.m
  15. 33
      Classes/CocoaShare/MGMPathSubscriber.h
  16. 101
      Classes/CocoaShare/MGMPathSubscriber.m
  17. 19
      Classes/CocoaShare/MGMPlugInProtocol.h
  18. 69
      Classes/CocoaShare/MGMWebDav/MGMWebDav.h
  19. 233
      Classes/CocoaShare/MGMWebDav/MGMWebDav.m
  20. 13
      Classes/CocoaShare/MGMWebDav/MGMWebDavAddons.h
  21. 37
      Classes/CocoaShare/MGMWebDav/MGMWebDavAddons.m
  22. 40
      Classes/CocoaShare/MGMWebDav/MGMWebDavDelete.h
  23. 89
      Classes/CocoaShare/MGMWebDav/MGMWebDavDelete.m
  24. 53
      Classes/CocoaShare/MGMWebDav/MGMWebDavGet.h
  25. 135
      Classes/CocoaShare/MGMWebDav/MGMWebDavGet.m
  26. 40
      Classes/CocoaShare/MGMWebDav/MGMWebDavMkCol.h
  27. 89
      Classes/CocoaShare/MGMWebDav/MGMWebDavMkCol.m
  28. 41
      Classes/CocoaShare/MGMWebDav/MGMWebDavOptions.h
  29. 92
      Classes/CocoaShare/MGMWebDav/MGMWebDavOptions.m
  30. 78
      Classes/CocoaShare/MGMWebDav/MGMWebDavPropFind.h
  31. 244
      Classes/CocoaShare/MGMWebDav/MGMWebDavPropFind.m
  32. 45
      Classes/CocoaShare/MGMWebDav/MGMWebDavPut.h
  33. 102
      Classes/CocoaShare/MGMWebDav/MGMWebDavPut.m
  34. 26
      Classes/CocoaShare/Preferences/MGMAccountPane.h
  35. 68
      Classes/CocoaShare/Preferences/MGMAccountPane.m
  36. 46
      Classes/CocoaShare/Preferences/MGMAutoUploadPane.h
  37. 145
      Classes/CocoaShare/Preferences/MGMAutoUploadPane.m
  38. 36
      Classes/CocoaShare/Preferences/MGMEventsPane.h
  39. 150
      Classes/CocoaShare/Preferences/MGMEventsPane.m
  40. 30
      Classes/CocoaShare/Preferences/MGMGeneralPane.h
  41. 81
      Classes/CocoaShare/Preferences/MGMGeneralPane.m
  42. 295
      Classes/CocoaShare/RegexKit/RegexKitLite.h
  43. 2636
      Classes/CocoaShare/RegexKit/RegexKitLite.m
  44. 14
      Classes/CocoaShare/main.m
  45. 7
      Classes/CocoaShare/prefix.pch
  46. 26
      Classes/Dropbox/DropboxSDK/DBAccountInfo.h
  47. 70
      Classes/Dropbox/DropboxSDK/DBAccountInfo.m
  48. 19
      Classes/Dropbox/DropboxSDK/DBError.h
  49. 11
      Classes/Dropbox/DropboxSDK/DBError.m
  50. 38
      Classes/Dropbox/DropboxSDK/DBMetadata.h
  51. 150
      Classes/Dropbox/DropboxSDK/DBMetadata.m
  52. 21
      Classes/Dropbox/DropboxSDK/DBQuota.h
  53. 56
      Classes/Dropbox/DropboxSDK/DBQuota.m
  54. 75
      Classes/Dropbox/DropboxSDK/DBRequest.h
  55. 285
      Classes/Dropbox/DropboxSDK/DBRequest.m
  56. 138
      Classes/Dropbox/DropboxSDK/DBRestClient.h
  57. 846
      Classes/Dropbox/DropboxSDK/DBRestClient.m
  58. 44
      Classes/Dropbox/DropboxSDK/DBSession.h
  59. 123
      Classes/Dropbox/DropboxSDK/DBSession.m
  60. 17
      Classes/Dropbox/DropboxSDK/DropboxSDK.h
  61. 50
      Classes/Dropbox/DropboxSDK/JSON/JSON.h
  62. 68
      Classes/Dropbox/DropboxSDK/JSON/NSObject+SBJSON.h
  63. 53
      Classes/Dropbox/DropboxSDK/JSON/NSObject+SBJSON.m
  64. 58
      Classes/Dropbox/DropboxSDK/JSON/NSString+SBJSON.h
  65. 55
      Classes/Dropbox/DropboxSDK/JSON/NSString+SBJSON.m
  66. 75
      Classes/Dropbox/DropboxSDK/JSON/SBJSON.h
  67. 213
      Classes/Dropbox/DropboxSDK/JSON/SBJSON.m
  68. 87
      Classes/Dropbox/DropboxSDK/JSON/SBJsonBase.h
  69. 84
      Classes/Dropbox/DropboxSDK/JSON/SBJsonBase.m
  70. 87
      Classes/Dropbox/DropboxSDK/JSON/SBJsonParser.h
  71. 475
      Classes/Dropbox/DropboxSDK/JSON/SBJsonParser.m
  72. 131
      Classes/Dropbox/DropboxSDK/JSON/SBJsonWriter.h
  73. 248
      Classes/Dropbox/DropboxSDK/JSON/SBJsonWriter.m
  74. 230
      Classes/Dropbox/DropboxSDK/MPOAuth/Crypto/Base64Transcoder.c
  75. 36
      Classes/Dropbox/DropboxSDK/MPOAuth/Crypto/Base64Transcoder.h
  76. 13
      Classes/Dropbox/DropboxSDK/MPOAuth/MPDebug.h
  77. 20
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuth.h
  78. 94
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAPI.h
  79. 253
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAPI.m
  80. 53
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAPIRequestLoader.h
  81. 231
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAPIRequestLoader.m
  82. 32
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAuthenticationMethod.h
  83. 140
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAuthenticationMethod.m
  84. 50
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAuthenticationMethodOAuth.h
  85. 231
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthAuthenticationMethodOAuth.m
  86. 28
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthConnection.h
  87. 54
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthConnection.m
  88. 90
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthCredentiaIConcreteStore+KeychainAdditionsMac.m
  89. 18
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthCredentialConcreteStore+KeychainAdditions.h
  90. 112
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthCredentialConcreteStore+KeychainAdditionsiPhone.m
  91. 48
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthCredentialConcreteStore.h
  92. 295
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthCredentialConcreteStore.m
  93. 33
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthCredentialStore.h
  94. 29
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthParameterFactory.h
  95. 28
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthSignatureParameter.h
  96. 94
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthSignatureParameter.m
  97. 36
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthURLRequest.h
  98. 119
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthURLRequest.m
  99. 21
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthURLResponse.h
  100. 41
      Classes/Dropbox/DropboxSDK/MPOAuth/MPOAuthURLResponse.m

10
.gitignore

@ -0,0 +1,10 @@
build
*.zip
*.xcodeproj/*.pbxuser
*.xcodeproj/*.mode*
*.xcodeproj/*.perspective*
*.xcodeproj/xcuserdata
*.xcodeproj/project.xcworkspace/xcuserdata
*.xcworkspace/xcuserdata
CocoaShare/*
Screenshots/*

32
About.rtf

@ -0,0 +1,32 @@
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\qc\pardirnatural
\f0\b\fs36 \cf0 By Mr. Gecko
\b0\fs32 \
\fs34 At {\field{\*\fldinst{HYPERLINK "http://mrgeckosmedia.com/"}}{\fldrslt mrgeckosmedia.com}}
\fs32 \
Special Thanks To\
\fs24 MegaEduX ({\field{\*\fldinst{HYPERLINK "http://megaedux.com"}}{\fldrslt megaedux.com}})\
PowerOfCheese ({\field{\*\fldinst{HYPERLINK "http://xtrememachinez.com"}}{\fldrslt xtrememachinez.com}})\
\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural
\cf0 CocoaShare Uses {\field{\*\fldinst{HYPERLINK "http://sparkle.andymatuschak.org"}}{\fldrslt Sparkle}} for software update, {\field{\*\fldinst{HYPERLINK "http://growl.info/"}}{\fldrslt Growl}} for notifications, {\field{\*\fldinst{HYPERLINK "http://regexkit.sourceforge.net/"}}{\fldrslt RegexKit Lite}} as a {\field{\*\fldinst{HYPERLINK "http://site.icu-project.org/"}}{\fldrslt ICU}} regular expression wrapper, and {\field{\*\fldinst{HYPERLINK "https://www.dropbox.com/developers"}}{\fldrslt Dropbox API}} for {\field{\*\fldinst{HYPERLINK "https://www.dropbox.com/"}}{\fldrslt Dropbox}} support.\
\
CocoaShare makes it easy for you to share files with friends using multiple services and multiple ways. With filters you can have CocoaShare find files that matches the regular expression and automatically upload them. The screenshot filter will automatically upload any screenshot taken using Mac OS X's built screenshot system. Dragging files to the dock or menu bar icon will upload them at your request. After a file is uploaded, it places the URL in your clipboard so you can easily paste it into a message for your friends. Events allows you to set options for when a file is being uploaded and when a file is uploaded, such as displaying a growl notification or playing a sound to let you know when it's uploaded. By using CocoaShare, you'll find how easy it is to share files.\
\
Services Included:\
{\field{\*\fldinst{HYPERLINK "http://tinygrab.com/"}}{\fldrslt TinyGrab}}\
{\field{\*\fldinst{HYPERLINK "https://www.dropbox.com/"}}{\fldrslt Dropbox}}\
FTP - File Transfer Protocol.\
HTTP - Hypertext Transport Protocol (Using a custom PHP script).\
{\field{\*\fldinst{HYPERLINK "https://www.me.com/"}}{\fldrslt MobileMe}}\
SFTP - File Transfer over Secure Shell.\
{\field{\*\fldinst{HYPERLINK "https://twitpic.com/"}}{\fldrslt twitpic}}\
WebDav - Web-based Distributed Authoring and Versioning.\
\
CocoaShare is open source at {\field{\*\fldinst{HYPERLINK "http://opensource.mrgeckosmedia.com/"}}{\fldrslt http://opensource.mrgeckosmedia.com/}}.}

19
Classes/CocoaShare/MGMAddons.h

@ -0,0 +1,19 @@
//
// MGMAddons.h
// CocoaShare
//
// Created by James on 1/22/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Cocoa/Cocoa.h>
@interface NSString (MGMAddons)
- (NSString *)replace:(NSString *)targetString with:(NSString *)replaceString;
- (NSString *)escapePath;
@end
@interface NSBezierPath (MGMAddons)
+ (NSBezierPath *)pathWithRect:(NSRect)theRect radiusX:(float)theRadiusX radiusY:(float)theRadiusY;
- (void)fillGradientFrom:(NSColor *)theStartColor to:(NSColor *)theEndColor;
@end

115
Classes/CocoaShare/MGMAddons.m

@ -0,0 +1,115 @@
//
// MGMAddons.m
// CocoaShare
//
// Created by James on 1/22/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import "MGMAddons.h"
#import <QuartzCore/QuartzCore.h>
@implementation NSString (MGMAddons)
- (NSString *)replace:(NSString *)targetString with:(NSString *)replaceString {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSMutableString *temp = [NSMutableString new];
NSRange replaceRange = NSMakeRange(0, [self length]);
NSRange rangeInOriginalString = replaceRange;
int replaced = 0;
while (1) {
NSRange rangeToCopy;
NSRange foundRange = [self rangeOfString:targetString options:0 range:rangeInOriginalString];
if (foundRange.length == 0) break;
rangeToCopy = NSMakeRange(rangeInOriginalString.location, foundRange.location - rangeInOriginalString.location);
[temp appendString:[self substringWithRange:rangeToCopy]];
[temp appendString:replaceString];
rangeInOriginalString.length -= NSMaxRange(foundRange) -
rangeInOriginalString.location;
rangeInOriginalString.location = NSMaxRange(foundRange);
replaced++;
if (replaced % 100 == 0) {
[pool drain];
pool = [NSAutoreleasePool new];
}
}
if (rangeInOriginalString.length > 0) [temp appendString:[self substringWithRange:rangeInOriginalString]];
[pool drain];
return [temp autorelease];
}
- (NSString *)escapePath {
NSString *escapedPath = [self replace:@" " with:@"\\ "];
escapedPath = [escapedPath replace:@"\"" with:@"\\\""];
escapedPath = [escapedPath replace:@"'" with:@"\\'"];
return escapedPath;
}
@end
@implementation NSBezierPath (MGMAddons)
+ (NSBezierPath *)pathWithRect:(NSRect)theRect radiusX:(float)theRadiusX radiusY:(float)theRadiusY {
NSBezierPath *path = [NSBezierPath bezierPath];
float maxRadiusX = theRect.size.width / 2.0;
float maxRadiusY = theRect.size.height / 2.0;
theRadiusX = (theRadiusX<maxRadiusX ? theRadiusX : maxRadiusX);
theRadiusY = (theRadiusY<maxRadiusY ? theRadiusY : maxRadiusY);
float ellipse = 0.55228474983079;
float controlX = theRadiusX * ellipse;
float controlY = theRadiusY * ellipse;
NSRect edges = NSInsetRect(theRect, theRadiusX, theRadiusY);
[path moveToPoint:NSMakePoint(edges.origin.x, theRect.origin.y)];
// top right corner
[path lineToPoint:NSMakePoint(NSMaxX(edges), theRect.origin.y)];
[path curveToPoint:NSMakePoint(NSMaxX(theRect), edges.origin.y) controlPoint1:NSMakePoint(NSMaxX(edges) + controlX, theRect.origin.y) controlPoint2:NSMakePoint(NSMaxX(theRect), edges.origin.y - controlY)];
// bottom right corner
[path lineToPoint:NSMakePoint(NSMaxX(theRect), NSMaxY(edges))];
[path curveToPoint:NSMakePoint(NSMaxX(edges), NSMaxY(theRect)) controlPoint1:NSMakePoint(NSMaxX(theRect), NSMaxY(edges) + controlY) controlPoint2:NSMakePoint(NSMaxX(edges) + controlX, NSMaxY(theRect))];
// bottom left corner
[path lineToPoint:NSMakePoint(edges.origin.x, NSMaxY(theRect))];
[path curveToPoint:NSMakePoint(theRect.origin.x, NSMaxY(edges)) controlPoint1:NSMakePoint(edges.origin.x - controlX, NSMaxY(theRect)) controlPoint2:NSMakePoint(theRect.origin.x, NSMaxY(edges) + controlY)];
// top left corner
[path lineToPoint:NSMakePoint(theRect.origin.x, edges.origin.y)];
[path curveToPoint:NSMakePoint(edges.origin.x, theRect.origin.y) controlPoint1:NSMakePoint(theRect.origin.x, edges.origin.y - controlY) controlPoint2:NSMakePoint(edges.origin.x - controlX, theRect.origin.y)];
[path closePath];
return path;
}
- (void)fillGradientFrom:(NSColor *)theStartColor to:(NSColor *)theEndColor {
CIFilter *filter = [CIFilter filterWithName:@"CILinearGradient"];
theStartColor = [theStartColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
theEndColor = [theEndColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
if (![[NSGraphicsContext currentContext] isFlipped]) {
NSColor *start = theStartColor;
NSColor *end = theEndColor;
theEndColor = start;
theStartColor = end;
}
CIColor *startColor = [CIColor colorWithRed:[theStartColor redComponent] green:[theStartColor greenComponent] blue:[theStartColor blueComponent] alpha:[theStartColor alphaComponent]];
CIColor *endColor = [CIColor colorWithRed:[theEndColor redComponent] green:[theEndColor greenComponent] blue:[theEndColor blueComponent] alpha:[theEndColor alphaComponent]];
[filter setValue:startColor forKey:@"inputColor0"];
[filter setValue:endColor forKey:@"inputColor1"];
CIVector *startVector = [CIVector vectorWithX:0.0 Y:0.0];
[filter setValue:startVector forKey:@"inputPoint0"];
CIVector *endVector = [CIVector vectorWithX:0.0 Y:[self bounds].size.height];
[filter setValue:endVector forKey:@"inputPoint1"];
CIImage *coreimage = [filter valueForKey:@"outputImage"];
[[NSGraphicsContext currentContext] saveGraphicsState];
[self setClip];
CIContext *context = [[NSGraphicsContext currentContext] CIContext];
[context drawImage:coreimage atPoint:CGPointMake([self bounds].origin.x, [self bounds].origin.y) fromRect:CGRectMake(0.0, 0.0, [self bounds].size.width, [self bounds].size.height)];
[[NSGraphicsContext currentContext] restoreGraphicsState];
}
@end

15
Classes/CocoaShare/MGMAutoUpdateField.h

@ -0,0 +1,15 @@
//
// MGMAutoUpdateField.h
// CocoaShare
//
// Created by James on 1/17/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Cocoa/Cocoa.h>
@interface MGMAutoUpdateField : NSTextField {
}
@end

15
Classes/CocoaShare/MGMAutoUpdateField.m

@ -0,0 +1,15 @@
//
// MGMAutoUpdateField.m
// CocoaShare
//
// Created by James on 1/17/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import "MGMAutoUpdateField.h"
@implementation MGMAutoUpdateField
- (void)keyUp:(NSEvent *)theEvent {
[self sendAction:[self action] to:[self target]];
}
@end

116
Classes/CocoaShare/MGMController.h

@ -0,0 +1,116 @@
//
// CocoaShareAppDelegate.h
// CocoaShare
//
// Created by Mr. Gecko on 1/15/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Cocoa/Cocoa.h>
#import "MGMPlugInProtocol.h"
extern NSString * const MGMDisplay;
extern NSString * const MGMStartup;
extern NSString * const MGMUploadName;
extern NSString * const MGMHistoryCount;
extern NSString * const MGMGrowlErrors;
extern NSString * const MGMESound;
extern NSString * const MGMEPath;
extern NSString * const MGMEDelete;
extern NSString * const MGMEGrowl;
extern const int MGMEUploadingAutomatic;
extern const int MGMEUploadedAutomatic;
extern const int MGMEUploading;
extern const int MGMEUploaded;
extern NSString * const MGMEventNotification;
extern NSString * const MGMEvent;
extern NSString * const MGMEventPath;
extern NSString * const MGMEventURL;
extern NSString * const MGMFiltersPlist;
extern NSString * const MGMFPath;
extern NSString * const MGMFFilter;
@class MGMURLConnectionManager, MGMPreferences, MGMAbout, MGMMenuItem, MGMPathSubscriber;
@interface MGMController : NSObject {
MGMURLConnectionManager *connectionManager;
MGMPreferences *preferences;
MGMAbout *about;
ProcessSerialNumber lastFrontProcess;
IBOutlet NSMenu *mainMenu;
IBOutlet NSMenuItem *disableFilters;
MGMMenuItem *menuItem;
NSStatusItem *statusItem;
NSMutableArray *history;
NSMutableArray *filters;
NSLock *saveLock;
int saveCount;
MGMPathSubscriber *filterWatcher;
BOOL filtersEnabled;
NSMutableArray *accountPlugIns;
NSMutableArray *plugIns;
id<MGMPlugInProtocol> currentPlugIn;
int currentPlugInIndex;
NSMutableArray *uploads;
}
+ (id)sharedController;
- (void)registerDefaults;
- (MGMURLConnectionManager *)connectionManager;
- (MGMPreferences *)preferences;
- (void)loadPlugIns;
- (NSArray *)accountPlugIns;
- (NSArray *)plugIns;
- (void)setCurrentPlugIn:(id)thePlugIn;
- (id<MGMPlugInProtocol>)currentPlugIn;
- (int)currentPlugInIndex;
- (void)becomeFront:(NSWindow *)theWindow;
- (void)resignFront;
- (void)addMenu;
- (void)removeMenu;
- (void)setDockHidden:(BOOL)isHidden;
- (NSMutableArray *)history;
- (void)updateMenu;
- (void)addURLToHistory:(NSURL *)theURL;
- (IBAction)uploadFile:(id)sender;
- (IBAction)disableFilters:(id)sender;
- (IBAction)about:(id)sender;
- (IBAction)preferences:(id)sender;
- (IBAction)donate:(id)sender;
- (IBAction)quit:(id)sender;
- (NSMutableArray *)filters;
- (void)saveFilters;
- (MGMPathSubscriber *)filterWatcher;
- (NSArray *)filtersForPath:(NSString *)thePath;
- (void)updateFilterWatcher;
- (void)subscribedPathChanged:(NSString *)thePath;
- (void)removePassword;
- (void)setPassword:(NSString *)thePassword;
- (NSString *)password;
- (void)processEvent:(int)theEvent path:(NSString *)thePath;
- (void)processEvent:(int)theEvent path:(NSString *)thePath url:(NSURL *)theURL;
- (NSMutableArray *)uploads;
- (NSDictionary *)uploadForPath:(NSString *)thePath;
- (void)addPathToUploads:(NSString *)thePath isAutomatic:(BOOL)isAutomatic;
- (void)processNextUpload;
- (void)upload:(NSString *)thePath receivedError:(NSError *)theError;
- (void)uploadFinished:(NSString *)thePath url:(NSURL *)theURL;
@end

684
Classes/CocoaShare/MGMController.m

@ -0,0 +1,684 @@
//
// MGMController.m
// CocoaShare
//
// Created by Mr. Gecko on 1/15/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import "MGMController.h"
#import "MGMFileManager.h"
#import "MGMPathSubscriber.h"
#import "MGMLoginItems.h"
#import "MGMMenuItem.h"
#import "RegexKitLite.h"
#import <MGMUsers/MGMUsers.h>
#import <GeckoReporter/GeckoReporter.h>
#import <Growl/GrowlApplicationBridge.h>
NSString * const MGMCopyright = @"Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/";
NSString * const MGMVersion = @"MGMVersion";
NSString * const MGMLaunchCount = @"MGMLaunchCount";
NSString * const MGMDisplay = @"MGMDisplay";
NSString * const MGMStartup = @"MGMStartup";
NSString * const MGMUploadName = @"MGMUploadName";
NSString * const MGMHistoryCount = @"MGMHistoryCount";
NSString * const MGMGrowlErrors = @"MGMGrowlErrors";
NSString * const MGMHistoryPlist = @"history.plist";
NSString * const MGMHURL = @"url";
NSString * const MGMHDate = @"date";
NSString * const MGMESound = @"MGME%dSound";
NSString * const MGMEPath = @"MGME%dPath";
NSString * const MGMEDelete = @"MGME%dDelete";
NSString * const MGMEGrowl = @"MGME%dGrowl";
const int MGMEUploadingAutomatic = 0;
const int MGMEUploadedAutomatic = 1;
const int MGMEUploading = 2;
const int MGMEUploaded = 3;
NSString * const MGMEventNotification = @"MGMEventNotification";
NSString * const MGMEvent = @"event";
NSString * const MGMEventPath = @"path";
NSString * const MGMEventURL = @"URL";
NSString * const MGMFiltersPlist = @"filters.plist";
NSString * const MGMFPath = @"path";
NSString * const MGMFFilter = @"filter";
NSString * const MGMPluginFolder = @"PlugIns";
NSString * const MGMCurrentPlugIn = @"MGMCurrentPlugIn";
NSString * const MGMKCType = @"application password";
NSString * const MGMKCName = @"CocoaShare";
NSString * const MGMUPath = @"path";
NSString * const MGMUAutomatic = @"automatic";
NSString * const MGMNSStringPboardType = @"NSStringPboardType";
NSString * const MGMNSPasteboardTypeString = @"public.utf8-plain-text";
static MGMController *MGMSharedController;
@implementation MGMController
+ (id)sharedController {
if (MGMSharedController==nil) {
MGMSharedController = [MGMController new];
}
return MGMSharedController;
}
- (id)init {
if (MGMSharedController!=nil) {
if (self = [super init])
[self release];
self = MGMSharedController;
} else if (self = [super init]) {
MGMSharedController = self;
}
return self;
}
- (void)awakeFromNib {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setup) name:MGMGRDoneNotification object:nil];
[MGMReporter sharedReporter];
}
- (void)setup {
[GrowlApplicationBridge setGrowlDelegate:nil];
connectionManager = [[MGMURLConnectionManager managerWithCookieStorage:[MGMUser cookieStorage]] retain];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[self registerDefaults];
if ([defaults integerForKey:MGMLaunchCount]!=5) {
[defaults setInteger:[defaults integerForKey:MGMLaunchCount]+1 forKey:MGMLaunchCount];
if ([defaults integerForKey:MGMLaunchCount]==5) {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Donations"];
[alert setInformativeText:@"Thank you for using CocoaShare. CocoaShare is donation supported software. If you like using it, please consider giving a donation to help with development."];
[alert addButtonWithTitle:@"Yes"];
[alert addButtonWithTitle:@"No"];
int result = [alert runModal];
if (result==1000)
[self donate:self];
}
}
if ([defaults boolForKey:MGMStartup])
[[MGMLoginItems items] addSelf];
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMHistoryPlist]]) {
history = [[NSMutableArray arrayWithContentsOfFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMHistoryPlist]] retain];
[self updateMenu];
} else {
history = [NSMutableArray new];
[history writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMHistoryPlist] atomically:YES];
[self updateMenu];
}
saveLock = [NSLock new];
filterWatcher = [MGMPathSubscriber sharedPathSubscriber];
[filterWatcher setDelegate:self];
if ([manager fileExistsAtPath:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMFiltersPlist]]) {
filters = [[NSMutableArray arrayWithContentsOfFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMFiltersPlist]] retain];
[self updateFilterWatcher];
} else {
filters = [NSMutableArray new];
[self saveFilters];
}
filtersEnabled = YES;
if ([defaults integerForKey:MGMDisplay]>0)
[self addMenu];
preferences = [MGMPreferences new];
[preferences addPreferencesPaneClassName:@"MGMGeneralPane"];
[preferences addPreferencesPaneClassName:@"MGMAccountPane"];
[preferences addPreferencesPaneClassName:@"MGMAutoUploadPane"];
[preferences addPreferencesPaneClassName:@"MGMEventsPane"];
if ([defaults integerForKey:MGMLaunchCount]==2)
[preferences showPreferences];
about = [MGMAbout new];
uploads = [NSMutableArray new];
[self loadPlugIns];
}
- (void)dealloc {
[connectionManager release];
[preferences release];
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem];
[statusItem release];
[menuItem release];
[history release];
[filters release];
[saveLock release];
[filterWatcher release];
[accountPlugIns release];
[plugIns release];
[uploads release];
[super dealloc];
}
- (void)registerDefaults {
NSMutableDictionary *defaults = [NSMutableDictionary dictionary];
[defaults setObject:[[MGMSystemInfo info] applicationVersion] forKey:MGMVersion];
[defaults setObject:[NSNumber numberWithInt:1] forKey:MGMLaunchCount];
[defaults setObject:[NSNumber numberWithInt:([[MGMSystemInfo info] isUIElement] ? 2 : 0)] forKey:MGMDisplay];
[defaults setObject:[NSNumber numberWithBool:[[MGMLoginItems items] selfExists]] forKey:MGMStartup];
[defaults setObject:[NSNumber numberWithInt:0] forKey:MGMUploadName];
[defaults setObject:[NSNumber numberWithInt:5] forKey:MGMHistoryCount];
[defaults setObject:[NSNumber numberWithInt:2] forKey:[NSString stringWithFormat:MGMEDelete, MGMEUploadedAutomatic]];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
}
- (MGMURLConnectionManager *)connectionManager {
return connectionManager;
}
- (MGMPreferences *)preferences {
return preferences;
}
- (void)loadPlugIns {
NSFileManager *manager = [NSFileManager defaultManager];
[accountPlugIns release];
accountPlugIns = [NSMutableArray new];
[plugIns release];
plugIns = [NSMutableArray new];
NSArray *checkPaths = [NSArray arrayWithObjects:[[NSBundle mainBundle] builtInPlugInsPath], [[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPluginFolder], nil];
for (int i=0; i<[checkPaths count]; i++) {
NSArray *plugInsFolder = [manager contentsOfDirectoryAtPath:[checkPaths objectAtIndex:i]];
for (int p=0; p<[plugInsFolder count]; p++) {
NSString *path = [[[checkPaths objectAtIndex:i] stringByAppendingPathComponent:[plugInsFolder objectAtIndex:p]] stringByResolvingSymlinksInPath];
NSBundle *bundle = [NSBundle bundleWithPath:path];
if (bundle!=nil) {
Class plugInClass = [bundle principalClass];
id<MGMPlugInProtocol> plugIn = [[[plugInClass alloc] init] autorelease];
if (plugIn!=nil && [plugIn respondsToSelector:@selector(isAccountPlugIn)] && [plugIn isAccountPlugIn])
[accountPlugIns addObject:plugIn];
else if (plugIn!=nil)
[plugIns addObject:plugIn];
}
}
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *currentPlugInName = [defaults objectForKey:MGMCurrentPlugIn];
BOOL foundCurrentPlugIn = NO;
for (int i=0; i<[accountPlugIns count]; i++) {
if ([NSStringFromClass([[accountPlugIns objectAtIndex:i] class]) isEqual:currentPlugInName]) {
currentPlugIn = [accountPlugIns objectAtIndex:i];
currentPlugInIndex = i;
if ([currentPlugIn respondsToSelector:@selector(setCurrentPlugIn:)]) [currentPlugIn setCurrentPlugIn:YES];
foundCurrentPlugIn = YES;
break;
}
}
if (!foundCurrentPlugIn && [accountPlugIns count]>0)
[self setCurrentPlugIn:[accountPlugIns objectAtIndex:0]];
}
- (NSArray *)accountPlugIns {
return accountPlugIns;
}
- (NSArray *)plugIns {
return plugIns;
}
- (void)setCurrentPlugIn:(id)thePlugIn {
int plugInIndex = [accountPlugIns indexOfObject:thePlugIn];
if (plugInIndex>=0) {
[self removePassword];
if ([currentPlugIn respondsToSelector:@selector(setCurrentPlugIn:)]) [currentPlugIn setCurrentPlugIn:NO];
currentPlugIn = thePlugIn;
currentPlugInIndex = plugInIndex;
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass([currentPlugIn class]) forKey:MGMCurrentPlugIn];
if ([currentPlugIn respondsToSelector:@selector(setCurrentPlugIn:)]) [currentPlugIn setCurrentPlugIn:YES];
}
}
- (id<MGMPlugInProtocol>)currentPlugIn {
return currentPlugIn;
}
- (int)currentPlugInIndex {
return currentPlugInIndex;
}
- (void)becomeFront:(NSWindow *)theWindow {
GetFrontProcess(&lastFrontProcess);
if (theWindow!=nil) {
if ([[MGMSystemInfo info] isUIElement])
[theWindow setLevel:NSFloatingWindowLevel];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:theWindow];
}
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
- (void)resignFront {
SetFrontProcess(&lastFrontProcess);
}
- (void)windowWillClose:(NSNotification *)notification {
[[NSNotificationCenter defaultCenter] removeObserver:self name:[notification name] object:[notification object]];
[self resignFront];
}
- (void)addMenu {
if (statusItem==nil) {
menuItem = [[MGMMenuItem alloc] initWithFrame:NSZeroRect];
[menuItem setDelegate:self];
[menuItem setImage:[NSImage imageNamed:@"menuicon"]];
[menuItem setAlternateImage:[NSImage imageNamed:@"menuiconselected"]];
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setView:menuItem];
[statusItem setToolTip:@"CocoaShare"];
}
}
- (void)removeMenu {
if (statusItem!=nil) {
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem];
[statusItem release];
statusItem = nil;
[menuItem release];
menuItem = nil;
}
}
- (void)setDockHidden:(BOOL)isHidden {
NSFileManager *manager = [NSFileManager defaultManager];
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [[bundle bundlePath] stringByAppendingPathComponent:@"Contents/Info.plist"];
if ([manager isWritableFileAtPath:path]) {
NSMutableDictionary *infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
[infoDict setObject:[NSNumber numberWithBool:isHidden] forKey:@"LSUIElement"];
[infoDict writeToFile:path atomically:NO];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate];
[manager setAttributes:attributes ofItemAtPath:[bundle bundlePath]];
if (isHidden) {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Restart Required"];
[alert setInformativeText:@"Inorder to hide the dock, you must restart CocoaShare. Do you want to restart CocoaShare now?"];
[alert addButtonWithTitle:@"Yes"];
[alert addButtonWithTitle:@"No"];
int result = [alert runModal];
if (result==1000) {
//Took from Sparkle.
NSString *pathToRelaunch = [[NSBundle mainBundle] bundlePath];
NSString *relaunchPath = [[[NSBundle bundleWithIdentifier:@"org.andymatuschak.Sparkle"] resourcePath] stringByAppendingPathComponent:@"relaunch"];
[NSTask launchedTaskWithLaunchPath:relaunchPath arguments:[NSArray arrayWithObjects:pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], nil]];
[[NSApplication sharedApplication] terminate:self];
}
}
} else {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Unable to change dock"];
[alert setInformativeText:[NSString stringWithFormat:@"CocoaShare is unable to %@ the dock due to permissions. To fix this issue, right click on CocoaShare and choose Get Info to make CocoaShare writable.", (isHidden ? @"hide" : @"unhide")]];
[alert runModal];
}
if (!isHidden) {
ProcessSerialNumber psn = {0, kCurrentProcess};
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
[self resignFront];
[self performSelector:@selector(becomeFront:) withObject:[preferences preferencesWindow] afterDelay:0.0];
}
}
- (void)menuClicked:(id)sender {
[statusItem popUpStatusItemMenu:mainMenu];
}
- (void)menuDraggingEntered:(id)sender {
[menuItem setImage:[NSImage imageNamed:@"menuicondrag"]];
}
- (void)menuDraggingExited:(id)sender {
[menuItem setImage:[NSImage imageNamed:@"menuicon"]];
}
- (void)menu:(id)sender droppedFiles:(NSArray *)files {
NSFileManager *manager = [NSFileManager defaultManager];
for (int i=0; i<[files count]; i++) {
BOOL directory = NO;
if ([manager fileExistsAtPath:[files objectAtIndex:i] isDirectory:&directory]) {
if (directory) {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Upload Error"];
[alert setInformativeText:@"Uploading of directories is impossible."];
[alert runModal];
continue;
}
[self addPathToUploads:[files objectAtIndex:i] isAutomatic:NO];
}
}
}
- (NSMutableArray *)history {
return history;
}
- (void)updateMenu {
int splitterIndex = 0;
for (int i=0; i<[mainMenu numberOfItems]; i++) {
if ([[mainMenu itemAtIndex:i] isSeparatorItem]) {
splitterIndex = i;
break;
}
[mainMenu removeItemAtIndex:i];
i--;
}
if ([history count]>0) {
for (int i=0; i<[history count]; i++) {
NSDictionary *historyItem = [history objectAtIndex:i];
NSMenuItem *item = [[NSMenuItem new] autorelease];
NSDateFormatter *formatter = [[NSDateFormatter new] autorelease];
[formatter setDateFormat:@"MMMM d, yyyy h:mm:ss a"];
[item setTitle:[formatter stringFromDate:[historyItem objectForKey:MGMHDate]]];
[item setRepresentedObject:[historyItem objectForKey:MGMHURL]];
[item setTarget:self];
[item setAction:@selector(copyHistoryItem:)];
[mainMenu insertItem:item atIndex:splitterIndex];
}
} else {
NSMenuItem *item = [[NSMenuItem new] autorelease];
[item setTitle:@"No Upload History"];
[item setEnabled:NO];
[mainMenu insertItem:item atIndex:splitterIndex];
}
}
- (IBAction)copyHistoryItem:(id)sender {
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
[pboard declareTypes:[NSArray arrayWithObjects:MGMNSStringPboardType, MGMNSPasteboardTypeString, nil] owner:nil];
[pboard setString:[sender representedObject] forType:MGMNSStringPboardType];
[pboard setString:[sender representedObject] forType:MGMNSPasteboardTypeString];
}
- (void)addURLToHistory:(NSURL *)theURL {
[history addObject:[NSDictionary dictionaryWithObjectsAndKeys:[theURL absoluteString], MGMHURL, [NSDate date], MGMHDate, nil]];
int maxHistoryItems = [[NSUserDefaults standardUserDefaults] integerForKey:MGMHistoryCount];
int itemsToDelete = [history count]-maxHistoryItems;
if (itemsToDelete>0) {
for (int i=0; i<itemsToDelete; i++) {
[history removeObjectAtIndex:0];
}
}
[history writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMHistoryPlist] atomically:YES];
[self updateMenu];
}
- (IBAction)uploadFile:(id)sender {
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setResolvesAliases:YES];
[panel setAllowsMultipleSelection:YES];
[panel setTitle:@"Choose File(s)"];
[panel setPrompt:@"Choose"];
[self becomeFront:nil];
int returnCode = [panel runModal];
if (returnCode==NSOKButton) {
for (int i=0; i<[[panel URLs] count]; i++) {
[self addPathToUploads:[[[panel URLs] objectAtIndex:i] path] isAutomatic:NO];
}
}
[self resignFront];
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag {
if (!flag)
[self preferences:self];
return YES;
}
- (void)application:(NSApplication *)theApplication openFiles:(NSArray *)theFiles {
for (int i=0; i<[theFiles count]; i++) {
[self addPathToUploads:[theFiles objectAtIndex:i] isAutomatic:NO];
}
}
- (IBAction)disableFilters:(id)sender {
filtersEnabled = !filtersEnabled;
[disableFilters setTitle:(filtersEnabled ? @"Disable Auto Upload" : @"Enable Auto Upload")];
}
- (IBAction)about:(id)sender {
[about show];
[self becomeFront:[about window]];
}
- (IBAction)preferences:(id)sender {
[preferences showPreferences];
[self becomeFront:[preferences preferencesWindow]];
}
- (IBAction)donate:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=U9LTDN57NPZ44"]];
}
- (IBAction)quit:(id)sender {
[[MGMLoginItems items] removeSelf];
[[NSApplication sharedApplication] terminate:self];
}
- (NSMutableArray *)filters {
return filters;
}
- (void)saveFilters {
if (saveCount==2)
return;
saveCount++;
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[saveLock lock];
[filters writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMFiltersPlist] atomically:YES];
[self updateFilterWatcher];
saveCount--;
[pool drain];
[saveLock unlock];
}
- (MGMPathSubscriber *)filterWatcher {
return filterWatcher;
}
- (NSArray *)filtersForPath:(NSString *)thePath {
NSMutableArray *filtersFound = [NSMutableArray array];
for (int i=0; i<[filters count]; i++) {
NSString *path = [[[filters objectAtIndex:i] objectForKey:MGMFPath] stringByExpandingTildeInPath];
if ([path isEqual:thePath])
[filtersFound addObject:[filters objectAtIndex:i]];
}
return filtersFound;
}
- (void)updateFilterWatcher {
[filterWatcher removeAllPaths];
for (int i=0; i<[filters count]; i++) {
NSDictionary *filter = [filters objectAtIndex:i];
if (![[filter objectForKey:MGMFFilter] isEqual:@""]) {
NSString *path = [[filter objectForKey:MGMFPath] stringByExpandingTildeInPath];
if (![path isEqual:@""])
[filterWatcher addPath:path];
}
}
}
- (void)subscribedPathChanged:(NSString *)thePath {
if (filtersEnabled) {
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *filtersFound = [self filtersForPath:thePath];
NSArray *files = [manager contentsOfDirectoryAtPath:thePath];
for (int i=0; i<[files count]; i++) {
NSString *file = [files objectAtIndex:i];
NSString *fullPath = [thePath stringByAppendingPathComponent:file];
BOOL directory = NO;
if ([manager fileExistsAtPath:fullPath isDirectory:&directory] && !directory) {
for (int f=0; f<[filtersFound count]; f++) {
if ([file isMatchedByRegex:[[filtersFound objectAtIndex:f] objectForKey:MGMFFilter]])
[self addPathToUploads:fullPath isAutomatic:YES];
}
}
}
}
}
- (void)removePassword {
NSArray *items = [MGMKeychain items:MGMKCType withName:MGMKCName service:MGMKCName account:MGMKCName];
if ([items count]>0)
[[items objectAtIndex:0] remove];
}
- (void)setPassword:(NSString *)thePassword {
NSArray *items = [MGMKeychain items:MGMKCType withName:MGMKCName service:MGMKCName account:MGMKCName];
if ([items count]>0) {
[[items objectAtIndex:0] setString:thePassword];
} else {
[MGMKeychain addItem:MGMKCType withName:MGMKCName service:MGMKCName account:MGMKCName password:thePassword];
}
}
- (NSString *)password {
NSArray *items = [MGMKeychain items:MGMKCType withName:MGMKCName service:MGMKCName account:MGMKCName];
if ([items count]>0)
return [[items objectAtIndex:0] string];
return nil;
}
- (void)processEvent:(int)theEvent path:(NSString *)thePath {
[self processEvent:theEvent path:thePath url:nil];
}
- (void)processEvent:(int)theEvent path:(NSString *)thePath url:(NSURL *)theURL {
NSMutableDictionary *eventInfo = [NSMutableDictionary dictionary];
[eventInfo setObject:[NSNumber numberWithInt:theEvent] forKey:MGMEvent];
[eventInfo setObject:thePath forKey:MGMEventPath];
if (theURL!=nil)
[eventInfo setObject:theURL forKey:MGMEventURL];
[[NSNotificationCenter defaultCenter] postNotificationName:MGMEventNotification object:self userInfo:eventInfo];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSFileManager *manager = [NSFileManager defaultManager];
NSString *soundPath = [defaults objectForKey:[NSString stringWithFormat:MGMESound, theEvent]];
if (soundPath!=nil && [manager fileExistsAtPath:soundPath]) {
NSSound *sound = [[NSSound alloc] initWithContentsOfFile:soundPath byReference:YES];
[sound setDelegate:self];
[sound play];
}
NSString *path = [[defaults objectForKey:[NSString stringWithFormat:MGMEPath, theEvent]] stringByExpandingTildeInPath];
if ([manager fileExistsAtPath:path])
[manager moveItemAtPath:thePath toPath:path];
int deleteFile = [[defaults objectForKey:[NSString stringWithFormat:MGMEDelete, theEvent]] intValue];
if (deleteFile!=0 && [manager fileExistsAtPath:thePath]) {
if (deleteFile==1) {
[manager removeItemAtPath:thePath];
} else if (deleteFile==2) {
NSString *trash = [@"~/.Trash" stringByExpandingTildeInPath];
NSInteger tag;
[[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:[thePath stringByDeletingLastPathComponent] destination:trash files:[NSArray arrayWithObject:[thePath lastPathComponent]] tag:&tag];
if (tag!=0)
NSLog(@"Error Deleting: %d", tag);
}
}
BOOL growl = [[defaults objectForKey:[NSString stringWithFormat:MGMEGrowl, theEvent]] boolValue];
if (growl) {
NSString *title = nil;
NSString *description = nil;
NSString *notificationName = nil;
if (theEvent==MGMEUploading) {
title = @"Uploading File";
description = [NSString stringWithFormat:@"Uploading %@", [[thePath lastPathComponent] stringByDeletingPathExtension]];
notificationName = @"UploadingFile";
} else if (theEvent==MGMEUploadingAutomatic) {
title = @"Automatically Uploading File";
description = [NSString stringWithFormat:@"Uploading %@", [[thePath lastPathComponent] stringByDeletingPathExtension]];
notificationName = @"UploadingFileAutomatically";
} else if (theEvent==MGMEUploaded) {
title = @"Uploaded File";
description = [NSString stringWithFormat:@"Uploaded %@ to %@", [[thePath lastPathComponent] stringByDeletingPathExtension], theURL];
notificationName = @"UploadedFile";
} else if (theEvent==MGMEUploadedAutomatic) {
title = @"Automatically Uploaded File";
description = [NSString stringWithFormat:@"Uploaded %@ to %@", [[thePath lastPathComponent] stringByDeletingPathExtension], theURL];
notificationName = @"UploadedFileAutomatically";
}
[GrowlApplicationBridge notifyWithTitle:title description:description notificationName:notificationName iconData:[[[NSApplication sharedApplication] applicationIconImage] TIFFRepresentation] priority:0 isSticky:NO clickContext:nil];
}
}
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finishedPlaying {
if (finishedPlaying)
[sound release];
}
- (NSMutableArray *)uploads {
return uploads;
}
- (NSDictionary *)uploadForPath:(NSString *)thePath {
for (int i=0; i<[uploads count]; i++) {
if ([[[uploads objectAtIndex:i] objectForKey:MGMUPath] isEqual:thePath])
return [uploads objectAtIndex:i];
}
return nil;
}
- (void)addPathToUploads:(NSString *)thePath isAutomatic:(BOOL)isAutomatic {
if ([self uploadForPath:thePath]==nil) {
if ([currentPlugIn respondsToSelector:@selector(allowedExtensions)]) {
if (![[currentPlugIn allowedExtensions] containsObject:[[thePath pathExtension] lowercaseString]]) {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Upload Error"];
[alert setInformativeText:@"The current PlugIn does not support this file format."];
[alert runModal];
return;
}
}
[uploads addObject:[NSDictionary dictionaryWithObjectsAndKeys:thePath, MGMUPath, [NSNumber numberWithBool:isAutomatic], MGMUAutomatic, nil]];
if ([uploads count]==1)
[self processNextUpload];
}
}
- (void)processNextUpload {
if ([uploads count]>0) {
if (currentPlugIn==nil) {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Upload Error"];
[alert setInformativeText:@"No PlugIns found. You must have at least 1 PlugIn to upload a file."];
[alert runModal];
[uploads removeAllObjects];
return;
} else if (![currentPlugIn respondsToSelector:@selector(sendFileAtPath:withName:)]) {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Upload Error"];
[alert setInformativeText:@"The current PlugIn doesn't support uploading."];
[alert runModal];
[uploads removeAllObjects];
return;
}
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *upload = [uploads objectAtIndex:0];
if (![manager fileExistsAtPath:[upload objectForKey:MGMUPath]]) {
[uploads removeObject:upload];
[self processNextUpload];
return;
}
[menuItem setImage:[NSImage imageNamed:@"menuiconupload"]];
[self processEvent:([[upload objectForKey:MGMUAutomatic] boolValue] ? MGMEUploadingAutomatic : MGMEUploading) path:[upload objectForKey:MGMUPath]];
int uploadNameType = [[[NSUserDefaults standardUserDefaults] objectForKey:MGMUploadName] intValue];
NSString *randomizedName = [[NSString stringWithFormat:@"%d", [[NSDate date] timeIntervalSince1970]] MD5];
NSString *name = [[upload objectForKey:MGMUPath] lastPathComponent];
if ((uploadNameType==0 && [[upload objectForKey:MGMUAutomatic] boolValue]) || uploadNameType==1)
name = [randomizedName stringByAppendingPathExtension:[name pathExtension]];
[currentPlugIn sendFileAtPath:[upload objectForKey:MGMUPath] withName:name];
} else {
[menuItem setImage:[NSImage imageNamed:@"menuicon"]];
}
}
- (void)upload:(NSString *)thePath receivedError:(NSError *)theError {
NSDictionary *upload = [self uploadForPath:thePath];
if (upload!=nil) {
if ([[NSUserDefaults standardUserDefaults] boolForKey:MGMGrowlErrors]) {
[GrowlApplicationBridge notifyWithTitle:@"Unable to upload" description:[NSString stringWithFormat:@"%@: %@", [[upload objectForKey:MGMUPath] lastPathComponent], [theError localizedDescription]] notificationName:@"UploadError" iconData:[[[NSApplication sharedApplication] applicationIconImage] TIFFRepresentation] priority:1 isSticky:NO clickContext:nil];
} else {
NSAlert *alert = [[NSAlert new] autorelease];
[alert setMessageText:@"Upload Error"];
[alert setInformativeText:[NSString stringWithFormat:@"Unable to upload %@: %@", [[upload objectForKey:MGMUPath] lastPathComponent], [theError localizedDescription]]];
[alert runModal];
}
[uploads removeObject:upload];
[self processNextUpload];
}
}
- (void)uploadFinished:(NSString *)thePath url:(NSURL *)theURL {
NSDictionary *upload = [self uploadForPath:thePath];
if (upload!=nil) {
[self processEvent:([[upload objectForKey:MGMUAutomatic] boolValue] ? MGMEUploadedAutomatic : MGMEUploaded) path:[upload objectForKey:MGMUPath] url:theURL];
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
[pboard declareTypes:[NSArray arrayWithObjects:MGMNSStringPboardType, MGMNSPasteboardTypeString, nil] owner:nil];
[pboard setString:[theURL absoluteString] forType:MGMNSStringPboardType];
[pboard setString:[theURL absoluteString] forType:MGMNSPasteboardTypeString];
[self addURLToHistory:theURL];
[uploads removeObject:upload];
[self processNextUpload];
}
}
@end

22
Classes/CocoaShare/MGMFileManager.h

@ -0,0 +1,22 @@
//
// MGMFileManager.h
// CocoaShare
//
// Created by James on 1/22/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Cocoa/Cocoa.h>
@interface NSFileManager (MGMFileManager)
- (BOOL)moveItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination;
- (BOOL)copyItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination;
- (BOOL)removeItemAtPath:(NSString *)thePath;
- (BOOL)linkItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination;
- (BOOL)createSymbolicLinkAtPath:(NSString *)thePath withDestinationPath:(NSString *)theDestination;
- (NSString *)destinationOfSymbolicLinkAtPath:(NSString *)thePath;
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)thePath;
- (NSDictionary *)attributesOfFileSystemForPath:(NSString *)thePath;
- (void)setAttributes:(NSDictionary *)theAttributes ofItemAtPath:(NSString *)thePath;
- (NSDictionary *)attributesOfItemAtPath:(NSString *)thePath;
@end

73
Classes/CocoaShare/MGMFileManager.m

@ -0,0 +1,73 @@
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
//
// MGMFileManager.m
// CocoaShare
//
// Created by James on 1/22/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import "MGMFileManager.h"
@implementation NSFileManager (MGMFileManager)
- (BOOL)moveItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination {
if ([self respondsToSelector:@selector(movePath:toPath:handler:)])
return [self movePath:thePath toPath:theDestination handler:nil];
else
return [self moveItemAtPath:thePath toPath:theDestination error:nil];
}
- (BOOL)copyItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination {
if ([self respondsToSelector:@selector(copyPath:toPath:handler:)])
return [self copyPath:thePath toPath:theDestination handler:nil];
else
return [self copyItemAtPath:thePath toPath:theDestination error:nil];
}
- (BOOL)removeItemAtPath:(NSString *)thePath {
if ([self respondsToSelector:@selector(removeFileAtPath:handler:)])
return [self removeFileAtPath:thePath handler:nil];
else
return [self removeItemAtPath:thePath error:nil];
}
- (BOOL)linkItemAtPath:(NSString *)thePath toPath:(NSString *)theDestination {
if ([self respondsToSelector:@selector(linkPath:toPath:handler:)])
return [self linkPath:thePath toPath:theDestination handler:nil];
else
return [self linkItemAtPath:thePath toPath:theDestination error:nil];
}
- (BOOL)createSymbolicLinkAtPath:(NSString *)thePath withDestinationPath:(NSString *)theDestination {
if ([self respondsToSelector:@selector(createSymbolicLinkAtPath:pathContent:)])
return [self createSymbolicLinkAtPath:thePath pathContent:theDestination];
else
return [self createSymbolicLinkAtPath:thePath withDestinationPath:theDestination error:nil];
}
- (NSString *)destinationOfSymbolicLinkAtPath:(NSString *)thePath {
if ([self respondsToSelector:@selector(pathContentOfSymbolicLinkAtPath:)])
return [self pathContentOfSymbolicLinkAtPath:thePath];
else
return [self destinationOfSymbolicLinkAtPath:thePath error:nil];
}
- (NSArray *)contentsOfDirectoryAtPath:(NSString *)thePath {
if ([self respondsToSelector:@selector(directoryContentsAtPath:)])
return [self directoryContentsAtPath:thePath];
else
return [self contentsOfDirectoryAtPath:thePath error:nil];
}
- (NSDictionary *)attributesOfFileSystemForPath:(NSString *)thePath {
if ([self respondsToSelector:@selector(fileSystemAttributesAtPath:)])
return [self fileSystemAttributesAtPath:thePath];
else
return [self attributesOfFileSystemForPath:thePath error:nil];
}
- (void)setAttributes:(NSDictionary *)theAttributes ofItemAtPath:(NSString *)thePath {
if ([self respondsToSelector:@selector(changeFileAttributes:atPath:)])
[self changeFileAttributes:theAttributes atPath:thePath];
else
[self setAttributes:theAttributes ofItemAtPath:thePath error:nil];
}
- (NSDictionary *)attributesOfItemAtPath:(NSString *)thePath {
if ([self respondsToSelector:@selector(fileAttributesAtPath:traverseLink:)])
return [self fileAttributesAtPath:thePath traverseLink:YES];
else
return [self attributesOfItemAtPath:thePath error:nil];
}
@end

24
Classes/CocoaShare/MGMLoginItems.h

@ -0,0 +1,24 @@
//
// MGMLoginItems.h
// Exhaust
//
// Created by Mr. Gecko on 8/7/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Cocoa/Cocoa.h>
@interface MGMLoginItems : NSObject {
NSMutableDictionary *loginItems;
}
+ (id)items;
- (NSArray *)paths;
- (BOOL)selfExists;
- (BOOL)addSelf;
- (BOOL)removeSelf;
- (BOOL)exists:(NSString *)thePath;
- (BOOL)add:(NSString *)thePath;
- (BOOL)add:(NSString *)thePath hide:(BOOL)shouldHide;
- (BOOL)remove:(NSString *)thePath;
- (void)_save;
@end

89
Classes/CocoaShare/MGMLoginItems.m

@ -0,0 +1,89 @@
//
// MGMLoginItems.m
// Exhaust
//
// Created by Mr. Gecko on 8/7/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import "MGMLoginItems.h"
NSString * const MGMLoginItemsPath = @"~/Library/Preferences/loginwindow.plist";
NSString * const MGMItemsKey = @"AutoLaunchedApplicationDictionary";
NSString * const MGMPathKey = @"Path";
NSString * const MGMHideKey = @"Hide";
@implementation MGMLoginItems
+ (id)items {
return [[[self alloc] init] autorelease];
}
- (id)init {
if (self = [super init]) {
loginItems = [[NSMutableDictionary dictionaryWithContentsOfFile:[MGMLoginItemsPath stringByExpandingTildeInPath]] retain];
}
return self;
}
- (void)dealloc {
[loginItems release];
[super dealloc];
}
- (NSArray *)paths {
NSMutableArray *returnApps = [NSMutableArray array];
NSArray *applications = [loginItems objectForKey:MGMItemsKey];
for (int i=0; i<[applications count]; i++) {
[returnApps addObject:[[applications objectAtIndex:i] objectForKey:MGMPathKey]];
}
return returnApps;
}
- (BOOL)selfExists {
return [self exists:[[NSBundle mainBundle] bundlePath]];
}
- (BOOL)addSelf {
return [self add:[[NSBundle mainBundle] bundlePath]];
}
- (BOOL)removeSelf {
return [self remove:[[NSBundle mainBundle] bundlePath]];
}
- (BOOL)exists:(NSString *)thePath {
NSArray *applications = [loginItems objectForKey:MGMItemsKey];
for (int i=0; i<[applications count]; i++) {
if ([[[applications objectAtIndex:i] objectForKey:MGMPathKey] isEqual:thePath])
return YES;
}
return NO;
}
- (BOOL)add:(NSString *)thePath {
return [self add:thePath hide:NO];
}
- (BOOL)add:(NSString *)thePath hide:(BOOL)shouldHide {
if ([self exists:thePath])
return NO;
NSMutableArray *applications = [NSMutableArray arrayWithArray:[loginItems objectForKey:MGMItemsKey]];
NSMutableDictionary *info = [NSMutableDictionary dictionary];
[info setObject:thePath forKey:MGMPathKey];
[info setObject:[NSNumber numberWithBool:shouldHide] forKey:MGMHideKey];
[applications addObject:info];
[loginItems setObject:applications forKey:MGMItemsKey];
[self _save];
return YES;
}
- (BOOL)remove:(NSString *)thePath {
NSMutableArray *applications = [NSMutableArray arrayWithArray:[loginItems objectForKey:MGMItemsKey]];
for (int i=0; i<[applications count]; i++) {
if ([[[applications objectAtIndex:i] objectForKey:MGMPathKey] isEqual:thePath]) {
[applications removeObjectAtIndex:i];
[loginItems setObject:applications forKey:MGMItemsKey];
[self _save];
return YES;
}
}
return NO;
}
- (void)_save {
[loginItems writeToFile:[MGMLoginItemsPath stringByExpandingTildeInPath] atomically:YES];
}
@end

33
Classes/CocoaShare/MGMMenuItem.h

@ -0,0 +1,33 @@
//
// MGMMenuItem.h
// CocoaShare
//
// Created by James on 1/16/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Cocoa/Cocoa.h>
@protocol MGMMenuItemDelegate <NSObject>
- (void)menuClicked:(id)sender;
- (void)menuDraggingEntered:(id)sender;
- (void)menuDraggingExited:(id)sender;
- (void)menu:(id)sender droppedFiles:(NSArray *)files;
@end
@interface MGMMenuItem : NSView {
id<MGMMenuItemDelegate> delegate;
NSImage *image;
NSImage *alternateImage;
BOOL isHighlighted;
}
- (void)setDelegate:(id)theDelegate;
- (id<MGMMenuItemDelegate>)delegate;
- (void)setImage:(NSImage *)theImage;
- (NSImage *)image;
- (void)setAlternateImage:(NSImage *)theImage;
- (NSImage *)alternateImage;
@end

87
Classes/CocoaShare/MGMMenuItem.m

@ -0,0 +1,87 @@
//
// MGMMenuItem.m
// CocoaShare
//
// Created by James on 1/16/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import "MGMMenuItem.h"
@implementation MGMMenuItem
- (id)initWithFrame:(NSRect)frame {
if ((self = [super initWithFrame:NSMakeRect(0, 0, 22, 22)])) {
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}
return self;
}
- (void)dealloc {
[image release];
[alternateImage release];
[super dealloc];
}
- (void)setDelegate:(id)theDelegate {
delegate = theDelegate;
}
- (id<MGMMenuItemDelegate>)delegate {
return delegate;
}
- (void)setImage:(NSImage *)theImage {
[image release];
image = [theImage copy];
[self display];
}
- (NSImage *)image {
return image;
}
- (void)setAlternateImage:(NSImage *)theImage {
[alternateImage release];
alternateImage = [theImage copy];
}
- (NSImage *)alternateImage {
return alternateImage;
}
- (void)drawRect:(NSRect)theRect {
NSImage *displayImage = image;
if (isHighlighted) {
NSBezierPath *path = [NSBezierPath bezierPathWithRect:theRect];
[[NSColor selectedMenuItemColor] set];
[path fill];
displayImage = alternateImage;
}
[displayImage drawInRect:NSMakeRect((22-[image size].width)/2, (22-[image size].height)/2, [image size].width, [image size].height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}
- (void)mouseDown:(NSEvent *)theEvent {
isHighlighted = YES;
[self display];
if ([delegate respondsToSelector:@selector(menuClicked:)]) [delegate menuClicked:self];
isHighlighted = NO;
[self display];
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
if ([[[sender draggingPasteboard] types] containsObject:NSFilenamesPboardType]) {
if ([delegate respondsToSelector:@selector(menuDraggingEntered:)]) [delegate menuDraggingEntered:self];
return NSDragOperationEvery;
}
return NSDragOperationNone;
}
- (void)draggingExited:(id <NSDraggingInfo>)sender {
if ([delegate respondsToSelector:@selector(menuDraggingExited:)]) [delegate menuDraggingExited:self];
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pboard = [sender draggingPasteboard];
if ([delegate respondsToSelector:@selector(menuDraggingExited:)]) [delegate menuDraggingExited:self];
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
if ([delegate respondsToSelector:@selector(menu:droppedFiles:)]) [delegate menu:self droppedFiles:files];
return YES;
}
return NO;
}
@end

33
Classes/CocoaShare/MGMPathSubscriber.h

@ -0,0 +1,33 @@
//
// MGMPathSubscriber.h
// CocoaShare
//
// Created by Mr. Gecko on 1/15/11.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
//
#import <Foundation/Foundation.h>
extern NSString * const MGMPathSubscriptionChangedNotification;
@protocol MGMPathSubscriberDelegate <NSObject>
- (void)subscribedPathChanged:(NSString *)thePath;
@end
@interface MGMPathSubscriber : NSObject {
id<MGMPathSubscriberDelegate> delegate;
NSMutableDictionary *subscriptions;
FNSubscriptionUPP subscriptionUPP;
NSMutableArray *notificationsSending;
}
+ (id)sharedPathSubscriber;
- (id<MGMPathSubscriberDelegate>)delegate;
- (void)setDelegate:(id)theDelegate;
- (void)addPath:(NSString *)thePath;
- (void)removePath:(NSString *)thePath;
- (void)removeAllPaths;
- (NSArray *)subscribedPaths;
@end

101
Classes/CocoaShare/MGMPathSubscriber.m

@ -0,0 +1,101 @@
//
/