diff --git a/recv.php b/recv.php
index fb776af..0ded369 100644
--- a/recv.php
+++ b/recv.php
@@ -4,7 +4,9 @@
# Install by putting this file on your web server and give the web server
# user write permissions to the directory in which you put this script.
#
+$SECRET = ""; # Set to "" if you don't want authentication
$MAXLENGTH = 4096000; # 4 MB
+$HTTP_LINK = true; # Set to true if you want all image links to point to the unsecure version
function rsperr($msg='', $st='400 Bad Request') {
header('HTTP/1.1 '.$st);
exit($msg);
@@ -19,9 +21,14 @@ function pathfromid($id, $suffix='') {
$suffix = strrchr($_GET['name'], '.');
$path = pathfromid($id, $suffix);
$abspath = dirname(realpath(__FILE__)).'/'.$path;
-$url = (isset($_SERVER['HTTPS']) ? 'https://' : 'http://')
+$url = (isset($_SERVER['HTTPS'] && $HTTP_LINK != true) ? 'https://' : 'http://')
. $_SERVER['SERVER_NAME'] . dirname($_SERVER['SCRIPT_NAME']) . '/' . $path;
+// Check if the secret is correct
+if(!empty($SECRET) && $_SERVER['HTTP_X_SCRUP_AUTH'] != base64_encode($SECRET)) {
+ rsperr("Bad authentication credentials!", "401 Unauthorized");
+}
+
# make dir if needed
$dirpath = dirname($abspath);
if (!file_exists($dirpath) && @mkdir($dirpath, 0775) === false)
diff --git a/resources/MainMenu.xib b/resources/MainMenu.xib
index b1cdb43..7f7bc25 100644
--- a/resources/MainMenu.xib
+++ b/resources/MainMenu.xib
@@ -2,10 +2,10 @@
1050
- 10C540
- 740
- 1038.25
- 458.00
+ 11D50
+ 2182
+ 1138.32
+ 568.00
diff --git a/scrup.xcodeproj/project.pbxproj b/scrup.xcodeproj/project.pbxproj
index 3d53ce5..dcda1a0 100644
--- a/scrup.xcodeproj/project.pbxproj
+++ b/scrup.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 45;
+ objectVersion = 46;
objects = {
/* Begin PBXAggregateTarget section */
@@ -554,8 +554,11 @@
/* Begin PBXProject section */
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0430;
+ };
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "scrup" */;
- compatibilityVersion = "Xcode 3.1";
+ compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
@@ -774,7 +777,6 @@
buildSettings = {
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- GCC_ENABLE_FIX_AND_CONTINUE = NO;
PRODUCT_NAME = Distribution;
ZERO_LINK = NO;
};
@@ -787,14 +789,12 @@
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
- GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_ENABLE_OBJC_GC = supported;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INSTALL_PATH = /usr/local/lib;
- PREBINDING = NO;
PRODUCT_NAME = pngcrush;
- SDKROOT = macosx10.6;
+ SDKROOT = macosx;
VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64";
};
name = Debug;
@@ -810,7 +810,6 @@
GCC_DEBUGGING_SYMBOLS = used;
GCC_DYNAMIC_NO_PIC = YES;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
- GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_ENABLE_OBJC_GC = supported;
GCC_ENABLE_SSE3_EXTENSIONS = YES;
GCC_ENABLE_SSE41_EXTENSIONS = YES;
@@ -820,9 +819,8 @@
GCC_OPTIMIZATION_LEVEL = 3;
GCC_UNROLL_LOOPS = YES;
INSTALL_PATH = /usr/local/lib;
- PREBINDING = NO;
PRODUCT_NAME = pngcrush;
- SDKROOT = macosx10.6;
+ SDKROOT = macosx;
VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64";
ZERO_LINK = NO;
};
@@ -839,7 +837,6 @@
"\"$(SRCROOT)/frameworks\"",
);
GCC_DYNAMIC_NO_PIC = NO;
- GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_ENABLE_OBJC_GC = required;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -852,8 +849,9 @@
GCC_WARN_UNUSED_VALUE = YES;
INFOPLIST_FILE = resources/Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
+ OTHER_LDFLAGS = "-lcrypto";
PRODUCT_NAME = Scrup;
- SDKROOT = macosx10.6;
+ SDKROOT = macosx;
};
name = Debug;
};
@@ -880,8 +878,9 @@
GCC_WARN_UNUSED_VALUE = YES;
INFOPLIST_FILE = resources/Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
+ OTHER_LDFLAGS = "-lcrypto";
PRODUCT_NAME = Scrup;
- SDKROOT = macosx10.6;
+ SDKROOT = macosx;
};
name = Release;
};
@@ -894,8 +893,8 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
- PREBINDING = NO;
- SDKROOT = macosx10.5;
+ OTHER_LDFLAGS = "";
+ SDKROOT = macosx;
};
name = Debug;
};
@@ -906,8 +905,8 @@
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- PREBINDING = NO;
- SDKROOT = macosx10.5;
+ OTHER_LDFLAGS = "";
+ SDKROOT = macosx;
};
name = Release;
};
diff --git a/src/DPAppDelegate.h b/src/DPAppDelegate.h
index 253d6d1..9a7653e 100644
--- a/src/DPAppDelegate.h
+++ b/src/DPAppDelegate.h
@@ -15,6 +15,7 @@
IBOutlet NSView *advancedSettingsView;
IBOutlet SUUpdater *updater;
IBOutlet NSTextField *receiverURL;
+ IBOutlet NSTextField *receiverSecret;
IBOutlet NSMenuItem *pauseMenuItem;
BOOL openAtLogin,
showInDock,
diff --git a/src/DPAppDelegate.m b/src/DPAppDelegate.m
index 6d55f54..d7c93fb 100644
--- a/src/DPAppDelegate.m
+++ b/src/DPAppDelegate.m
@@ -10,6 +10,11 @@
#include
#include
+/* For base64 encoding */
+#include
+#include
+
+
#define SCREENSHOT_LOG_LIMIT 10 /* todo: make configurable */
/*@interface NSStatusBar (Unofficial)
@@ -153,6 +158,12 @@ - (void)awakeFromNib {
[self performSelectorInBackground:@selector(debugPerpetualStateCheck) withObject:nil];
#endif
+ /* In order to check for http/https if the secret is set.
+ XXX The user is still not warned if the preferences window is closed without "ending"
+ the input session (because then controlTextDidEndEditing doesn't get called, for some reason */
+ [receiverSecret setDelegate:self];
+ [receiverURL setDelegate:self];
+
// XXX
/*[self displayPreprocessingUIForScreenshotAtPath:@""
meta:[NSDictionary dictionaryWithObjectsAndKeys:[NSDate date], @"du", nil]
@@ -161,6 +172,47 @@ - (void)awakeFromNib {
}];*/
}
+-(void) controlTextDidEndEditing:(NSNotification *)aNotification {
+ if([aNotification object] == receiverSecret || [aNotification object] == receiverURL) {
+ /* If we're losing focus because sslAlertEnd switched to receiverURL, don't display another sheet.
+ Also check user preference. */
+ if([mainWindow attachedSheet] != NULL
+ || [defaults boolForKey:@"sslDontAskAgain"]) {
+ return;
+ }
+
+ /* If a secret is set, check if receiverURL contains 'https://' and alert if it doesn't */
+ if(!([[receiverSecret stringValue] isEqualToString:@""] || [[receiverURL stringValue] isEqualToString:@""])) {
+ NSRange matchHTTPS = [[receiverURL stringValue] rangeOfString:@"https://"];
+ if(matchHTTPS.length <= 0) {
+ NSAlert *sslAlert = [[[NSAlert alloc] init] autorelease];
+ [sslAlert setMessageText:@"Security Tip"];
+ [sslAlert setInformativeText:@"Great, you set a secret key! But you should really use a secure connection (SSL, \"https://\") in this case. Otherwise anyone eavesdropping on your connection can easily filter out the key."];
+ [sslAlert addButtonWithTitle:@"Re-Edit Receiver URL ..."];
+ [sslAlert addButtonWithTitle:@"No! Don't ever ask again."];
+ [sslAlert beginSheetModalForWindow:mainWindow modalDelegate:self didEndSelector:@selector(sslAlertEnd:returnCode:contextInfo:) contextInfo:nil];
+ }
+ }
+ }
+}
+
+-(void)sslAlertEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
+ switch(returnCode) {
+ case NSAlertFirstButtonReturn:
+ /* Select the URL field's 'http://' portion */
+ [receiverURL becomeFirstResponder];
+ NSText* textEditor = [mainWindow fieldEditor:YES forObject:receiverURL];
+ NSRange range = {0, 7};
+ [textEditor setSelectedRange:range];
+
+ break;
+ case NSAlertSecondButtonReturn:
+ [defaults setBool:YES forKey:@"sslDontAskAgain"];
+ break;
+ }
+ return;
+}
+
- (NSRect)menuItemFrame {
// ugly, ugly hack... damn you Apple.
@@ -491,6 +543,26 @@ -(void)processScreenshotAtPath:(NSString *)path modifiedAtDate:(NSDate *)dateMod
return;
}
+ // Check for a secret and base64 encode it
+ NSString *secret = [receiverSecret stringValue];
+ NSString *encodedSecret = NULL;
+ if([secret length] > 0) {
+ BIO *context = BIO_new(BIO_s_mem());
+
+ BIO *command = BIO_new(BIO_f_base64());
+ context = BIO_push(command, context);
+
+ // Encode all the data
+ BIO_write(context, [[secret dataUsingEncoding:NSUTF8StringEncoding] bytes], [[secret dataUsingEncoding:NSUTF8StringEncoding] length]);
+ BIO_flush(context);
+
+ char *outputBuffer;
+ long outputLength = BIO_get_mem_data(context, &outputBuffer);
+ encodedSecret = [NSString stringWithCString:outputBuffer length:outputLength];
+ BIO_free_all(context);
+ }
+
+
// Register
NSMutableDictionary *rec = [uploadedScreenshots objectForKey:fn];
if (rec) {
@@ -505,6 +577,9 @@ -(void)processScreenshotAtPath:(NSString *)path modifiedAtDate:(NSDate *)dateMod
void (^continue_block)(NSString *) = ^(NSString *actualPath){
HTTPPOSTOperation *postOp = [HTTPPOSTOperation alloc];
[postOp initWithPath:actualPath URL:url delegate:self];
+ if(encodedSecret != NULL)
+ [postOp.request setValue:[encodedSecret stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] forHTTPHeaderField:@"X-Scrup-Auth"];
+
nCurrOps++;
[self updateMenuItem:self];
[statusItem setImage:iconSending];