From 2b0a6428279dc80b5960f7da4e0ffbee25f3774f Mon Sep 17 00:00:00 2001 From: cacaodev Date: Fri, 8 Apr 2016 18:45:15 +0200 Subject: [PATCH 1/4] FIXED: CPView received multiple -viewDidHide/Unhide messages FIXED: when a view is hidden by a hidden superview and added to a non hidden superview, the -viewDidUnhide message is sent. With test : CPViewTest.j --- AppKit/CPView.j | 88 ++++++++++++-------- Tests/AppKit/CPViewTest.j | 165 +++++++++++++++++++++++++++++++------- 2 files changed, 190 insertions(+), 63 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 669f21122..a142e82a9 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -172,6 +172,7 @@ var CPViewHighDPIDrawingEnabled = YES; CPArray _registeredDraggedTypesArray; BOOL _isHidden; + BOOL _isHiddenOrHasHiddenAncestor; BOOL _hitTests; BOOL _clipsToBounds; @@ -372,6 +373,7 @@ var CPViewHighDPIDrawingEnabled = YES; _opacity = 1.0; _isHidden = NO; + _isHiddenOrHasHiddenAncestor = NO; _hitTests = YES; _hierarchyScaleSize = CGSizeMake(1.0 , 1.0); @@ -598,7 +600,7 @@ var CPViewHighDPIDrawingEnabled = YES; [aSubview _removeFromSuperview]; // Set ourselves as the superview. - aSubview._superview = self; + [aSubview _setSuperview:self]; } if (anIndex === CPNotFound || anIndex >= count) @@ -623,11 +625,6 @@ var CPViewHighDPIDrawingEnabled = YES; [aSubview setNextResponder:self]; [aSubview _scaleSizeUnitSquareToSize:[self _hierarchyScaleSize]]; - // If the subview is not hidden and one of its ancestors is hidden, - // notify the subview that it is now hidden. - if (![aSubview isHidden] && [self isHiddenOrHasHiddenAncestor]) - [aSubview _notifyViewDidHide]; - [aSubview viewDidMoveToSuperview]; // Set the subview's window to our own. @@ -697,13 +694,10 @@ var CPViewHighDPIDrawingEnabled = YES; // If the view is not hidden and one of its ancestors is hidden, // notify the view that it is now unhidden. - if (!_isHidden && [_superview isHiddenOrHasHiddenAncestor]) - [self _notifyViewDidUnhide]; + [self _setSuperview:nil]; [self _notifyWindowDidResignKey]; [self _notifyViewDidResignFirstResponder]; - - _superview = nil; } /*! @@ -1599,7 +1593,7 @@ var CPViewHighDPIDrawingEnabled = YES; // FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE. // _DOMElement.style.visibility = (_isHidden = aFlag) ? "hidden" : "visible"; - _isHidden = aFlag; + #if PLATFORM(DOM) _DOMElement.style.display = _isHidden ? "none" : "block"; @@ -1622,33 +1616,61 @@ var CPViewHighDPIDrawingEnabled = YES; while (view = [view superview]); } - [self _notifyViewDidHide]; + [self _recursiveGainedHiddenAncestor]; } else { [self setNeedsDisplay:YES]; - [self _notifyViewDidUnhide]; + + [self _recursiveLostHiddenAncestor]; } + + _isHidden = aFlag; } -- (void)_notifyViewDidHide +- (void)_setSuperview:(CPView)aSuperview { - [self viewDidHide]; + var hasOldSuperview = (_superview !== nil), + hasNewSuperview = (aSuperview !== nil), + oldSuperviewIsHidden = hasOldSuperview && [_superview isHiddenOrHasHiddenAncestor], + newSuperviewIsHidden = hasNewSuperview && [aSuperview isHiddenOrHasHiddenAncestor]; - var count = [_subviews count]; + if (!newSuperviewIsHidden && oldSuperviewIsHidden) + [self _recursiveLostHiddenAncestor]; - while (count--) - [_subviews[count] _notifyViewDidHide]; + if (newSuperviewIsHidden && !oldSuperviewIsHidden) + [self _recursiveGainedHiddenAncestor]; + + _superview = aSuperview; } -- (void)_notifyViewDidUnhide +- (void)_recursiveLostHiddenAncestor { - [self viewDidUnhide]; + if (_isHiddenOrHasHiddenAncestor) + { + _isHiddenOrHasHiddenAncestor = NO; + [self viewDidUnhide]; + } - var count = [_subviews count]; + [_subviews enumerateObjectsUsingBlock:function(view, idx, stop) + { + [view _recursiveLostHiddenAncestor]; + }]; +} - while (count--) - [_subviews[count] _notifyViewDidUnhide]; +- (void)_recursiveGainedHiddenAncestor +{ + if (!_isHidden) + { + [self viewDidHide]; + } + + _isHiddenOrHasHiddenAncestor = YES; + + [_subviews enumerateObjectsUsingBlock:function(view, idx, stop) + { + [view _recursiveGainedHiddenAncestor]; + }]; } /*! @@ -1718,12 +1740,7 @@ var CPViewHighDPIDrawingEnabled = YES; */ - (BOOL)isHiddenOrHasHiddenAncestor { - var view = self; - - while (view && ![view isHidden]) - view = [view superview]; - - return view !== nil; + return _isHiddenOrHasHiddenAncestor; } /*! @@ -3494,14 +3511,14 @@ setBoundsOrigin: Invoked automatically when the view’s geometry changes such that its tracking areas need to be recalculated. You should override this method to remove out of date tracking areas and add recomputed tracking areas; - + Cocoa calls this on every view, whereas they have tracking area(s) or not. Cappuccino behaves differently : - updateTrackingAreas is called when placing a view in the view hierarchy (that is in a window) - if you have only CPTrackingInVisibleRect tracking areas attached to a view, it will not be called again (until you move the view in the hierarchy) - if you have at least one non-CPTrackingInVisibleRect tracking area attached, it will be called every time the view geometry could be modified You don't have to touch to CPTrackingInVisibleRect tracking areas, they will be automatically updated - + Please note that it is the owner of a tracking area who is called for updateTrackingAreas. But, if a view without any tracking area is inserted in the view hierarchy (that is, in a window), the view is called for updateTrackingAreas. This enables you to use updateTrackingArea to initially attach your tracking areas to the view. @@ -3513,16 +3530,16 @@ setBoundsOrigin: /*! This utility method is intended for CPView subclasses overriding updateTrackingAreas - + Typical use would be : - + - (void)updateTrackingAreas { [self removeAllTrackingAreas]; - + ... add your specific updated tracking areas ... } - + */ - (void)removeAllTrackingAreas { @@ -3707,6 +3724,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", #endif [self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]]; + _isHiddenOrHasHiddenAncestor = NO; if ([aCoder containsValueForKey:CPViewOpacityKey]) [self setAlphaValue:[aCoder decodeIntForKey:CPViewOpacityKey]]; diff --git a/Tests/AppKit/CPViewTest.j b/Tests/AppKit/CPViewTest.j index 383db1a99..78812d2fc 100644 --- a/Tests/AppKit/CPViewTest.j +++ b/Tests/AppKit/CPViewTest.j @@ -895,70 +895,167 @@ var updateTrackingAreasCalls, [self assert:nil equals:[view effectiveAppearance]]; } +- (void)testViewDidHideDidUnhide +{ + var expectedResult = [@"viewDidHide_view1", @"viewDidUnhide_view1"]; + + [view1 setHidden:YES]; + [view1 setHidden:NO]; + + [self assert:expectedResult equals:methodCalled]; +} + +- (void)testViewGainedHiddenAncestor +{ + var expectedResult = [@"viewDidHide_view1", + @"viewWillMoveToSuperview_view3", + @"viewDidMoveToSuperview_view3", + @"viewWillMoveToSuperview_view2", + @"viewDidHide_view2", + @"viewDidHide_view3", + @"viewDidMoveToSuperview_view2"]; + + [view1 setHidden:YES]; + [view2 addSubview:view3]; + [view1 addSubview:view2]; + + [self assert:expectedResult equals:methodCalled]; + [self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES"]; + [self assertTrue: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES"]; + + [self assertFalse:[view2 isHidden]]; + [self assertFalse:[view3 isHidden]]; +} + +- (void)testRemoveViewsHiddenByAncestor +{ + var expectedResult = @[ + @"viewWillMoveToSuperview_view2", + @"viewDidUnhide_view2", + @"viewDidUnhide_view3", + @"viewDidMoveToSuperview_view2", + @"viewWillMoveToWindow_view2", + @"viewWillMoveToWindow_view3", + @"viewDidMoveToWindow_view3", + @"viewDidMoveToWindow_view2" +]; + + [view1 setHidden:YES]; + [view1 addSubview:view2]; + [view2 addSubview:view3]; + + [self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES" ]; + [self assertFalse:[view2 isHidden]]; + + [self assertTrue: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES" ]; + [self assertFalse:[view3 isHidden]]; + + methodCalled = []; + + [view2 removeFromSuperview]; + + [self assertFalse: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = NO" ]; + [self assertFalse: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = NO" ]; + + [self assert:expectedResult equals:methodCalled]; +} + +- (void)testRemoveHiddenView +{ + var expectedResult = [@"viewWillMoveToSuperview_view2", @"viewDidMoveToSuperview_view2", @"viewWillMoveToWindow_view2", @"viewDidMoveToWindow_view2"]; + + [view1 addSubview:view2]; + [view2 setHidden:YES]; + + methodCalled = []; + + [view2 removeFromSuperview]; + [self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES" ]; + [self assert:expectedResult equals:methodCalled]; +} + +- (void)testLostHiddenAncestorAfterMovingToNewSuperview +{ + var expectedResult = @[ + @"viewWillMoveToSuperview_view2", + @"viewDidMoveToSuperview_view2", + @"viewDidHide_view1", + @"viewDidHide_view2", + @"viewWillMoveToSuperview_view2", + @"viewDidUnhide_view2", + @"viewDidMoveToSuperview_view2" +]; + + [view1 addSubview:view2]; + [view1 setHidden:YES]; + [view3 addSubview:view2]; + + [self assert:expectedResult equals:methodCalled]; +} // TrackingAreaAdditions - (void)testTrackingAreas { var trackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect owner:self userInfo:nil]; - + [self assert:0 equals:[[view trackingAreas] count] message:@"Initially, a view has no tracking area"]; // - + [view addTrackingArea:trackingArea]; [self assert:1 equals:[[view trackingAreas] count] message:@"After adding a tracking area"]; [self assert:view equals:[trackingArea view] message:@"Tracking area should be linked to view"]; // - + [view removeTrackingArea:trackingArea]; [self assert:0 equals:[[view trackingAreas] count] message:@"After removing the only tracking area"]; [self assert:nil equals:[trackingArea view] message:@"Tracking area should be unlinked"]; - + // - + [view addTrackingArea:trackingArea]; [view addTrackingArea:trackingArea]; [view addTrackingArea:trackingArea]; [self assert:1 equals:[[view trackingAreas] count] message:@"Adding the same tracking area multiple times should add it once"]; [self assert:view equals:[trackingArea view] message:@"Tracking area should be linked to view"]; - + var trackingArea2 = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow owner:self userInfo:nil]; // - + [view addTrackingArea:trackingArea2]; [self assert:2 equals:[[view trackingAreas] count] message:@"After adding a second tracking area"]; [self assert:view equals:[trackingArea2 view] message:@"Tracking area should be linked to view"]; // - + [view removeAllTrackingAreas]; [self assert:0 equals:[[view trackingAreas] count] message:@"After removing all tracking areas"]; [self assert:nil equals:[trackingArea view] message:@"Tracking area should be unlinked"]; [self assert:nil equals:[trackingArea2 view] message:@"Tracking area should be unlinked"]; // - + [view addTrackingArea:trackingArea]; - + var contentView = [window contentView]; [contentView addSubview:view]; [self assert:0 equals:updateTrackingAreasCalls message:@"Putting a view with a CPTrackingAreaInVisibleRect in a window should not call updateTrackingAreas"]; - + [view removeFromSuperview]; // - + [view addTrackingArea:trackingArea2]; [contentView addSubview:view]; [self assert:1 equals:updateTrackingAreasCalls message:@"Putting a view with a non CPTrackingAreaInVisibleRect in a window should call updateTrackingAreas"]; - + [view removeAllTrackingAreas]; - + // - + var viewTA = [[CPTrackingAreaView alloc] initWithFrame:CGRectMakeZero()]; updateTrackingAreasCalls = 0; @@ -966,17 +1063,17 @@ var updateTrackingAreasCalls, [self assert:1 equals:updateTrackingAreasCalls message:@"Putting a view with no tracking areas in a window should call updateTrackingAreas"]; // - + updateTrackingAreasCalls = 0; [viewTA addTrackingArea:trackingArea]; [viewTA setFrame:CGRectMake(10, 10, 10, 10)]; [self assert:0 equals:updateTrackingAreasCalls message:@"Changing geometry of a view with a CPTrackingAreaInVisibleRect should not call updateTrackingAreas"]; - + // - + updateTrackingAreasCalls = 0; - + [viewTA addTrackingArea:trackingArea2]; [viewTA setFrame:CGRectMake(20, 20, 20, 20)]; [self assert:1 equals:updateTrackingAreasCalls message:@"Changing geometry of a view with a non CPTrackingAreaInVisibleRect should call updateTrackingAreas"]; @@ -1048,7 +1145,7 @@ var updateTrackingAreasCalls, [viewTA removeAllTrackingAreas]; [viewTA addTrackingArea:trackingAreaAllWithDrag]; - + // Mouse enters the tracking area while dragging (option set) [self moveMouseAtPoint:CGPointMake(21, 21) dragging:YES]; @@ -1103,7 +1200,7 @@ var updateTrackingAreasCalls, [self assert:0 equals:mouseExitedCalls message:@"Mouse entering inner tracking area should not call mouseExited"]; [self assert:1 equals:mouseMovedCalls message:@"Mouse entering inner tracking area should call mouseMoved"]; [self assert:1 equals:cursorUpdateCalls message:@"Mouse entering inner tracking area should call cursorUpdate"]; - + // Mouse moves in inner view [self moveMouseAtPoint:CGPointMake(27, 27) dragging:NO]; @@ -1112,7 +1209,7 @@ var updateTrackingAreasCalls, [self assert:0 equals:mouseExitedCalls message:@"Mouse moving in inner tracking area should not call mouseExited"]; [self assert:2 equals:mouseMovedCalls message:@"Mouse moving in inner tracking area should call mouseMoved for both views"]; [self assert:0 equals:cursorUpdateCalls message:@"Mouse moving in inner tracking area should not call cursorUpdate"]; - + // Mouse leaves inner view but remains in outer view [self moveMouseAtPoint:CGPointMake(36, 36) dragging:NO]; @@ -1121,7 +1218,7 @@ var updateTrackingAreasCalls, [self assert:1 equals:mouseExitedCalls message:@"Mouse moving from inner to outer tracking area should call mouseExited (for inner)"]; [self assert:1 equals:mouseMovedCalls message:@"Mouse moving from inner to outer tracking area should call mouseMoved (for outer)"]; [self assert:1 equals:cursorUpdateCalls message:@"Mouse moving from inner to outer tracking area should call cursorUpdate (for outer)"]; - + [self assert:innerViewTA equals:involvedViewForMouseExited message:@"Inner view should receive mouseExited"]; [self assert:viewTA equals:involvedViewForCursorUpdate message:@"Outer view should receive cursorUpdate"]; @@ -1278,7 +1375,7 @@ var updateTrackingAreasCalls, [self mouseUpAtPoint:CGPointMake(10, 10)]; [self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 1.7 : cursor should be an arrow"]; - + // [self moveMouseAtPoint:CGPointMake(1, 1) dragging:NO]; @@ -1292,7 +1389,7 @@ var updateTrackingAreasCalls, [self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO]; [self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 2.1 : cursor should be an arrow"]; - + // Step 2.2 : inside the superview / outside the subview [self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO]; @@ -1310,7 +1407,7 @@ var updateTrackingAreasCalls, [self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO]; [self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 2.4 : cursor should be a crosshair"]; - + // Step 2.5 : outside the superview [self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO]; @@ -1355,14 +1452,14 @@ var updateTrackingAreasCalls, [self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO]; [self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 3.5 : cursor should be an arrow"]; - + } - (void)testTrackingAreasLiveViewHierarchyModification { // 1. viewB inside viewA with mouseEntered removing itself - var viewA = [[CPTrackingAreaViewWithCursorUpdate alloc] initWithFrame:CGRectMake(20, 20, 40, 40)] + var viewA = [[CPTrackingAreaViewWithCursorUpdate alloc] initWithFrame:CGRectMake(20, 20, 40, 40)], viewB = [[CPTrackingAreaViewLiveRemoval alloc] initWithFrame:CGRectMake(10, 10, 20, 20)]; [[window contentView] setSubviews:[CPArray arrayWithObject:viewA]]; @@ -1691,6 +1788,18 @@ var updateTrackingAreasCalls, [methodCalled addObject:string]; } +- (void)viewDidUnhide +{ + var string = _cmd + @"_" + [self identifier]; + [methodCalled addObject:string]; +} + +- (void)viewDidHide +{ + var string = _cmd + @"_" + [self identifier]; + [methodCalled addObject:string]; +} + - (BOOL)acceptsFirstResponder { return YES; From b773af96b8a3831440ff51758beb0eba7b85660f Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sat, 18 Jun 2016 13:40:14 +0200 Subject: [PATCH 2/4] FIXED : css display attribute was incorrectly set --- AppKit/CPView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index a142e82a9..3780f63b9 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1596,7 +1596,7 @@ var CPViewHighDPIDrawingEnabled = YES; #if PLATFORM(DOM) - _DOMElement.style.display = _isHidden ? "none" : "block"; + _DOMElement.style.display = aFlag ? "none" : "block"; #endif if (aFlag) From 82213393186de674ee1050103a1263bfb74e1e3b Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sat, 18 Jun 2016 13:40:27 +0200 Subject: [PATCH 3/4] Style --- AppKit/CPView.j | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 3780f63b9..abd703591 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -1593,8 +1593,6 @@ var CPViewHighDPIDrawingEnabled = YES; // FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE. // _DOMElement.style.visibility = (_isHidden = aFlag) ? "hidden" : "visible"; - - #if PLATFORM(DOM) _DOMElement.style.display = aFlag ? "none" : "block"; #endif @@ -1631,9 +1629,9 @@ var CPViewHighDPIDrawingEnabled = YES; - (void)_setSuperview:(CPView)aSuperview { var hasOldSuperview = (_superview !== nil), - hasNewSuperview = (aSuperview !== nil), - oldSuperviewIsHidden = hasOldSuperview && [_superview isHiddenOrHasHiddenAncestor], - newSuperviewIsHidden = hasNewSuperview && [aSuperview isHiddenOrHasHiddenAncestor]; + hasNewSuperview = (aSuperview !== nil), + oldSuperviewIsHidden = hasOldSuperview && [_superview isHiddenOrHasHiddenAncestor], + newSuperviewIsHidden = hasNewSuperview && [aSuperview isHiddenOrHasHiddenAncestor]; if (!newSuperviewIsHidden && oldSuperviewIsHidden) [self _recursiveLostHiddenAncestor]; From 5c1cdea3c6f8c5203e3e5e069fc9f404d077a817 Mon Sep 17 00:00:00 2001 From: daboe01 Date: Fri, 8 Jul 2016 21:34:14 +0200 Subject: [PATCH 4/4] Removed: Obsoleted Nativehost stuff --- AppKit/CPWindow/CPWindow.j | 3 +- CommonJS/lib/cappuccino/nativehost.js | 70 - .../UndoRedoWithMenuUpdate/AppController.j | 4 +- Tools/NativeHost/.gitignore | 5 - Tools/NativeHost/AppController+MainMenu.m | 33 - .../AppController+WebFrameLoadDelegate.m | 26 - .../AppController+WebPolicyDelegate.m | 35 - .../AppController+WebResourceLoadDelegate.m | 32 - .../NativeHost/AppController+WebUIDelegate.m | 71 - Tools/NativeHost/AppController.h | 54 - Tools/NativeHost/AppController.m | 221 --- Tools/NativeHost/Application.h | 18 - Tools/NativeHost/Application.m | 49 - Tools/NativeHost/BridgedMethods.h | 65 - Tools/NativeHost/BridgedMethods.m | 345 ----- Tools/NativeHost/Console.h | 21 - Tools/NativeHost/Console.m | 69 - .../English.lproj/InfoPlist.strings | Bin 92 -> 0 bytes Tools/NativeHost/English.lproj/MainMenu.cib | 1 - Tools/NativeHost/English.lproj/MainMenu.xib | 548 -------- Tools/NativeHost/Info.plist | 30 - Tools/NativeHost/Jakefile | 45 - Tools/NativeHost/MenuBridge.h | 22 - Tools/NativeHost/MenuBridge.m | 63 - Tools/NativeHost/MenuItemBridge.h | 24 - Tools/NativeHost/MenuItemBridge.m | 77 -- Tools/NativeHost/NSObject+WebAdditions.h | 16 - Tools/NativeHost/NSObject+WebAdditions.m | 19 - Tools/NativeHost/NSURL+Additions.h | 17 - Tools/NativeHost/NSURL+Additions.m | 36 - .../NativeHost.xcodeproj/TemplateIcon.icns | Bin 52318 -> 0 bytes .../NativeHost.xcodeproj/project.pbxproj | 424 ------ Tools/NativeHost/NativeHost_Prefix.pch | 8 - Tools/NativeHost/SSCrypto.h | 116 -- Tools/NativeHost/SSCrypto.m | 1214 ----------------- Tools/NativeHost/Server.h | 21 - Tools/NativeHost/Server.m | 193 --- Tools/NativeHost/WebPasteboardProxy.h | 19 - Tools/NativeHost/WebPasteboardProxy.m | 95 -- Tools/NativeHost/WebScripObject+Objective-J.h | 22 - Tools/NativeHost/WebScripObject+Objective-J.m | 46 - Tools/NativeHost/WebWindow.h | 44 - Tools/NativeHost/WebWindow.m | 515 ------- Tools/NativeHost/icon.icns | Bin 81151 -> 0 bytes Tools/NativeHost/main.m | 23 - .../Templates/NibApplication/Jakefile | 12 - 46 files changed, 3 insertions(+), 4768 deletions(-) delete mode 100644 CommonJS/lib/cappuccino/nativehost.js delete mode 100644 Tools/NativeHost/.gitignore delete mode 100644 Tools/NativeHost/AppController+MainMenu.m delete mode 100644 Tools/NativeHost/AppController+WebFrameLoadDelegate.m delete mode 100644 Tools/NativeHost/AppController+WebPolicyDelegate.m delete mode 100644 Tools/NativeHost/AppController+WebResourceLoadDelegate.m delete mode 100644 Tools/NativeHost/AppController+WebUIDelegate.m delete mode 100644 Tools/NativeHost/AppController.h delete mode 100644 Tools/NativeHost/AppController.m delete mode 100644 Tools/NativeHost/Application.h delete mode 100644 Tools/NativeHost/Application.m delete mode 100644 Tools/NativeHost/BridgedMethods.h delete mode 100644 Tools/NativeHost/BridgedMethods.m delete mode 100644 Tools/NativeHost/Console.h delete mode 100644 Tools/NativeHost/Console.m delete mode 100644 Tools/NativeHost/English.lproj/InfoPlist.strings delete mode 100644 Tools/NativeHost/English.lproj/MainMenu.cib delete mode 100644 Tools/NativeHost/English.lproj/MainMenu.xib delete mode 100644 Tools/NativeHost/Info.plist delete mode 100644 Tools/NativeHost/Jakefile delete mode 100644 Tools/NativeHost/MenuBridge.h delete mode 100644 Tools/NativeHost/MenuBridge.m delete mode 100644 Tools/NativeHost/MenuItemBridge.h delete mode 100644 Tools/NativeHost/MenuItemBridge.m delete mode 100644 Tools/NativeHost/NSObject+WebAdditions.h delete mode 100644 Tools/NativeHost/NSObject+WebAdditions.m delete mode 100644 Tools/NativeHost/NSURL+Additions.h delete mode 100644 Tools/NativeHost/NSURL+Additions.m delete mode 100644 Tools/NativeHost/NativeHost.xcodeproj/TemplateIcon.icns delete mode 100644 Tools/NativeHost/NativeHost.xcodeproj/project.pbxproj delete mode 100644 Tools/NativeHost/NativeHost_Prefix.pch delete mode 100644 Tools/NativeHost/SSCrypto.h delete mode 100644 Tools/NativeHost/SSCrypto.m delete mode 100644 Tools/NativeHost/Server.h delete mode 100644 Tools/NativeHost/Server.m delete mode 100644 Tools/NativeHost/WebPasteboardProxy.h delete mode 100644 Tools/NativeHost/WebPasteboardProxy.m delete mode 100644 Tools/NativeHost/WebScripObject+Objective-J.h delete mode 100644 Tools/NativeHost/WebScripObject+Objective-J.m delete mode 100644 Tools/NativeHost/WebWindow.h delete mode 100644 Tools/NativeHost/WebWindow.m delete mode 100644 Tools/NativeHost/icon.icns delete mode 100644 Tools/NativeHost/main.m diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 9c4880938..c9e8381aa 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -308,7 +308,7 @@ CPTexturedBackgroundWindowMask [self setPlatformWindow:[CPPlatformWindow primaryPlatformWindow]]; else { - // give zero sized borderless bridge windows a default size if we're not in the browser so they show up in NativeHost. + // give zero sized borderless bridge windows a default size. if ((aStyleMask & CPBorderlessBridgeWindowMask) && aContentRect.size.width === 0 && aContentRect.size.height === 0) { var visibleFrame = [[[CPScreen alloc] init] visibleFrame]; @@ -655,7 +655,6 @@ CPTexturedBackgroundWindowMask CPBorderlessWindowMask CPTitledWindowMask CPClosableWindowMask - CPMiniaturizableWindowMask (NOTE: only available in NativeHost) CPResizableWindowMask CPTexturedBackgroundWindowMask CPBorderlessBridgeWindowMask diff --git a/CommonJS/lib/cappuccino/nativehost.js b/CommonJS/lib/cappuccino/nativehost.js deleted file mode 100644 index 8def87642..000000000 --- a/CommonJS/lib/cappuccino/nativehost.js +++ /dev/null @@ -1,70 +0,0 @@ -var FILE = require("file"); -var OS = require("os"); - -var NATIVEHOST_SOURCE = FILE.path(module.path).dirname().dirname().dirname().join("support", "NativeHost.app"); - -exports.buildNativeHost = function(rootPath, buildNative, options) { - options = options || {}; - options.index = options.index || "index.html"; - - rootPath = FILE.path(rootPath); - buildNative = FILE.path(buildNative); - - if (buildNative.exists()) - buildNative.rmtree(); - - buildNative.dirname().mkdirs(); - // FIXME: Narwhal doesn't preserve permissions - // FILE.copyTree(NATIVEHOST_SOURCE, buildNative); - OS.system(["cp", "-r", NATIVEHOST_SOURCE, buildNative]); - FILE.chmod(buildNative.join("Contents", "MacOS", "NativeHost"), 0755); - - var rootBaseName = rootPath.basename(); - var buildClientDirectory = buildNative.join("Contents", "Resources", rootBaseName); - - FILE.mkdirs(FILE.dirname(buildClientDirectory)); - // FILE.copyTree(rootPath, buildClientDirectory); - OS.system(["cp", "-r", rootPath, buildClientDirectory]); - - var defaultBundleName = buildNative.basename().match(/^(.*)(\.app)?$/)[1]; - - function mergePlist(plist, path) { - var otherPlist = CFPropertyList.readPropertyListFromFile(String(path)); - - otherPlist.keys().forEach(function(key) { - var value = otherPlist.valueForKey(key); - plist.setValueForKey(key, value); - - if (key === "CPBundleName") - plist.setValueForKey("CFBundleName", value); - - if (key === "CFBundleIconFile") { - var iconPath = rootPath.join("Resources", value); - if (iconPath.isFile()) - iconPath.copy(buildNative.join("Contents", "Resources", value)); - else - print("Warning: CFBundleIconFile references " + value + " but does not exist in the resources directory."); - } - - if (key === "CFBundleExecutable") { - buildNative.join("Contents", "MacOS", "NativeHost").rename(value); - // FIXME: - FILE.chmod(buildNative.join("Contents", "MacOS", value), 0755); - } - }); - } - - CFPropertyList.modifyPlist(buildNative.join("Contents", "Info.plist"), function(plist) { - - plist.setValueForKey("CFBundleName", defaultBundleName); - plist.setValueForKey("NHInitialResource", FILE.join(rootBaseName, options.index)); - - // merge Cappuccino plist - var cappPlistPath = rootPath.join("Info.plist"); - if (cappPlistPath.isFile()) - mergePlist(plist, cappPlistPath); - - if (options.extraPlistPath) - mergePlist(plist, options.extraPlistPath); - }); -} diff --git a/Tests/Manual/UndoRedoWithMenuUpdate/AppController.j b/Tests/Manual/UndoRedoWithMenuUpdate/AppController.j index 8eb717751..a7df34795 100644 --- a/Tests/Manual/UndoRedoWithMenuUpdate/AppController.j +++ b/Tests/Manual/UndoRedoWithMenuUpdate/AppController.j @@ -142,7 +142,7 @@ [_menuItemView setDirty]; } -// Performs autoenable processing, returns isEnabled to propagate state to NativeHost +// Performs autoenable processing, returns isEnabled to propagate state - (BOOL)_performAutoenable { if ([_menu autoenablesItems]) @@ -162,7 +162,7 @@ } else { - // XXX: will toggle state as part of _target check, required to sync stane with NativeHost + // XXX: will toggle state as part of _target check _isEnabled = isEnabled; [_menuItemView setDirty]; diff --git a/Tools/NativeHost/.gitignore b/Tools/NativeHost/.gitignore deleted file mode 100644 index f921bd442..000000000 --- a/Tools/NativeHost/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -*.mode1v3 -*.pbxuser -*.perspectivev3 -build diff --git a/Tools/NativeHost/AppController+MainMenu.m b/Tools/NativeHost/AppController+MainMenu.m deleted file mode 100644 index dbc98e63e..000000000 --- a/Tools/NativeHost/AppController+MainMenu.m +++ /dev/null @@ -1,33 +0,0 @@ -// -// AppController+MainMenu.m -// NativeHost -// -// Created by Francisco Tolmasky on 9/2/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - -#import "MenuBridge.h" -#import "AppController.h" - - -@interface NSApplication (MenuMethods) - -- (void)setAppleMenu:(NSMenu *)aMenu; - -@end - -@implementation AppController (MainMenu) - -- (void)setMainMenuObject:(WebScriptObject *)aMenuObject -{ - NSMenu * mainMenu = [[MenuBridge alloc] initWithMenuObject:aMenuObject]; - - [NSApp setAppleMenu:[[mainMenu itemArray] objectAtIndex:0]]; - [NSApp setMainMenu:mainMenu]; - - [mainMenu release]; -} - -@end diff --git a/Tools/NativeHost/AppController+WebFrameLoadDelegate.m b/Tools/NativeHost/AppController+WebFrameLoadDelegate.m deleted file mode 100644 index fdce4d601..000000000 --- a/Tools/NativeHost/AppController+WebFrameLoadDelegate.m +++ /dev/null @@ -1,26 +0,0 @@ - - -// -// AppController+WebFrameLoadDelegate.m -// NativeHost -// -// Created by Francisco Tolmasky on 7/28/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "AppController.h" - -#import "BridgedMethods.h" - - -@implementation AppController (WebFrameLoadDelegate) - -- (void)webView:(WebView *)aWebView didClearWindowObject:(WebScriptObject *)aWindowObject forFrame:(WebFrame *)aFrame -{ - if (aWebView == webView) - [GlobalMethods enhanceWindowObject:aWindowObject ofWebView:aWebView]; - else - [WindowMethods enhanceWindowObject:aWindowObject ofWebView:aWebView]; -} - -@end diff --git a/Tools/NativeHost/AppController+WebPolicyDelegate.m b/Tools/NativeHost/AppController+WebPolicyDelegate.m deleted file mode 100644 index 2c098dcd0..000000000 --- a/Tools/NativeHost/AppController+WebPolicyDelegate.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// AppController+WebPolicyDelegate.m -// NativeHost -// -// Created by Francisco Tolmasky on 5/11/10. -// Copyright 2010 280 North, Inc. All rights reserved. -// - -#import "NSURL+Additions.h" -#import "AppController.h" - - -@implementation AppController (WebPolicyDelegate) - -- (void)webView:(WebView *)aWebView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)aRequest newFrameName:(NSString *)aFrameName decisionListener:(id /*< WebPolicyDecisionListener >*/)aListener -{ - [[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]]; - [aListener ignore]; -} - -- (void)webView:(WebView *)aWebView decidePolicyForNavigationAction:(NSDictionary *)aDictionary request:(NSURLRequest *)aRequest frame:(WebFrame *)aWebFrame decisionListener:(id /**/)aDecisionListener -{ - NSURL * requestURL = [aRequest URL]; - - if([aWebView mainFrame] != aWebFrame || - [[baseURL scheme] isEqualTo:[requestURL scheme]] && - ![baseURL host] || [[baseURL host] isEqualTo:[requestURL host]] && - ![baseURL port] || [[baseURL port] isEqualTo:[requestURL port]]) - return [aDecisionListener use]; - - [[NSWorkspace sharedWorkspace] openURL:[aDictionary objectForKey:WebActionOriginalURLKey]]; - [aDecisionListener ignore]; -} - -@end diff --git a/Tools/NativeHost/AppController+WebResourceLoadDelegate.m b/Tools/NativeHost/AppController+WebResourceLoadDelegate.m deleted file mode 100644 index a60540b75..000000000 --- a/Tools/NativeHost/AppController+WebResourceLoadDelegate.m +++ /dev/null @@ -1,32 +0,0 @@ -// -// AppController+WebResourceLoadDelegate.m -// NativeHost -// -// Created by Francisco Tolmasky on 7/28/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "AppController.h" -#import "SSCrypto.h" - -NSString *authHeader = nil; - -@implementation AppController (WebResourceLoadDelegate) - -- (NSURLRequest *)webView:(WebView *)aSender resource:(id)anIdentifier willSendRequest:(NSURLRequest *)aRequest redirectResponse:(NSURLResponse *)aRedirectResponse fromDataSource:(WebDataSource *)aDataSource -{ - aRequest = [[aRequest mutableCopy] autorelease]; - - if (!authHeader) - { - NSString *plaintext = [NSString stringWithFormat:@"%@:%@", SERVER_USER, SERVER_PASSWORD]; - NSData *data = [plaintext dataUsingEncoding:NSASCIIStringEncoding]; - authHeader = [[NSString alloc] initWithFormat:@"Basic %@", [data encodeBase64WithNewlines:NO]]; - } - - [(NSMutableURLRequest *)aRequest setValue:authHeader forHTTPHeaderField:@"Authorization"]; - - return aRequest; -} - -@end diff --git a/Tools/NativeHost/AppController+WebUIDelegate.m b/Tools/NativeHost/AppController+WebUIDelegate.m deleted file mode 100644 index a75f9d6a9..000000000 --- a/Tools/NativeHost/AppController+WebUIDelegate.m +++ /dev/null @@ -1,71 +0,0 @@ -// -// AppController+WebUIDelegate.m -// NativeHost -// -// Created by Francisco Tolmasky on 7/28/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "AppController.h" -#import "WebWindow.h" - - -@implementation AppController (WebUIDelegate) - -- (void)webView:(WebView *)aWebView setFrame:(NSRect)aFrame -{ - [[aWebView window] setFrame:aFrame display:YES]; -} - -- (NSRect)webViewFrame:(WebView *)aWebView -{ - return [[aWebView window] frame]; -} - -- (WebView *)webView:(WebView *)aWebView createWebViewWithRequest:(NSURLRequest *)aRequest -{ - return [[WebWindow webWindow] webView]; -} - -- (void)webViewClose:(WebView *)aWebView -{ - // Important to call close and not: - // -performClose:, which beeps without the presence of a close button. - // -orderOut:, which doesn't release the window. - [[aWebView window] close]; - //[[aWebView window] orderOut:self]; -} - -- (void)webViewShow:(WebView *)aWebView -{ - [[aWebView window] makeKeyAndOrderFront:self]; -} - -- (NSAttributedString *)loggedOutput; -{ - return loggedOutput; -} - -- (void)webView:(WebView *)aWebView addMessageToConsole:(NSDictionary *)aDictionary -{ - NSString * message = [aDictionary objectForKey:@"message"]; - NSAttributedString * attributedString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n", message, nil]]; - - [loggedOutput appendAttributedString:attributedString]; - - [attributedString release]; - NHLog(@"CONSOLE", message); -} - -- (void)webView:(WebView *)aSender runJavaScriptAlertPanelWithMessage:(NSString *)aMessage initiatedByFrame:(WebFrame *)aFrame -{ - WebDataSource * dataSource = [aFrame dataSource]; - NSString * title = [dataSource pageTitle]; - - if (![title length]) - title = [[[dataSource request] URL] absoluteString]; - - [[NSAlert alertWithMessageText:title defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", aMessage, nil] runModal]; -} - -@end diff --git a/Tools/NativeHost/AppController.h b/Tools/NativeHost/AppController.h deleted file mode 100644 index 69e1d2358..000000000 --- a/Tools/NativeHost/AppController.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// AppController.h -// NativeHost -// -// Created by Francisco Tolmasky on 6/4/09. -// Copyright 2009 280 North, Inc. All rights reserved. -// - -#import - -extern int SERVER_PORT; -extern NSString *SERVER_PASSWORD; -extern NSString *SERVER_USER; - -@class Server; -@class WebScriptObject; - -@interface AppController : NSObject -{ - NSWindow * webViewWindow; - WebView * webView; - - NSMutableArray * openingFilenames; - NSMutableArray * openingURLStrings; - - Server * server; - NSFileHandle * stdinFileHandle; - - NSMutableAttributedString * loggedOutput; - - NSURL * baseURL; -} - -- (void)configureLocalStorage; -- (NSURL *)baseURL; - -- (void)startServer; -- (void)startCappuccinoApplication; - -- (NSArray *)openingURLStrings; - -- (NSView *)keyView; -- (WebView *)webView; -- (WebScriptObject *)windowScriptObject; - -@end - -@interface AppController (MainMenu) - -- (void)setMainMenuObject:(WebScriptObject *)aMenuObject; - -@end - -void NHLog(NSString *type, NSString *message); \ No newline at end of file diff --git a/Tools/NativeHost/AppController.m b/Tools/NativeHost/AppController.m deleted file mode 100644 index fa64a749d..000000000 --- a/Tools/NativeHost/AppController.m +++ /dev/null @@ -1,221 +0,0 @@ -// -// AppController.m -// NativeHost -// -// Created by Francisco Tolmasky on 6/4/09. -// Copyright 2009 280 North, Inc. All rights reserved. -// - -#import "Console.h" -#import "Server.h" -#import "AppController.h" -#import "NSURL+Additions.h" -#import "BridgedMethods.h" -#import "WebWindow.h" -#import "WebScripObject+Objective-J.h" - -extern int interactive; - -int SERVER_PORT = 9191; -NSString *SERVER_PASSWORD = nil; -NSString *SERVER_USER = nil; - - -@implementation AppController - -- (id)init -{ - self = [super init]; - - if (self) - openingURLStrings = [NSMutableArray new]; - - return self; -} - -- (void)dealloc -{ - [webView release]; - [webViewWindow release]; - - [openingURLStrings release]; - - [super dealloc]; -} - -- (BOOL)application:(NSApplication *)anApplication openFile:(NSString *)aFilename -{ - id canOpenFilesImmediately = [[webView windowScriptObject] evaluateWebScript:@"CPApp && CPApp._finishedLaunching"]; - - NSString *path = [[[NSURL fileURLWithPath:aFilename] HTTPFileSystemURL] absoluteString]; - if ([canOpenFilesImmediately isKindOfClass:[NSNumber class]] && [canOpenFilesImmediately boolValue]) - [[webView windowScriptObject] evaluateObjectiveJ:[NSString stringWithFormat:@"[CPApp _openURL:[CPURL URLWithString:\"%@\"]]", path]]; - else - [openingURLStrings addObject:path]; - - return NO; -} - -- (void)applicationWillFinishLaunching:(NSNotification *)aNotification -{ - NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; - - [defaults registerDefaults:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"WebKitDeveloperExtras"]]; - - [self startServer]; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)notification -{ - [self startCappuccinoApplication]; -} - -- (void)applicationDidResignActive:(NSNotification *)aNotification -{ - // FIXME: handle this better. - [[self windowScriptObject] evaluateObjectiveJ:@"[CPApp _willResignActive];"]; - [[self windowScriptObject] evaluateObjectiveJ:@"CPApp._isActive = NO;"]; - [[self windowScriptObject] evaluateObjectiveJ:@"[CPApp _didResignActive];"]; -} - -- (void)applicationDidBecomeActive:(NSNotification *)aNotification -{ - // FIXME: handle this better. - [[self windowScriptObject] evaluateObjectiveJ:@"[CPApp _willBecomeActive];"]; - [[self windowScriptObject] evaluateObjectiveJ:@"CPApp._isActive = YES;"]; - [[self windowScriptObject] evaluateObjectiveJ:@"[CPApp _didBecomeActive];"]; -} - -- (NSArray *)openingURLStrings -{ - return openingURLStrings; -} - -- (NSView *)keyView -{ - return [[[webView mainFrame] frameView] documentView]; -} - -- (WebView *)webView -{ - return webView; -} - -- (WebScriptObject *)windowScriptObject -{ - return [webView windowScriptObject]; -} - -- (void)startServer -{ - server = [[Server alloc] init]; - - if (![server start]) - exit(0); - - if (interactive) - { - stdinFileHandle = [[NSFileHandle fileHandleWithStandardInput] retain]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(didReadStdin:) - name:NSFileHandleReadCompletionNotification - object:stdinFileHandle]; - - fprintf(stdout, "objj> "); - fflush(stdout); - [stdinFileHandle readInBackgroundAndNotify]; - } -} - -- (void)didReadStdin:(NSNotification *)aNotification -{ - NSString *string = [[NSString alloc] initWithData:[[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem] encoding:NSASCIIStringEncoding]; - NSString *result = [[self windowScriptObject] evaluateObjectiveJReturningString:string]; - [string release]; - if ([result respondsToSelector:@selector(UTF8String)]) - fprintf(stdout, "%s\n", [result UTF8String]); - fprintf(stdout, "objj> "); - fflush(stdout); - [stdinFileHandle readInBackgroundAndNotify]; -} - -- (NSURL *)baseURL -{ - return baseURL; -} - -- (void)startCappuccinoApplication -{ - NSString *initialURL = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NHInitialURL"]; - BOOL prependServer = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NHInitialURLPrependServer"] boolValue]; - - if (!initialURL) - { - NSString *initialResource = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NHInitialResource"]; - - if (!initialResource) - initialResource = @"Application/index.html"; - - initialURL = [[NSString stringWithFormat:@"file://%@/%@", [[NSBundle mainBundle] resourcePath], initialResource] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - baseURL = [[NSURL alloc] initWithString:@"file:///"]; - } - else if (prependServer) - { - initialURL = [NSString stringWithFormat:@"http://127.0.0.1:%d/%@", SERVER_PORT, initialURL]; - baseURL = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"http://127.0.0.1:%d/", SERVER_PORT]]; - } - - NHLog(@"STARTUP", [initialURL description]); - - [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:initialURL]]]; -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification -{ - [server stop]; -} - -- (void)configureLocalStorage -{ - WebPreferences *webConfiguration = [WebPreferences standardPreferences]; - NSBundle *mainBundle = [NSBundle mainBundle]; - NSString *cappBundleName = [mainBundle objectForInfoDictionaryKey:@"CPBundleName"]; - NSString *applicationSupportFile = [@"~/Library/Application Support/" stringByExpandingTildeInPath]; - NSString *savePath = [NSString pathWithComponents:[NSArray arrayWithObjects:applicationSupportFile, cappBundleName, @"LocalStorage", nil]]; - - if ([webConfiguration respondsToSelector:@selector(setLocalStorageDatabasePath:)]) - [webConfiguration setLocalStorageDatabasePath:savePath]; - else - [webConfiguration _setLocalStorageDatabasePath:savePath]; - - [webView setPreferences:webConfiguration]; -} - -- (void)awakeFromNib -{ - webView = [[WebView alloc] init]; - - [webView setUIDelegate:self]; - [webView setFrameLoadDelegate:self]; - [webView setResourceLoadDelegate:self]; - [webView setPolicyDelegate:self]; - - [self configureLocalStorage]; - - webViewWindow = [[NSWindow alloc] init]; - - [webViewWindow setContentView:webView]; -} - -@end - -void NHLog(NSString *type, NSString *message) -{ - NSArray *lines = [message componentsSeparatedByString:@"\n"]; - for (NSString *line in lines) - { - if ([line length] > 0) - NSLog(@"%10@: %@", type, line); - } -} diff --git a/Tools/NativeHost/Application.h b/Tools/NativeHost/Application.h deleted file mode 100644 index d09086a9f..000000000 --- a/Tools/NativeHost/Application.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Application.h -// NativeHost -// -// Created by Francisco Tolmasky on 10/8/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -@interface Application : NSApplication -{ -} - -- (void)_reallyTerminate:(id)sender; - -@end diff --git a/Tools/NativeHost/Application.m b/Tools/NativeHost/Application.m deleted file mode 100644 index 2234f307d..000000000 --- a/Tools/NativeHost/Application.m +++ /dev/null @@ -1,49 +0,0 @@ -// -// Application.m -// NativeHost -// -// Created by Francisco Tolmasky on 10/8/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "Application.h" -#import "AppController.h" -#import "WebScripObject+Objective-J.h" -#import "WebWindow.h" - -@implementation Application - -- (void)sendEvent:(NSEvent *)anEvent -{ - [WebWindow enableAllWindows]; - - NSWindow * window = [anEvent window]; - - if (!window || [window isKindOfClass:[WebWindow class]]) - { - NSResponder * firstResponder = window ? [window firstResponder] : [(AppController *)[self delegate] keyView]; - - switch ([anEvent type]) - { - case NSKeyDown: return [firstResponder keyDown:anEvent]; - case NSKeyUp: return [firstResponder keyUp:anEvent]; - } - } - - [super sendEvent:anEvent]; -} - -- (void)terminate:(id)sender -{ - if ([[[self delegate] windowScriptObject] evaluateObjectiveJ:@"(CPApp)"] == [WebUndefined undefined]) - [self _reallyTerminate:sender]; - else - [[(AppController *)[self delegate] windowScriptObject] evaluateObjectiveJ:@"[CPApp terminate:nil]"]; -} - -- (void)_reallyTerminate:(id)sender -{ - [super terminate:sender]; -} - -@end diff --git a/Tools/NativeHost/BridgedMethods.h b/Tools/NativeHost/BridgedMethods.h deleted file mode 100644 index a9af18f1f..000000000 --- a/Tools/NativeHost/BridgedMethods.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// BridgedMethods.h -// NativeHost -// -// Created by Francisco Tolmasky on 10/16/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -@interface BridgedMethods : NSObject -{ - WebView * webView; -} -+ (NSMutableArray *)arrayFromWebScriptObject:(WebScriptObject *)incomingObject; -+ (void)enhanceWindowObject:(WebScriptObject *)aWindowObject ofWebView:(WebView *)aWebView; -@end - -@interface GlobalMethods : BridgedMethods -{ -} -- (id)isDesktop; - -- (id)openingURLStrings; - -- (id)setMainMenu:(id)arguments; - -- (id)terminate; -- (id)activateIgnoringOtherApps:(NSArray *)arguments; -- (id)deactivate; -- (id)hide; -- (id)hideOtherApplications; - -- (id)savePanel:(NSArray *)arguments; // FIXME: This should be implemented in Cappuccino. -- (id)openPanel; // FIXME: This should be implemented in Cappuccino. - -- (id)clearRecentDocuments; -- (id)noteNewRecentDocumentPath:(NSArray *)aURL; -- (id)recentDocumentURLs; - -- (id)pasteboardWithName:(NSArray *)arguments; - -@end - -@interface WindowMethods : BridgedMethods -{ -} -- (id)miniaturize; -- (id)deminiaturize; - -- (id)level; -- (id)setLevel:(NSArray *)arguments; - -- (id)hasShadow; -- (id)setHasShadow:(NSArray *)arguments; - -- (id)shadowStyle; -- (id)setShadowStyle:(NSArray *)arguments; - -- (id)frame; -- (id)setFrame:(NSArray *)arguments; - -@end - diff --git a/Tools/NativeHost/BridgedMethods.m b/Tools/NativeHost/BridgedMethods.m deleted file mode 100644 index 7e637692a..000000000 --- a/Tools/NativeHost/BridgedMethods.m +++ /dev/null @@ -1,345 +0,0 @@ -// -// BridgedMethods.m -// NativeHost -// -// Created by Francisco Tolmasky on 10/16/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - - -#import -#import "Application.h" -#import "AppController.h" -#import "BridgedMethods.h" -#import "NSObject+WebAdditions.h" -#import "NSURL+Additions.h" -#import "WebWindow.h" -#import "WebPasteboardProxy.h" - -static NSMutableDictionary * MethodClasses; - -@implementation GlobalMethods - -- (id)isDesktop -{ - return [NSNumber numberWithBool:YES]; -} - -- (id)openingURLStrings -{ - return [(AppController *)[NSApp delegate] openingURLStrings]; -} - -- (id)setMainMenu:(id)arguments -{ - [[NSApp delegate] setMainMenuObject:[arguments objectAtIndex:0]]; - - return [WebUndefined undefined]; -} - -- (id)terminate -{ - [(Application *)NSApp _reallyTerminate:self]; - - return [WebUndefined undefined]; -} - -- (id)activateIgnoringOtherApps:(NSArray *)arguments -{ - id argument = [arguments objectAtIndex:0]; - - [(NSApplication *)NSApp activateIgnoringOtherApps:[argument isKindOfClass:[NSNumber class]] && [(NSNumber *)argument boolValue]]; - - return [WebUndefined undefined]; -} - -- (id)deactivate -{ - [(NSApplication *)NSApp deactivate]; - return [WebUndefined undefined]; -} - -- (id)hide -{ - [NSApp hide:self]; - return [WebUndefined undefined]; -} - -- (id)hideOtherApplications -{ - [NSApp hideOtherApplications:self]; - return [WebUndefined undefined]; -} - -- (id)openPanel -{ - NSOpenPanel * openPanel = [NSOpenPanel openPanel]; - - NSInteger result = [openPanel runModal]; - - NSMutableString * resultObject = [NSMutableString stringWithFormat:@"({ button:%d, URLs:", result]; - - NSMutableArray * fileSystemURLs = [NSMutableArray array]; - - for (NSURL * URL in [openPanel URLs]) - [fileSystemURLs addObject:[URL HTTPFileSystemURL]]; - - if (result == NSFileHandlingPanelOKButton) - [resultObject appendString:[NSString stringWithFormat:@"[\"%@\"] })", [fileSystemURLs componentsJoinedByString:@"\", \""]]]; - - else - [resultObject appendString:@"[] })"]; - - return [[webView windowScriptObject] evaluateWebScript:resultObject]; -} - -- (id)savePanel:(NSArray *)arguments -{ - NSSavePanel * savePanel = [NSSavePanel savePanel]; - WebScriptObject *args = [arguments objectAtIndex:0]; - - [savePanel setAllowedFileTypes:[BridgedMethods arrayFromWebScriptObject:[args valueForKey:@"allowedFileTypes"]]]; - - id allowsOtherFileTypes = [args valueForKey:@"allowsOtherFileTypes"]; - - [savePanel setAllowsOtherFileTypes:allowsOtherFileTypes && [allowsOtherFileTypes webBoolValue]]; - - id isExtensionHidden = [args valueForKey:@"isExtensionHidden"]; - - [savePanel setExtensionHidden:isExtensionHidden && [isExtensionHidden webBoolValue]]; - - id canSelectHiddenExtension = [args valueForKey:@"canSelectHiddenExtension"]; - - [savePanel setCanSelectHiddenExtension:canSelectHiddenExtension && canSelectHiddenExtension]; - - id canCreateDirectories = [args valueForKey:@"canCreateDirectories"]; - - [savePanel setCanCreateDirectories:canCreateDirectories && [canCreateDirectories webBoolValue]]; - - NSInteger result = [savePanel runModal]; - - return [[webView windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"({ button:%d, URL:\"%@\" })", result, [[[savePanel URL] HTTPFileSystemURL] absoluteString]]]; -} - -- (id)clearRecentDocuments -{ - [[NSDocumentController sharedDocumentController] clearRecentDocuments:self]; - return [WebUndefined undefined]; -} - -- (id)noteNewRecentDocumentPath:(NSArray *)arguments -{ - if (![arguments count]) - return [WebUndefined undefined]; - - NSString *aURL = [arguments objectAtIndex:0]; - NSURL *fileURL = [NSURL fileSystemURLFromHTTPFileSystemString:aURL]; - - [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:fileURL]; - - return [WebUndefined undefined]; -} - -- (id)recentDocumentURLs -{ - NSArray *existingURLs = [[NSDocumentController sharedDocumentController] recentDocumentURLs]; - NSMutableArray *urlsAsStrings = [NSMutableArray array]; - - for (int i=0, count = [existingURLs count]; i < count; i++) - [urlsAsStrings addObject:[[existingURLs objectAtIndex:i] absoluteString]]; - - return urlsAsStrings; -} - -- (id)pasteboardWithName:(NSArray *)arguments -{ - if (![arguments count]) - return [WebUndefined undefined]; - - return [WebPasteboardProxy pasteboardWithName:[arguments objectAtIndex:0]]; -} - -@end - -@implementation WindowMethods - -- (id)miniaturize -{ - [[webView window] miniaturize:nil]; - return [WebUndefined undefined]; -} - -- (id)deminiaturize -{ - [[webView window] deminiaturize:nil]; - return [WebUndefined undefined]; -} - -- (id)level -{ - return [NSNumber numberWithInt:[[webView window] level]]; -} - -- (id)setLevel:(NSArray *)arguments -{ - [[webView window] setLevel:[[arguments objectAtIndex:0] intValue]]; - - return [WebUndefined undefined]; -} - -- (id)hasShadow -{ - return [NSNumber numberWithBool:[[webView window] hasShadow]]; -} - -- (id)setHasShadow:(NSArray *)arguments -{ - [[webView window] setHasShadow:[[arguments objectAtIndex:0] boolValue]]; - - return [WebUndefined undefined]; -} - -- (id)frame -{ - NSRect frame = [[webView window] frame]; - - return [[webView windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"({ origin:{%f, %f}, size:{%f, %f}})", NSMinX(frame), NSMinY(frame), NSWidth(frame), NSHeight(frame)]]; -} - -- (id)setFrame:(NSArray *)arguments -{ - id origin = [[arguments objectAtIndex:0] valueForKey:@"origin"], - size = [[arguments objectAtIndex:0] valueForKey:@"size"]; - - NSWindow * window = [webView window]; - NSScreen * screen = [window screen]; - - if (!screen) - screen = [NSScreen mainScreen]; // Is this correct? - - float height = [[size valueForKey:@"height"] floatValue]; - - [[webView window] setFrame:NSMakeRect([[origin valueForKey:@"x"] floatValue], NSMaxY([screen frame]) - [[origin valueForKey:@"y"] floatValue] - height, [[size valueForKey:@"width"] floatValue], height) display:YES]; - /* - NSLog([webView description]); - NSLog(@"%@ %@", [window screen], NSStringFromRect([window frame])); - NSLog(@"%f - %f - %f = %f", NSMaxY([[window screen] frame]), [[origin valueForKey:@"y"] floatValue], height, NSMaxY([[window screen] frame]) - [[origin valueForKey:@"y"] floatValue] - height); - NSLog(@"FROM: %@", NSStringFromRect(NSMakeRect([[origin valueForKey:@"x"] floatValue], [[origin valueForKey:@"y"] floatValue], [[size valueForKey:@"width"] floatValue], height))); - NSLog(@" TO: %@", NSStringFromRect([[webView window] frame])); - */ - - return [WebUndefined undefined]; -} - -- (id)shadowStyle -{ - WebWindow * window = (WebWindow *)[webView window]; - - return [NSNumber numberWithInt:[window shadowStyle]]; -} - -- (id)setShadowStyle:(id)arguments -{ - int type = [[arguments objectAtIndex:0] intValue]; - - WebWindow * window = (WebWindow *)[webView window]; - - [window setShadowStyle:type]; - - return [WebUndefined undefined]; -} - -@end - - -@interface WindowScriptObjectMethod : NSObject -{ - WebView * webView; -} - -- (id)initWithWebView:(WebView *)aWebView; - -@end - -@implementation WindowScriptObjectMethod - -- (id)initWithWebView:(WebView *)aWebView -{ - self = [super init]; - - if (self) - webView = aWebView; - - return self; -} - -@end - -@implementation BridgedMethods - -+ (NSMutableArray *)arrayFromWebScriptObject:(WebScriptObject *)incomingObject -{ - if (!incomingObject) - return nil; - - NSMutableArray * newItems = [[NSMutableArray alloc] init]; - - for (int i=0; [incomingObject webScriptValueAtIndex:i]!=[WebUndefined undefined]; i++) - { - id oneItem =[incomingObject webScriptValueAtIndex:i]; - [newItems addObject:oneItem]; - } - - return [newItems autorelease]; -} - -+ (void)enhanceWindowObject:(WebScriptObject *)aWindowObject ofWebView:(WebView *)aWebView -{ - NSDictionary * classMethods = [MethodClasses objectForKey:[self className]]; - NSString * key = nil; - NSEnumerator * keyEnumerator = [classMethods keyEnumerator]; - - while (key = [keyEnumerator nextObject]) - [aWindowObject setValue:[(WindowScriptObjectMethod *)[[[classMethods objectForKey:key] alloc] initWithWebView:aWebView] autorelease] forKey:key]; -} - -+ (void)bridgeMethod:(Method)aMethod dictionary:(NSMutableDictionary *)aDictionary -{ - NSString * methodName = NSStringFromSelector(method_getName(aMethod)), - * publicMethodName = [NSString stringWithFormat:@"cp%@", [[NSString stringWithFormat:@"%@%@", [[methodName substringToIndex:1] uppercaseString], [methodName substringFromIndex:1]] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]]; - - Class methodClass = objc_allocateClassPair([WindowScriptObjectMethod class], [[NSString stringWithFormat:@"WebScriptObjectMethod_%@", publicMethodName] cString], 0); - - class_addMethod(methodClass, @selector(invokeDefaultMethodWithArguments:), method_getImplementation(aMethod), "@@:@"); - - objc_registerClassPair(methodClass); - - [aDictionary setObject:methodClass forKey:publicMethodName]; -} - -+ (void)initialize -{ - if (!MethodClasses) - MethodClasses = [[NSMutableDictionary alloc] init]; - - NSMutableDictionary * dictionary = [[NSMutableDictionary alloc] init]; - - [MethodClasses setObject:dictionary forKey:[self className]]; - [dictionary release]; - - unsigned int methodCount = 0; - Method * methods = class_copyMethodList(self, &methodCount); - - if (!methods) - return; - - int index = 0; - - for (; index < methodCount; ++index) - [self bridgeMethod:methods[index] dictionary:dictionary]; - - free(methods); - methods = NULL; -} - -@end diff --git a/Tools/NativeHost/Console.h b/Tools/NativeHost/Console.h deleted file mode 100644 index a4d9b6c42..000000000 --- a/Tools/NativeHost/Console.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Console.h -// NativeHost -// -// Created by Francisco Tolmasky on 6/16/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -@interface Console : NSObject -{ - NSMutableAttributedString * contents; -} - -+ (id)sharedConsole; - -- (NSAttributedString *)contents; - -@end diff --git a/Tools/NativeHost/Console.m b/Tools/NativeHost/Console.m deleted file mode 100644 index 2118f999b..000000000 --- a/Tools/NativeHost/Console.m +++ /dev/null @@ -1,69 +0,0 @@ -// -// Console.m -// NativeHost -// -// Created by Francisco Tolmasky on 6/16/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "Console.h" - -#import "AppController.h" - - -@implementation Console - -+ (id)sharedConsole -{ - static Console * console = nil; - - if (!console) - console = [[Console alloc] init]; - - return console; -} - -- (id)init -{ - self = [super init]; - - if (self) - contents = [[NSMutableAttributedString alloc] init]; - - return self; -} - -- (void)dealloc -{ - [contents release]; - [super dealloc]; -} - -- (NSAttributedString *)contents -{ - return contents; -} - -- (void)webView:(WebView *)aWebView addMessageToConsole:(NSDictionary *)aDictionary -{ - NSString * message = [aDictionary objectForKey:@"message"]; - - NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n", message, nil]]; - [contents appendAttributedString:attrString]; - [attrString release]; - - NHLog(@"CONSOLE", message); -} - -- (void)webView:(WebView *)aSender runJavaScriptAlertPanelWithMessage:(NSString *)aMessage initiatedByFrame:(WebFrame *)aFrame -{ - WebDataSource * dataSource = [aFrame dataSource]; - NSString * title = [dataSource pageTitle]; - - if (![title length]) - title = [[[dataSource request] URL] absoluteString]; - - [[NSAlert alertWithMessageText:title defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:aMessage, nil] runModal]; -} - -@end diff --git a/Tools/NativeHost/English.lproj/InfoPlist.strings b/Tools/NativeHost/English.lproj/InfoPlist.strings deleted file mode 100644 index 5e45963c382ba690b781b953a00585212b898ac5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92 zcmW-XQ3`+{5C!MkQ~2$No+IcIkqMDxWCV8j>LCj|yTg2Mz+o9F%uHlf9u}h9EuK`F a!Y*1dX%G66ZqL#C$|bw0ZoP5@jOGW1ArT7z diff --git a/Tools/NativeHost/English.lproj/MainMenu.cib b/Tools/NativeHost/English.lproj/MainMenu.cib deleted file mode 100644 index 36815f025..000000000 --- a/Tools/NativeHost/English.lproj/MainMenu.cib +++ /dev/null @@ -1 +0,0 @@ -280NPLIST;1.0;D;K;4;$topD;K;18;CPCibObjectDataKeyD;K;6;CP$UIDd;1;2E;E;K;8;$objectsA;S;5;$nullD;K;10;$classnameS;16;_CPCibObjectDataK;8;$classesA;S;16;_CPCibObjectDataS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;1E;K;28;_CPCibObjectDataNamesKeysKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataNamesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataClassesKeysKeyD;K;6;CP$UIDd;1;0E;K;32;_CPCibObjectDataClassesValuesKeyD;K;6;CP$UIDd;1;0E;K;30;_CPCibObjectDataConnectionsKeyD;K;6;CP$UIDd;1;4E;K;28;_CPCibObjectDataFrameworkKeyD;K;6;CP$UIDd;1;0E;K;26;_CPCibObjectDataNextOidKeyD;K;6;CP$UIDd;1;5E;K;30;_CPCibObjectDataObjectsKeysKeyD;K;6;CP$UIDd;1;6E;K;32;_CPCibObjectDataObjectsValuesKeyD;K;6;CP$UIDd;1;7E;K;26;_CPCibObjectDataOidKeysKeyD;K;6;CP$UIDd;1;8E;K;28;_CPCibObjectDataOidValuesKeyD;K;6;CP$UIDd;1;9E;K;28;_CPCibObjectDataFileOwnerKeyD;K;6;CP$UIDd;2;11E;K;33;_CPCibObjectDataVisibleWindowsKeyD;K;6;CP$UIDd;2;13E;E;D;K;10;$classnameS;7;CPArrayK;8;$classesA;S;7;CPArrayS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;15E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;16E;D;K;6;CP$UIDd;2;17E;D;K;6;CP$UIDd;2;18E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;D;K;6;CP$UIDd;2;11E;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;D;K;10;$classnameS;18;_CPCibCustomObjectK;8;$classesA;S;18;_CPCibCustomObjectS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;19E;E;D;K;10;$classnameS;5;CPSetK;8;$classesA;S;5;CPSetS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;12E;K;15;CPSetObjectsKeyD;K;6;CP$UIDd;2;20E;E;D;K;10;$classnameS;20;CPCibOutletConnectorK;8;$classesA;S;20;CPCibOutletConnectorS;14;CPCibConnectorS;8;CPObjectE;E;D;K;6;$classD;K;6;CP$UIDd;2;14E;K;24;_CPCibConnectorSourceKeyD;K;6;CP$UIDd;2;16E;K;29;_CPCibConnectorDestinationKeyD;K;6;CP$UIDd;2;18E;K;23;_CPCibConnectorLabelKeyD;K;6;CP$UIDd;2;21E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;19E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;22E;E;D;K;6;$classD;K;6;CP$UIDd;2;10E;K;27;_CPCibCustomObjectClassNameD;K;6;CP$UIDd;2;23E;E;S;13;CPApplicationD;K;6;$classD;K;6;CP$UIDd;1;3E;K;10;CP.objectsA;E;E;S;8;delegateS;13;NSFontManagerS;13;AppControllerE;K;9;$archiverS;15;CPKeyedArchiverK;8;$versionS;6;100000E; \ No newline at end of file diff --git a/Tools/NativeHost/English.lproj/MainMenu.xib b/Tools/NativeHost/English.lproj/MainMenu.xib deleted file mode 100644 index 2bce8a810..000000000 --- a/Tools/NativeHost/English.lproj/MainMenu.xib +++ /dev/null @@ -1,548 +0,0 @@ - - - - 1050 - 10C540 - 732 - 1038.25 - 458.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 732 - - - YES - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - - - YES - - YES - - - YES - - - - YES - - NSApplication - - - FirstResponder - - - NSApplication - - - NSFontManager - - - AppController - - - - - YES - - - delegate - - - - 519 - - - - - YES - - 0 - - - - - - -2 - - - File's Owner - - - -1 - - - First Responder - - - -3 - - - Application - - - 420 - - - - - 487 - - - - - - - -3.IBPluginDependency - com.apple.InterfaceBuilder.CocoaPlugin - - - YES - - - YES - - - - - YES - - - YES - - - - 677 - - - - YES - - AppController - NSObject - - IBProjectSource - AppController.h - - - - NSObject - - IBProjectSource - NSObject+WebAdditions.h - - - - - YES - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSFontManager - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebDownload.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebEditingDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebFrameLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebJavaPlugIn.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPlugin.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPluginContainer.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebPolicyDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebResourceLoadDelegate.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebScriptObject.h - - - - NSObject - - IBFrameworkSource - WebKit.framework/Headers/WebUIDelegate.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - - 0 - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES - ../NativeHost.xcodeproj - 3 - - diff --git a/Tools/NativeHost/Info.plist b/Tools/NativeHost/Info.plist deleted file mode 100644 index 2f8dbca99..000000000 --- a/Tools/NativeHost/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - icon - CFBundleShortVersionString - 0.9 - CFBundleIdentifier - com.280north.${PRODUCT_NAME:identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - NativeHost - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - diff --git a/Tools/NativeHost/Jakefile b/Tools/NativeHost/Jakefile deleted file mode 100644 index 8df9bce4b..000000000 --- a/Tools/NativeHost/Jakefile +++ /dev/null @@ -1,45 +0,0 @@ - -require("../../common.jake"); - -var OS = require("os"); -var task = require("jake").task -var stream = require("narwhal/term").stream; - -task ("build", function() -{ - if (executableExists("xcodebuild")) - { - var args = "-alltargets -configuration Release"; - - if (xcodebuildHasTenPointFiveSDK()) - args = "-sdk macosx10.5 " + args; - - else - args = "-sdk macosx " + args; - - if (OS.system("xcodebuild " + args)) - OS.exit(1); - - rm_rf(FILE.join($BUILD_CJS_CAPPUCCINO, "support", "NativeHost.app")); - FILE.mkdirs(FILE.join($BUILD_CJS_CAPPUCCINO, "support")) - cp_r(FILE.join("build", "Release", "NativeHost.app"), FILE.join($BUILD_CJS_CAPPUCCINO, "support", "NativeHost.app")); - } - else - { - print("Building NativeHost requires Xcode."); - } -}); - -task ("clean", function() -{ - if (OS.system("xcodebuild clean")) - OS.exit(1); -}); - -task ("clobber", function() -{ - if (OS.system("xcodebuild clean")) - OS.exit(1); -}); - -task ("default", ["build"]); diff --git a/Tools/NativeHost/MenuBridge.h b/Tools/NativeHost/MenuBridge.h deleted file mode 100644 index 847237409..000000000 --- a/Tools/NativeHost/MenuBridge.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// MenuBridge.h -// NativeHost -// -// Created by Francisco Tolmasky on 9/2/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -@class WebScriptObject; - -@interface MenuBridge : NSMenu -{ - WebScriptObject * menuObject; -} - -+ (id)menuBridgeWithMenuObject:(WebScriptObject *)aMenuObject; -- (id)initWithMenuObject:(WebScriptObject *)aMenuObject; - -@end diff --git a/Tools/NativeHost/MenuBridge.m b/Tools/NativeHost/MenuBridge.m deleted file mode 100644 index ad14a7191..000000000 --- a/Tools/NativeHost/MenuBridge.m +++ /dev/null @@ -1,63 +0,0 @@ -// -// MenuBridge.m -// NativeHost -// -// Created by Francisco Tolmasky on 9/2/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "WebScripObject+Objective-J.h" -#import "MenuItemBridge.h" -#import "MenuBridge.h" - - -@implementation MenuBridge - -+ (id)menuBridgeWithMenuObject:(WebScriptObject *)aMenuObject -{ - if (!aMenuObject) - return nil; - - static NSMapTable * cache = nil; - - if (!cache) - cache = [[NSMapTable mapTableWithStrongToStrongObjects] retain]; - - MenuBridge * menuBridge = [cache objectForKey:aMenuObject]; - - if (!menuBridge) - { - menuBridge = [MenuBridge alloc]; - - [cache setObject:menuBridge forKey:aMenuObject]; - - [[menuBridge initWithMenuObject:aMenuObject] autorelease]; - } - - return menuBridge; -} - -- (id)initWithMenuObject:(WebScriptObject *)aMenuObject -{ - self = [super initWithTitle:[aMenuObject bridgeSelector:@selector(title)]]; - - if (self) - { - menuObject = aMenuObject; - - NSInteger index = 0, - count = [[aMenuObject bridgeSelector:@selector(numberOfItems)] intValue]; - - for (; index < count; ++index) - [self addItem:[[[MenuItemBridge alloc] initWithMenuItemObject:[aMenuObject bridgeSelector:@selector(itemAtIndex:) withObject:[NSNumber numberWithInt:index]]] autorelease]]; - } - - return self; -} - -- (void)performActionForItemAtIndex:(NSInteger)anIndex -{ - [menuObject bridgeSelector:@selector(performActionForItemAtIndex:) withObject:[NSNumber numberWithInt:anIndex]]; -} - -@end diff --git a/Tools/NativeHost/MenuItemBridge.h b/Tools/NativeHost/MenuItemBridge.h deleted file mode 100644 index 86e70d6f2..000000000 --- a/Tools/NativeHost/MenuItemBridge.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// ReflectMenuItem.h -// NativeHost -// -// Created by Francisco Tolmasky on 9/2/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -@class WebScriptObject; - -@interface MenuItemBridge : NSMenuItem -{ - WebScriptObject * menuItemObject; -} - -+ (id)menuItemBridgeWithMenuItemObject:(WebScriptObject *)aMenuItemObject; -- (id)initWithMenuItemObject:(WebScriptObject *)aMenuItemObject; - -- (void)updateFromMenuItemObject; - -@end diff --git a/Tools/NativeHost/MenuItemBridge.m b/Tools/NativeHost/MenuItemBridge.m deleted file mode 100644 index b661f35e8..000000000 --- a/Tools/NativeHost/MenuItemBridge.m +++ /dev/null @@ -1,77 +0,0 @@ -// -// ReflectMenuItem.m -// NativeHost -// -// Created by Francisco Tolmasky on 9/2/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "WebScripObject+Objective-J.h" -#import "MenuBridge.h" -#import "MenuItemBridge.h" - - -@implementation MenuItemBridge - -+ (id)menuItemBridgeWithMenuItemObject:(WebScriptObject *)aMenuItemObject -{ - if (!aMenuItemObject) - return nil; - - static NSMapTable * cache = nil; - - if (!cache) - cache = [[NSMapTable mapTableWithStrongToStrongObjects] retain]; - - MenuItemBridge * menuItemBridge = [cache objectForKey:aMenuItemObject]; - - if (!menuItemBridge) - { - menuItemBridge = [MenuBridge alloc]; - - [cache setObject:menuItemBridge forKey:aMenuItemObject]; - - [[menuItemBridge initWithMenuItemObject:aMenuItemObject] autorelease]; - } - - return menuItemBridge; -} - -- (id)initWithMenuItemObject:(WebScriptObject *)aMenuItemObject -{ - if ([[aMenuItemObject bridgeSelector:@selector(isSeparatorItem)] boolValue]) - return [[NSMenuItem separatorItem] retain]; - - self = [super init]; - - if (self) - { - menuItemObject = aMenuItemObject; - - [self updateFromMenuItemObject]; - } - - return self; -} -/* -- (BOOL)isSeparatorItem -{ - return [[menuItemObject bridgeSelector:@selector(isSeparatorItem)] boolValue]; -} -*/ -- (void)updateFromMenuItemObject -{ - [self setTitle:[menuItemObject bridgeSelector:@selector(title)]]; - [self setSubmenu:[MenuBridge menuBridgeWithMenuObject:[menuItemObject bridgeSelector:@selector(submenu)]]]; - [self setKeyEquivalent:[menuItemObject bridgeSelector:@selector(keyEquivalent)]]; - [self setKeyEquivalentModifierMask:[[menuItemObject evaluateObjectiveJ:[NSString stringWithFormat:@"(function() { var mask = %u; return (((mask & CPAlphaShiftKeyMask) ? %u : 0) | ((mask & CPShiftKeyMask) ? %u : 0) | ((mask & CPControlKeyMask) ? %u : 0) | ((mask & CPAlternateKeyMask) ? %u : 0) | ((mask & CPCommandKeyMask) ? %u : 0) | ((mask & CPNumericPadKeyMask) ? %u : 0) | ((mask & CPHelpKeyMask) ? %u : 0) | ((mask & CPFunctionKeyMask) ? %u : 0)) }())", [[menuItemObject bridgeSelector:@selector(keyEquivalentModifierMask)] unsignedIntegerValue], NSAlphaShiftKeyMask, NSShiftKeyMask, NSControlKeyMask, NSAlternateKeyMask, NSCommandKeyMask, NSNumericPadKeyMask, NSHelpKeyMask, NSFunctionKeyMask, NSDeviceIndependentModifierFlagsMask]] unsignedIntegerValue]];[self setAction:@selector(bridgeAction:)]; - [self setTarget:self]; - [self setAction:@selector(bridgeAction:)]; -} - -// This exists so that the menu items are enabled. -- (void)bridgeAction:(id)aSender -{ -} - -@end diff --git a/Tools/NativeHost/NSObject+WebAdditions.h b/Tools/NativeHost/NSObject+WebAdditions.h deleted file mode 100644 index b4ab41035..000000000 --- a/Tools/NativeHost/NSObject+WebAdditions.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// NSObject+WebAdditions.h -// NativeHost -// -// Created by Francisco Tolmasky on 11/16/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -@interface NSObject (WebAdditions) - -- (BOOL)webBoolValue; - -@end diff --git a/Tools/NativeHost/NSObject+WebAdditions.m b/Tools/NativeHost/NSObject+WebAdditions.m deleted file mode 100644 index 1ffd942a1..000000000 --- a/Tools/NativeHost/NSObject+WebAdditions.m +++ /dev/null @@ -1,19 +0,0 @@ -// -// NSObject+WebAdditions.m -// NativeHost -// -// Created by Francisco Tolmasky on 11/16/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "NSObject+WebAdditions.h" - - -@implementation NSObject (WebAdditions) - -- (BOOL)webBoolValue -{ - return [self isKindOfClass:[NSNumber class]] && [(NSNumber *)self boolValue]; -} - -@end diff --git a/Tools/NativeHost/NSURL+Additions.h b/Tools/NativeHost/NSURL+Additions.h deleted file mode 100644 index 32cee28f6..000000000 --- a/Tools/NativeHost/NSURL+Additions.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// NSURL+Additions.h -// NativeHost -// -// Created by Francisco Tolmasky on 6/3/09. -// Copyright 2009 280 North, Inc. All rights reserved. -// - -#import - - -@interface NSURL (Additions) - -- (NSURL *)HTTPFileSystemURL; -+ (NSURL *)fileSystemURLFromHTTPFileSystemString:(NSString *)aString; - -@end diff --git a/Tools/NativeHost/NSURL+Additions.m b/Tools/NativeHost/NSURL+Additions.m deleted file mode 100644 index 39cabb1a3..000000000 --- a/Tools/NativeHost/NSURL+Additions.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// NSURL+Additions.m -// NativeHost -// -// Created by Francisco Tolmasky on 6/3/09. -// Copyright 2009 280 North, Inc. All rights reserved. -// - -#import "NSURL+Additions.h" -#import "AppController.h" - -@implementation NSURL (Additions) - -- (NSURL *)HTTPFileSystemURL -{ - if ([[self scheme] caseInsensitiveCompare:@"file"] == NSOrderedSame) - return [[[NSURL alloc] initWithScheme:@"http" - host:[NSString stringWithFormat:@"127.0.0.1:%d", SERVER_PORT] - path:[@"/filesystem/" stringByAppendingString:[self path]]] autorelease]; - - return [[self copy] autorelease]; -} - -+ (NSURL *)fileSystemURLFromHTTPFileSystemString:(NSString *)aString -{ - NSURL *httpURL = [NSURL URLWithString:aString]; - NSString *path = [httpURL path]; - NSRange range = [path rangeOfString:@"/filesystem"]; - - if (range.location == 0 && NSMaxRange(range) < [path length]) - path = [path substringFromIndex:[@"/filesystem" length]]; - - return [[[NSURL alloc] initFileURLWithPath:path] autorelease]; -} - -@end diff --git a/Tools/NativeHost/NativeHost.xcodeproj/TemplateIcon.icns b/Tools/NativeHost/NativeHost.xcodeproj/TemplateIcon.icns deleted file mode 100644 index 62cb7015e09d6ea3e65d7f7949c4c07f9246a908..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52318 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 WhsmLR^b3` - #import -#endif diff --git a/Tools/NativeHost/SSCrypto.h b/Tools/NativeHost/SSCrypto.h deleted file mode 100644 index 89ff70a9e..000000000 --- a/Tools/NativeHost/SSCrypto.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright (c) 2003-2006, Septicus Software All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Septicus Software nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -// -// SSCrypto.h -// -// Created by Ed Silva on Sat May 31 2003. -// Copyright (c) 2003-2006 Septicus Software. All rights reserved. -// - - -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -@interface NSData (HexDump) -- (NSString *)encodeBase64; -- (NSString *)encodeBase64WithNewlines:(BOOL)encodeWithNewlines; -- (NSData *)decodeBase64; -- (NSData *)decodeBase64WithNewLines:(BOOL)decodeWithNewLines; -- (NSString *)hexval; -- (NSString *)hexdump; -@end - -@interface SSCrypto : NSObject -{ - NSData *symmetricKey; - NSData *cipherText; - NSData *clearText; - NSData *publicKey; - NSData *privateKey; - - BOOL isSymmetric; -} - -- (id)init; -- (id)initWithSymmetricKey:(NSData *)k; -- (id)initWithPublicKey:(NSData *)pub; -- (id)initWithPrivateKey:(NSData *)priv; -- (id)initWithPublicKey:(NSData *)pub privateKey:(NSData *)priv; - -- (BOOL)isSymmetric; -- (void)setIsSymmetric:(BOOL)flag; - -- (NSData *)symmetricKey; -- (void)setSymmetricKey:(NSData *)k; - -- (NSData *)publicKey; -- (void)setPublicKey:(NSData *)k; - -- (NSData *)privateKey; -- (void)setPrivateKey:(NSData *)k; - -- (NSData *)clearTextAsData; -- (NSString *)clearTextAsString; -- (void)setClearTextWithData:(NSData *)c; -- (void)setClearTextWithString:(NSString *)c; - -- (NSData *)cipherTextAsData; -- (NSString *)cipherTextAsString; -- (void)setCipherText:(NSData *)c; - -- (NSData *)decrypt; -- (NSData *)decrypt:(NSString *)cipherName; - -- (NSData *)verify; - -- (NSData *)encrypt; -- (NSData *)encrypt:(NSString *)cipherName; - -- (NSData *)sign; - -- (NSData *)digest:(NSString *)digestName; - -+ (NSData *)generateRSAPrivateKeyWithLength:(int)length; -+ (NSData *)generateRSAPublicKeyFromPrivateKey:(NSData *)privateKey; -+ (NSData *)getKeyDataWithLength:(int)length; -+ (NSData *)getKeyDataWithLength:(int)length fromPassword:(NSString *)pass withSalt:(NSString *)salt; -+ (NSData *)getKeyDataWithLength:(int)length fromPassword:(NSString *)pass withSalt:(NSString *)salt withIterations:(int)count; -+ (NSData *)getSHA1ForData:(NSData *)d; -+ (NSData *)getMD5ForData:(NSData *)d; - -@end diff --git a/Tools/NativeHost/SSCrypto.m b/Tools/NativeHost/SSCrypto.m deleted file mode 100644 index 09c557531..000000000 --- a/Tools/NativeHost/SSCrypto.m +++ /dev/null @@ -1,1214 +0,0 @@ -/* - Copyright (c) 2003-2006, Septicus Software All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Septicus Software nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -// -// SSCrypto.m -// SimpleWebCam -// -// Created by Ed Silva on Sat May 31 2003. -// Copyright (c) 2003-2006 Septicus Software. All rights reserved. -// - -#import "SSCrypto.h" - -@implementation NSData (HexDump) - -/** - * Encodes the current data in base64, and creates and returns an NSString from the result. - * This is the same as piping data through "... | openssl enc -base64" on the command line. - * - * Code courtesy of DaveDribin (http://www.dribin.org/dave/) - * Taken from http://www.cocoadev.com/index.pl?BaseSixtyFour -**/ -- (NSString *)encodeBase64 -{ - return [self encodeBase64WithNewlines: YES]; -} - -/** - * Encodes the current data in base64, and creates and returns an NSString from the result. - * This is the same as piping data through "... | openssl enc -base64" on the command line. - * - * Code courtesy of DaveDribin (http://www.dribin.org/dave/) - * Taken from http://www.cocoadev.com/index.pl?BaseSixtyFour -**/ -- (NSString *)encodeBase64WithNewlines:(BOOL)encodeWithNewlines -{ - // Create a memory buffer which will contain the Base64 encoded string - BIO * mem = BIO_new(BIO_s_mem()); - - // Push on a Base64 filter so that writing to the buffer encodes the data - BIO * b64 = BIO_new(BIO_f_base64()); - if (!encodeWithNewlines) - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - mem = BIO_push(b64, mem); - - // Encode all the data - BIO_write(mem, [self bytes], [self length]); - BIO_flush(mem); - - // Create a new string from the data in the memory buffer - char * base64Pointer; - long base64Length = BIO_get_mem_data(mem, &base64Pointer); - // we use an NSData here since the base64pointer is not null terminated - // the byte array the NSData return should be - // so making an NSString from that will be okay - NSData * base64data = [NSData dataWithBytes:base64Pointer length:base64Length]; - NSString * base64String = [NSString stringWithUTF8String:[base64data bytes]]; - - // Clean up and go home - BIO_free_all(mem); - - if (!encodeWithNewlines) - base64String = [[base64String componentsSeparatedByString:@"\n"] componentsJoinedByString:@""]; - - return base64String; -} - -- (NSData *)decodeBase64 -{ - return [self decodeBase64WithNewLines:YES]; -} - -- (NSData *)decodeBase64WithNewLines:(BOOL)encodedWithNewlines -{ - // Create a memory buffer containing Base64 encoded string data - BIO * mem = BIO_new_mem_buf((void *) [self bytes], [self length]); - - // Push a Base64 filter so that reading from the buffer decodes it - BIO * b64 = BIO_new(BIO_f_base64()); - if (!encodedWithNewlines) - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - mem = BIO_push(b64, mem); - - // Decode into an NSMutableData - NSMutableData * data = [NSMutableData data]; - char inbuf[512]; - int inlen; - while ((inlen = BIO_read(mem, inbuf, sizeof(inbuf))) > 0) - [data appendBytes: inbuf length: inlen]; - - // Clean up and go home - BIO_free_all(mem); - return data; -} - -- (NSString *)hexval -{ - NSMutableString *hex = [NSMutableString string]; - unsigned char *bytes = (unsigned char *)[self bytes]; - char temp[3]; - int i = 0; - - for (i = 0; i < [self length]; i++) { - temp[0] = temp[1] = temp[2] = 0; - (void)sprintf(temp, "%02x", bytes[i]); - [hex appendString:[NSString stringWithUTF8String:temp]]; - } - - return hex; -} - -- (NSString *)hexdump -{ - NSMutableString *ret=[NSMutableString stringWithCapacity:[self length]*2]; - /* dumps size bytes of *data to string. Looks like: - * [0000] 75 6E 6B 6E 6F 77 6E 20 - * 30 FF 00 00 00 00 39 00 unknown 0.....9. - * (in a single line of course) - */ - unsigned int size= [self length]; - const unsigned char *p = [self bytes]; - unsigned char c; - int n; - char bytestr[4] = {0}; - char addrstr[10] = {0}; - char hexstr[ 16*3 + 5] = {0}; - char charstr[16*1 + 5] = {0}; - for(n=1;n<=size;n++) { - if (n%16 == 1) { - /* store address for this line */ - snprintf(addrstr, sizeof(addrstr), "%.4x", - (unsigned int)((long)p-(long)self) ); - } - - c = *p; - if (isalnum(c) == 0) { - c = '.'; - } - - /* store hex str (for left side) */ - snprintf(bytestr, sizeof(bytestr), "%02X ", *p); - strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1); - - /* store char str (for right side) */ - snprintf(bytestr, sizeof(bytestr), "%c", c); - strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1); - - if(n%16 == 0) { - /* line completed */ - //printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); - [ret appendString:[NSString stringWithFormat:@"[%4.4s] %-50.50s %s\n", - addrstr, hexstr, charstr]]; - hexstr[0] = 0; - charstr[0] = 0; - } else if(n%8 == 0) { - /* half line: add whitespaces */ - strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1); - strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1); - } - p++; /* next byte */ - } - - if (strlen(hexstr) > 0) { - /* print rest of buffer if not empty */ - //printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); - [ret appendString:[NSString stringWithFormat:@"[%4.4s] %-50.50s %s\n", - addrstr, hexstr, charstr]]; - } - return ret; -} - -@end - -@interface SSCrypto (PrivateAPI) -- (void)setupOpenSSL; -- (void)cleanupOpenSSL; -@end - -// SSCrypto object -@implementation SSCrypto - -/** - * Generic constructor. - * Simply configures internal OpenSSL setup. -**/ -- (id)init -{ - if(self = [super init]) - { - // Call private method to handle the setup for internal OpenSSL stuff - [self setupOpenSSL]; - } - return self; -} - -/** - * Symmetric key constructor. - * Configures the instance to use symmetric encryption/decryption using the given symmetric key. -**/ -- (id)initWithSymmetricKey:(NSData *)k -{ - if(self = [super init]) - { - // Call private method to handle the setup for internal OpenSSL stuff - [self setupOpenSSL]; - - [self setSymmetricKey:k]; - [self setIsSymmetric:YES]; - } - return self; -} - -/** - * Public key only constructor. - * Configures the instance to use non-symmetric encryption/decryption, and to use the given public key. -**/ -- (id)initWithPublicKey:(NSData *)pub -{ - return [self initWithPublicKey:pub privateKey:nil]; -} - -/** - * Private key only constructor. - * Configures the instance to use non-symmetric encryption/decryption, and to use the given private key. -**/ -- (id)initWithPrivateKey:(NSData *)priv -{ - return [self initWithPublicKey:nil privateKey:priv]; -} - -/** - * Public and Private key constructor. - * Configures the instance to use non-symmetric encryption/decryption, and to use the given public and private keys. -**/ -- (id)initWithPublicKey:(NSData *)pub privateKey:(NSData *)priv; -{ - if(self = [super init]) - { - // Call private method to handle the setup for internal OpenSSL stuff - [self setupOpenSSL]; - - // Store the publicKey variable (if not nil) - if(pub != nil) - [self setPublicKey:pub]; - - // Store the privateKey variable (if not nil) - if(priv != nil) - [self setPrivateKey:priv]; - - // Since we're using public and private keys, we can assume we're not using symmetric encryption - [self setIsSymmetric:NO]; - } - return self; -} - -/** - * This method sets up everything needed to use the OpenSSL libraries later within the code. - * This method should be called by every constructor. -**/ -- (void)setupOpenSSL -{ - // OpenSSL keeps an internal table of digest algorithms and ciphers. - // It uses this table to lookup ciphers via functions such as EVP_get_cipher_byname(). - // OpenSSL_add_all_digests() adds all digest algorithms to the table. - // OpenSSL_add_all_ciphers() adds all cipher algorithms to the table. - // OpenSSL_add_all_algorithms() adds all algorithms to the table (digests and ciphers). - // EVP_cleanup() removes all ciphers and digests from the table. - // - // A typical application will call OpenSSL_add_all_algorithms() initially and EVP_cleanup() before exiting. - - OpenSSL_add_all_algorithms(); - - // ERR_load_crypto_strings() registers the error strings for all libcrypto functions. - // SSL_load_error_strings() does the same, but also registers the libssl error strings. - // ERR_free_strings() frees all previously loaded error strings. - // - // One of these functions should be called before generating textual error messages. - // However, this is not required when memory usage is an issue. - - ERR_load_crypto_strings(); -} - -/** - * Standard deallocation method. -**/ -- (void)dealloc -{ - // Cleanup all OpenSSL stuff - [self cleanupOpenSSL]; - - // Release all instance variables - [symmetricKey release]; - [cipherText release]; - [clearText release]; - [publicKey release]; - [privateKey release]; - - // Move up the inheritance chain - [super dealloc]; -} - -- (void)cleanupOpenSSL -{ - // EVP_cleanup() removes all ciphers and digests from the table. - EVP_cleanup(); - - // ERR_free_strings() frees all previously loaded error strings. - ERR_free_strings(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Getter, Setter Methods: -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Returns whether or not symmetric encryption is to be used. - * If symmetric encryption is in use, then calls to encrypt or decrypt operate using symmetric encryption/decryption. - * Otherwise, it is assumed that asymmetric encryption/decryption is to be used. -**/ -- (BOOL)isSymmetric -{ - return isSymmetric; -} - -- (void)setIsSymmetric:(BOOL)flag -{ - isSymmetric = flag; -} - -- (NSData *)symmetricKey -{ - return symmetricKey; -} - -- (void)setSymmetricKey:(NSData *)k -{ - [k retain]; - [symmetricKey release]; - symmetricKey = k; -} - -/** - * Returns the public key currently in use. -**/ -- (NSData *)publicKey -{ - return publicKey; -} - -/** - * Sets the public key to use. - * Public keys are used to verify signed data, or to encrypt data. (ToDo) -**/ -- (void)setPublicKey:(NSData *)k -{ - [k retain]; - [publicKey release]; - publicKey = k; -} - -/** - * Returns the private key currently in use. -**/ -- (NSData *)privateKey -{ - return privateKey; -} - -/** - * Sets the private key to use. - * Private keys are used to sign data, or to decrypt data. (ToDo) - * - * The data that is provided should from a file (such as private.pem) that was generated by openssl. -**/ -- (void)setPrivateKey:(NSData *)k -{ - [k retain]; - [privateKey release]; - privateKey = k; -} - -/** - * Returns the clear text as plain NSData. - * The plain text contains the text that was previously set. - * It's the known text, which is to be encrypted, decrypted, etc. -**/ -- (NSData *)clearTextAsData -{ - return clearText; -} - -/** - * Returns the clear text formatted as an NSString. - * The plain text contains the text that was previously set. - * It's the known text, which is to be encrypted, decrypted, etc. -**/ -- (NSString *)clearTextAsString -{ - return [[[NSString alloc] initWithData:[self clearTextAsData] encoding:NSUTF8StringEncoding] autorelease]; -} - -/** - * Sets the clear text using the given data. - * The clear text will be used for encryption, decryption, etc. - * - * Note that the given data reference is retained and later used, so it shouldn't be externally modified. -**/ -- (void)setClearTextWithData:(NSData *)c -{ - [c retain]; - [clearText release]; - clearText = c; -} - -/** - * Sets the clear text using the given string. - * The clear text will be used for encryption, signing, and digests. - **/ -- (void)setClearTextWithString:(NSString *)c -{ - [clearText release]; - - // BUG FIX : PLL (2009/02/21) - // - // [c length] : Returns the number of Unicode characters in the receiver. - // For example "‚àö¬©‚àö‚Ć‚àö√ü test" in UTF8 is 11 bytes (c3 a9 c3 a0 c3 a7 20 74 65 73 74) - // but only 8 Unicode characters. - // So this will truncate the text and result in one error. - // - // clearText = [[NSData alloc] initWithBytes:[c UTF8String] length:[c length]]; - - // The number of bytes required to store the receiver in the encoding enc in a non-external representation. The length does not include space for a terminating NULL character. - unsigned int length = [c lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - clearText = [[NSData alloc] initWithBytes:[c UTF8String] length:length]; -} - -/** - * Returns the cipher text as plain NSData. - * The cipher text contains the most recent encrypted data. (Result of call to encrypt) -**/ -- (NSData *)cipherTextAsData -{ - return cipherText; -} - -/** - * Returns the ciper text formatted as an NSString. - * The ciper text contains the most recent encrypted data. (Result of call to encrypt) -**/ -- (NSString *)cipherTextAsString -{ - return [[[NSString alloc] initWithData:[self cipherTextAsData] encoding:NSUTF8StringEncoding] autorelease]; -} - -/** - * Sets the cipher text using the given data. - * The cipher text will be used for decryption and verifying. -**/ -- (void)setCipherText:(NSData *)c -{ - [c retain]; - [cipherText release]; - cipherText = c; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Decryption methods: -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Peforms decryption, and returns resulting clear text data. - * If symmetric decryption is being used, performs symmetric decryption using aes128. - * Otherwise, performs decryption using the private key. -**/ -- (NSData *)decrypt -{ - if([self isSymmetric] && [self symmetricKey]) - { - return [self decrypt:@"aes128"]; - } - else if([self privateKey]) - { - return [self decrypt:nil]; - } - else - { - NSLog(@"No symmetric key or private key is set!"); - return nil; - } -} - -/** - * Decrypts the cipher text data. - * If symmetric decryption is being used, then the decryption is done using the given cipher. - * Otherwise, asymmetric decryptions is used, and the data is encrypted using the private key. - * - * Returns the clear text data that is the result of the decryption. - * The resulting clear text data may also be later retrieved with the clearTextAsData or clearTextAsString methods. -**/ -- (NSData *)decrypt:(NSString *)cipherName -{ - // If there is no cipher text set, or the cipher text is an empty string (zero length data) - // then there is nothing to decrypt, and we may as well return nil - if(cipherText == nil || [cipherText length] == 0) - { - return nil; - } - - unsigned char *outbuf, iv[EVP_MAX_IV_LENGTH]; - int outlen, templen, inlen; - inlen = [cipherText length]; - unsigned char *input = (unsigned char *)[cipherText bytes]; - - if([self isSymmetric]) - { - // Use symmetric decryption... - - unsigned char evp_key[EVP_MAX_KEY_LENGTH] = {"\0"}; - EVP_CIPHER_CTX cCtx; - const EVP_CIPHER *cipher; - - if(cipherName) - { - cipher = EVP_get_cipherbyname((const char *)[cipherName UTF8String]); - if(!cipher) - { - NSLog(@"cannot get cipher with name %@", cipherName); - return nil; - } - } - else - { - cipher = EVP_bf_cbc(); - if(!cipher) - { - NSLog(@"cannot get cipher with name %@", @"EVP_bf_cbc"); - return nil; - } - } - - // Sometimes OpenSSL encrypted data contains an 8 byte salt. - // This is indicated by the "Salted__" prefix in the encrypted data. - - NSData *salt = nil; - - if([cipherText length] > 8+8) - { - if(strncmp((const char *)[cipherText bytes], "Salted__", 8) == 0) - { - salt = [cipherText subdataWithRange:NSMakeRange(8, 8)]; - - input += 16; - inlen -= 16; - } - } - - EVP_BytesToKey(cipher, EVP_md5(), [salt bytes], - [symmetricKey bytes], [symmetricKey length], 1, evp_key, iv); - - EVP_CIPHER_CTX_init(&cCtx); - - if (!EVP_DecryptInit(&cCtx, cipher, evp_key, iv)) - { - NSLog(@"EVP_DecryptInit() failed!"); - EVP_CIPHER_CTX_cleanup(&cCtx); - return nil; - } - EVP_CIPHER_CTX_set_key_length(&cCtx, EVP_MAX_KEY_LENGTH); - - // The data buffer passed to EVP_DecryptUpdate() should have sufficient room for - // (input_length + cipher_block_size) bytes unless the cipher block size is 1 in which - // case input_length bytes is sufficient. - - if(EVP_CIPHER_CTX_block_size(&cCtx) > 1) - outbuf = (unsigned char *)calloc(inlen + EVP_CIPHER_CTX_block_size(&cCtx), sizeof(unsigned char)); - else - outbuf = (unsigned char *)calloc(inlen, sizeof(unsigned char)); - - NSAssert(outbuf, @"Cannot allocate memory for buffer!"); - - if (!EVP_DecryptUpdate(&cCtx, outbuf, &outlen, input, inlen)) - { - NSLog(@"EVP_DecryptUpdate() failed!"); - EVP_CIPHER_CTX_cleanup(&cCtx); - return nil; - } - - if (!EVP_DecryptFinal(&cCtx, outbuf + outlen, &templen)) - { - NSLog(@"EVP_DecryptFinal() failed!"); - EVP_CIPHER_CTX_cleanup(&cCtx); - return nil; - } - - outlen += templen; - EVP_CIPHER_CTX_cleanup(&cCtx); - } - else - { - // Use asymmetric decryption... - - if([self privateKey] == nil) - { - NSLog(@"Cannot decrypt without the private key, which is currently nil"); - return nil; - } - - BIO *privateBIO = NULL; - RSA *privateRSA = NULL; - - if(!(privateBIO = BIO_new_mem_buf((unsigned char*)[[self privateKey] bytes], [[self privateKey] length]))) - { - NSLog(@"BIO_new_mem_buf() failed!"); - return nil; - } - - if(!PEM_read_bio_RSAPrivateKey(privateBIO, &privateRSA, NULL, NULL)) - { - NSLog(@"PEM_read_bio_RSAPrivateKey() failed!"); - return nil; - } - - // RSA_check_key() returns 1 if rsa is a valid RSA key, and 0 otherwise. - - unsigned long check = RSA_check_key(privateRSA); - if(check != 1) - { - NSLog(@"RSA_check_key() failed with result %d!", check); - return nil; - } - - // RSA_size() returns the RSA modulus size in bytes. - // It can be used to determine how much memory must be allocated for an RSA encrypted value. - - outbuf = (unsigned char *)malloc(RSA_size(privateRSA)); - - if(!(outlen = RSA_private_decrypt(inlen, input, outbuf, privateRSA, RSA_PKCS1_PADDING))) - { - NSLog(@"RSA_private_decrypt() failed!"); - return nil; - } - - if(outlen == -1) - { - NSLog(@"Decrypt error: %s (%s)", - ERR_error_string(ERR_get_error(), NULL), - ERR_reason_error_string(ERR_get_error())); - return nil; - } - - if (privateBIO) BIO_free(privateBIO); - if (privateRSA) RSA_free(privateRSA); - } - - // Store the decrypted data as the clear text - [self setClearTextWithData:[NSData dataWithBytes:outbuf length:outlen]]; - - // Release the outbuf, since it was malloc'd - if (outbuf) { - free(outbuf); - } - - return [self clearTextAsData]; -} - -/** - * Verifies (decrypts) the cipher text data using the public key. - * The resulting clear text data is returned. - * - * The resulting clear text data may also be later retrieved with the clearTextAsData or clearTextAsString methods. - **/ -- (NSData *)verify -{ - // If there is no cipher text set, or the cipher text is an empty string (zero length data) - // then there is nothing to decrypt, and we may as well return nil - if(cipherText == nil || [cipherText length] == 0) - { - return nil; - } - - unsigned char *outbuf; - int outlen, inlen; - inlen = [cipherText length]; - unsigned char *input = (unsigned char *)[cipherText bytes]; - - if([self publicKey] == nil) - { - NSLog(@"Cannot verify (decrypt) without the public key, which is currently nil"); - return nil; - } - - BIO *publicBIO = NULL; - RSA *publicRSA = NULL; - - if(!(publicBIO = BIO_new_mem_buf((unsigned char *)[[self publicKey] bytes], [[self publicKey] length]))) - { - NSLog(@"BIO_new_mem_buf() failed!"); - return nil; - } - - if(!PEM_read_bio_RSA_PUBKEY(publicBIO, &publicRSA, NULL, NULL)) - { - NSLog(@"PEM_read_bio_RSA_PUBKEY() failed!"); - return nil; - } - - // RSA_size() returns the RSA modulus size in bytes. - // It can be used to determine how much memory must be allocated for an RSA encrypted value. - - outbuf = (unsigned char *)malloc(RSA_size(publicRSA)); - - if(!(outlen = RSA_public_decrypt(inlen, input, outbuf, publicRSA, RSA_PKCS1_PADDING))) - { - NSLog(@"RSA_public_decrypt() failed!"); - return nil; - } - - if(outlen == -1) - { - NSLog(@"Decrypt error: %s (%s)", - ERR_error_string(ERR_get_error(), NULL), - ERR_reason_error_string(ERR_get_error())); - return nil; - } - - if (publicBIO) BIO_free(publicBIO); - if (publicRSA) RSA_free(publicRSA); - - // Store the decrypted data as the clear text - [self setClearTextWithData:[NSData dataWithBytes:outbuf length:outlen]]; - - // Release the outbuf, since it was malloc'd - if (outbuf) { - free(outbuf); - } - - return [self clearTextAsData]; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Encryption methods: -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Peforms encryption, and returns resulting ciper text data. - * If symmetric encryption is being used, performs symmetric encryption using aes128. - * Otherwise, performs encryption using the public key. -**/ -- (NSData *)encrypt -{ - if([self isSymmetric] && [self symmetricKey]) - { - return [self encrypt:@"aes128"]; - } - else if([self publicKey]) - { - return [self encrypt:nil]; - } - else - { - NSLog(@"No symmetric key or public key is set!"); - return nil; - } -} - -/** - * Encrypts the clear text data. - * If symmetric encryption is being used, then the encryption is done using the given cipher. - * Otherwise, asymmetric encryption is used, and the data is encrypted using the public key. - * - * Returns the cipher text data that is the result of the encryption. - * The resulting cipher text data may also be later retrieved with the cipherTextAsData or cipherTextAsString methods. -**/ -- (NSData *)encrypt:(NSString *)cipherName -{ - // If there is no clear text set, or the clear text is an empty string (zero length data) - // then there is nothing to encrypt, and we may as well return nil - if(clearText == nil || [clearText length] == 0) - { - return nil; - } - - unsigned char *input = (unsigned char *)[clearText bytes]; - unsigned char *outbuf, iv[EVP_MAX_IV_LENGTH]; - int outlen, templen, inlen; - inlen = [clearText length]; - - if([self isSymmetric]) - { - // Perform symmetric encryption... - - unsigned char evp_key[EVP_MAX_KEY_LENGTH] = {"\0"}; - EVP_CIPHER_CTX cCtx; - const EVP_CIPHER *cipher; - - if (cipherName){ - cipher = EVP_get_cipherbyname((const char *)[cipherName UTF8String]); - if (!cipher){ - NSLog(@"cannot get cipher with name %@", cipherName); - return nil; - } - } else { - cipher = EVP_bf_cbc(); - if (!cipher){ - NSLog(@"cannot get cipher with name %@", @"EVP_bf_cbc"); - return nil; - } - } - - EVP_BytesToKey(cipher, EVP_md5(), NULL, - [[self symmetricKey] bytes], [[self symmetricKey] length], 1, evp_key, iv); - EVP_CIPHER_CTX_init(&cCtx); - - if (!EVP_EncryptInit(&cCtx, cipher, evp_key, iv)) { - NSLog(@"EVP_EncryptInit() failed!"); - EVP_CIPHER_CTX_cleanup(&cCtx); - return nil; - } - EVP_CIPHER_CTX_set_key_length(&cCtx, EVP_MAX_KEY_LENGTH); - - // The data buffer passed to EVP_EncryptUpdate() should have sufficient room for - // (input_length + cipher_block_size - 1) - - outbuf = (unsigned char *)calloc(inlen + EVP_CIPHER_CTX_block_size(&cCtx) - 1, sizeof(unsigned char)); - NSAssert(outbuf, @"Cannot allocate memory for buffer!"); - - if (!EVP_EncryptUpdate(&cCtx, outbuf, &outlen, input, inlen)) - { - NSLog(@"EVP_EncryptUpdate() failed!"); - EVP_CIPHER_CTX_cleanup(&cCtx); - return nil; - } - if (!EVP_EncryptFinal(&cCtx, outbuf + outlen, &templen)) - { - NSLog(@"EVP_EncryptFinal() failed!"); - EVP_CIPHER_CTX_cleanup(&cCtx); - return nil; - } - outlen += templen; - EVP_CIPHER_CTX_cleanup(&cCtx); - - } - else - { - // Perform asymmetric encryption... - - if([self publicKey] == nil) - { - NSLog(@"Cannot encrypt without the public key, which is currently nil"); - return nil; - } - - BIO *publicBIO = NULL; - RSA *publicRSA = NULL; - - if(!(publicBIO = BIO_new_mem_buf((unsigned char*)[[self publicKey] bytes], [[self publicKey] length]))) - { - NSLog(@"BIO_new_mem_buf() failed!"); - return nil; - } - - if(!PEM_read_bio_RSA_PUBKEY(publicBIO, &publicRSA, NULL, NULL)) - { - NSLog(@"PEM_read_bio_RSA_PUBKEY() failed!"); - return nil; - } - - // RSA_size() returns the RSA modulus size in bytes. - // It can be used to determine how much memory must be allocated for an RSA encrypted value. - - outbuf = (unsigned char *)malloc(RSA_size(publicRSA)); - - if(!(outlen = RSA_public_encrypt(inlen, input, (unsigned char*)outbuf, publicRSA, RSA_PKCS1_PADDING))) - { - NSLog(@"RSA_public_encrypt failed!"); - return nil; - } - - if(outlen == -1) - { - NSLog(@"Encrypt error: %s (%s)", - ERR_error_string(ERR_get_error(), NULL), - ERR_reason_error_string(ERR_get_error())); - return nil; - } - - if (publicBIO) BIO_free(publicBIO); - if (publicRSA) RSA_free(publicRSA); - } - - // Store the encrypted data as the cipher text - [self setCipherText:[NSData dataWithBytes:outbuf length:outlen]]; - - // Release the outbuf, since it was malloc'd - if(outbuf) { - free(outbuf); - } - - return [self cipherTextAsData]; -} - -/** - * Signs (encrypts) the clear text data using the private key. - * The resulting cipher text data is returned, and may later be verified (decrypted) using the public key. - * - * The resulting cipher text data may also be later retrieved with the cipherTextAsData or cipherTextAsString methods. -**/ -- (NSData *)sign -{ - // If there is no clear text set, or the clear text is an empty string (zero length data) - // then there is nothing to encrypt, and we may as well return nil - if(clearText == nil || [clearText length] == 0) - { - return nil; - } - - unsigned char *input = (unsigned char *)[clearText bytes]; - unsigned char *outbuf; - int outlen, inlen; - inlen = [clearText length]; - - if([self privateKey] == nil) - { - NSLog(@"Cannot sign (encrypt) without the private key, which is currently nil"); - return nil; - } - - BIO *privateBIO = NULL; - RSA *privateRSA = NULL; - - if(!(privateBIO = BIO_new_mem_buf((unsigned char*)[[self privateKey] bytes], [[self privateKey] length]))) - { - NSLog(@"BIO_new_mem_buf() failed!"); - return nil; - } - - if(!PEM_read_bio_RSAPrivateKey(privateBIO, &privateRSA, NULL, NULL)) - { - NSLog(@"PEM_read_bio_RSAPrivateKey() failed!"); - return nil; - } - - // RSA_check_key() returns 1 if rsa is a valid RSA key, and 0 otherwise. - - unsigned long check = RSA_check_key(privateRSA); - if(check != 1) - { - NSLog(@"RSA_check_key() failed with result %d!", check); - return nil; - } - - // RSA_size() returns the RSA modulus size in bytes. - // It can be used to determine how much memory must be allocated for an RSA encrypted value. - - outbuf = (unsigned char *)malloc(RSA_size(privateRSA)); - - if(!(outlen = RSA_private_encrypt(inlen, input, (unsigned char*)outbuf, privateRSA, RSA_PKCS1_PADDING))) - { - NSLog(@"RSA_private_encrypt failed!"); - return nil; - } - - if(outlen == -1) - { - NSLog(@"Encrypt error: %s (%s)", - ERR_error_string(ERR_get_error(), NULL), - ERR_reason_error_string(ERR_get_error())); - return nil; - } - - if (privateBIO) BIO_free(privateBIO); - if (privateRSA) RSA_free(privateRSA); - - // Store the encrypted data as the cipher text - [self setCipherText:[NSData dataWithBytes:outbuf length:outlen]]; - - // Release the outbuf, since it was malloc'd - if(outbuf) { - free(outbuf); - } - - return [self cipherTextAsData]; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Other methods: -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Description forthcoming... -**/ -- (NSData *)digest:(NSString *)digestName -{ - if(clearText == nil) { - return nil; - } - - unsigned char outbuf[EVP_MAX_MD_SIZE]; - unsigned int templen, inlen; - unsigned char *input=(unsigned char*)[clearText bytes]; - EVP_MD_CTX ctx; - const EVP_MD *digest = NULL; - - inlen = [clearText length]; - - if(inlen==0) - return nil; - if(digestName) { - digest = EVP_get_digestbyname((const char*)[digestName UTF8String]); - if (!digest) { - NSLog(@"cannot get digest with name %@",digestName); - return nil; - } - } else { - digest=EVP_md5(); - if(!digest) { - NSLog(@"cannot get digest with name %@",@"MD5"); - return nil; - } - } - - EVP_MD_CTX_init(&ctx); - EVP_DigestInit(&ctx,digest); - if(!EVP_DigestUpdate(&ctx,input,inlen)) { - NSLog(@"EVP_DigestUpdate() failed!"); - EVP_MD_CTX_cleanup(&ctx); - return nil; - } - if (!EVP_DigestFinal(&ctx, outbuf, &templen)) { - NSLog(@"EVP_DigesttFinal() failed!"); - EVP_MD_CTX_cleanup(&ctx); - return nil; - } - EVP_MD_CTX_cleanup(&ctx); - - return [NSData dataWithBytes:outbuf length:templen]; -} - -- (NSString *)description -{ - NSString *format = @"clearText: %@, cipherText: %@, symmetricKey: %@, publicKey: %@, privateKey: %@"; - NSString *desc = [NSString stringWithFormat:format, [clearText hexdump], [cipherText hexdump], - [symmetricKey hexdump], [publicKey hexdump], [privateKey hexdump]]; - return desc; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark Class methods: -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -+ (NSData *)generateRSAPrivateKeyWithLength:(int)length -{ - RSA *key = NULL; - do { - key = RSA_generate_key(length, RSA_F4, NULL, NULL); - } while (1 != RSA_check_key(key)); - - BIO *bio = BIO_new(BIO_s_mem()); - - if (!PEM_write_bio_RSAPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) - { - NSLog(@"cannot write private key to memory"); - return nil; - } - if (key) RSA_free(key); - - char *pbio_data = NULL; - int data_len = BIO_get_mem_data(bio, &pbio_data); - NSData *result = [NSData dataWithBytes:pbio_data length:data_len]; - - if (bio) - BIO_free(bio); - - return result; -} - -+ (NSData *)generateRSAPublicKeyFromPrivateKey:(NSData *)privateKey -{ - BIO *privateBIO = NULL; - RSA *privateRSA = NULL; - - if (!(privateBIO = BIO_new_mem_buf((unsigned char*)[privateKey bytes], [privateKey length]))) - { - NSLog(@"BIO_new_mem_buf() failed!"); - return nil; - } - - if (!PEM_read_bio_RSAPrivateKey(privateBIO, &privateRSA, NULL, NULL)) - { - NSLog(@"PEM_read_bio_RSAPrivateKey() failed!"); - return nil; - } - - // RSA_check_key() returns 1 if rsa is a valid RSA key, and 0 otherwise. - - unsigned long check = RSA_check_key(privateRSA); - if (check != 1) - { - NSLog(@"RSA_check_key() failed with result %d!", check); - return nil; - } - - BIO *bio = BIO_new(BIO_s_mem()); - - if (!PEM_write_bio_RSA_PUBKEY(bio, privateRSA)) - { - NSLog(@"cannot write public key to memory"); - return nil; - } - if (privateRSA) RSA_free(privateRSA); - - char *pbio_data = NULL; - int data_len = BIO_get_mem_data(bio, &pbio_data); - NSData *result = [NSData dataWithBytes:pbio_data length:data_len]; - - if (bio) - BIO_free(bio); - - return result; -} - -+ (NSData *)getKeyDataWithLength:(int)length -{ - NSData *randData = nil; - unsigned char *buffer; - - buffer = (unsigned char *)calloc(length*4, sizeof(unsigned char)); - NSAssert((buffer != NULL), @"Cannot calloc memory for buffer."); - - if (!RAND_bytes(buffer, length)){ - free(buffer); - } - - randData = [NSData dataWithBytes:buffer length:length]; - free(buffer); - - return randData; -} - -// PBKDF2 support functions -// Thanks to Chris Benedict (chrisbdaemon@gmail.com) for the code -+ (NSData *)getKeyDataWithLength:(int)length fromPassword:(NSString *)pass withSalt:(NSString *)salt -{ - return [SSCrypto getKeyDataWithLength:length fromPassword:pass withSalt:salt withIterations:1000]; -} - -+ (NSData *)getKeyDataWithLength:(int)length fromPassword:(NSString *)pass withSalt:(NSString *)salt withIterations:(int)count -{ - NSData *key = nil; - unsigned char *buffer = (unsigned char *)calloc(length, sizeof(unsigned char)); - NSAssert((buffer != NULL), @"Cannot calloc memory for buffer."); - const char *password = [pass UTF8String]; - const char *saltVal = [salt UTF8String]; - - if(!PKCS5_PBKDF2_HMAC_SHA1(password, [pass length], (unsigned char *)saltVal, [salt length], count, length, buffer)) { - return nil; - } - - key = [NSData dataWithBytes:buffer length:length]; - free(buffer); - - return key; -} - -+ (NSData *)getSHA1ForData:(NSData *)d -{ - unsigned length = [d length]; - const void *buffer = [d bytes]; - unsigned char *md = (unsigned char *)calloc(SHA_DIGEST_LENGTH, sizeof(unsigned char)); - NSAssert((md != NULL), @"Cannot calloc memory for buffer."); - - (void)SHA1(buffer, length, md); - - return [NSData dataWithBytesNoCopy:md length:SHA_DIGEST_LENGTH freeWhenDone:YES]; -} - -+ (NSData *)getMD5ForData:(NSData *)d -{ - unsigned length = [d length]; - const void *buffer = [d bytes]; - unsigned char *md = (unsigned char *)calloc(MD5_DIGEST_LENGTH, sizeof(unsigned char)); - NSAssert((md != NULL), @"Cannot calloc memory for buffer."); - - (void)MD5(buffer, length, md); - - return [NSData dataWithBytesNoCopy:md length:MD5_DIGEST_LENGTH freeWhenDone:YES]; -} - -@end diff --git a/Tools/NativeHost/Server.h b/Tools/NativeHost/Server.h deleted file mode 100644 index a11e9d701..000000000 --- a/Tools/NativeHost/Server.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Server.h -// NativeHost -// -// Created by Francisco Tolmasky on 8/18/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - -@interface Server : NSObject -{ - NSFileHandle * outputFile; - NSFileHandle * errorFile; - NSTask * process; -} - -- (BOOL)start; -- (void)stop; - -@end diff --git a/Tools/NativeHost/Server.m b/Tools/NativeHost/Server.m deleted file mode 100644 index 5439bc967..000000000 --- a/Tools/NativeHost/Server.m +++ /dev/null @@ -1,193 +0,0 @@ -// -// Server.m -// NativeHost -// -// Created by Francisco Tolmasky on 8/18/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "Server.h" -#import "AppController.h" - -#import -#import - -@implementation Server - -- (BOOL)start -{ - NSBundle *mainBundle = [NSBundle mainBundle]; - NSString *serverPath = [mainBundle pathForResource:@"NativeHostServer" ofType:@"" inDirectory:@"Server"]; - - if (!serverPath) - { - return YES; - } - - // find an available port - struct sockaddr_in addr; - int sockfd; - int attempts = 0; - - while (SERVER_PORT == 9191 && attempts++ < 5) - { - // Create a socket - sockfd = socket( AF_INET, SOCK_STREAM, 0 ); - - // Setup its address structure - bzero( &addr, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl( INADDR_ANY ); - addr.sin_port = htons( 0 ); - - // Bind it to an address and port - bind( sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)); - - // Set it listening for connections - listen( sockfd, 5 ); - - // Find out what port the socket was bound to - socklen_t namelen = sizeof(struct sockaddr_in); - getsockname( sockfd, (struct sockaddr *)&addr, &namelen ); - - if (addr.sin_port <= 1024) - addr.sin_port = 9191; - else - SERVER_PORT = addr.sin_port; - - shutdown(sockfd, 2); - } - - if (SERVER_PASSWORD == nil) - { - CFUUIDRef uuidObj = CFUUIDCreate(nil); - SERVER_PASSWORD = (NSString*)CFUUIDCreateString(nil, uuidObj); - CFRelease(uuidObj); - } - - if (SERVER_USER == nil) - { - CFUUIDRef uuidObj = CFUUIDCreate(nil); - SERVER_USER = (NSString*)CFUUIDCreateString(nil, uuidObj); - CFRelease(uuidObj); - // usernames can't have "-" in them - SERVER_USER = [[SERVER_USER autorelease] stringByReplacingOccurrencesOfString:@"-" withString:@""]; - } - - // setup environment variables - NSDictionary *env = [[[NSProcessInfo processInfo] environment] mutableCopy]; - [env setValue:[mainBundle resourcePath] forKey:@"NATIVEHOST_RESOURCES"]; - [env setValue:[[NSNumber numberWithInt:SERVER_PORT] stringValue] forKey:@"NATIVEHOST_SERVER_PORT"]; - [env setValue:SERVER_USER forKey:@"NATIVEHOST_SERVER_USER"]; - [env setValue:SERVER_PASSWORD forKey:@"NATIVEHOST_SERVER_PASSWORD"]; - - // create pipes for stdout and stderr - NSPipe * outputPipe = [NSPipe pipe]; - outputFile = [outputPipe fileHandleForReading]; - NSPipe * errorPipe = [NSPipe pipe]; - errorFile = [errorPipe fileHandleForReading]; - - // setup the process - process = [[NSTask alloc] init]; - [process setLaunchPath:serverPath]; - [process setStandardOutput:outputPipe]; - [process setStandardError:errorPipe]; - [process setEnvironment:env]; - [env release]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(serverDidTerminate:) - name:NSTaskDidTerminateNotification - object:process]; - - [process launch]; - - BOOL didStartup = NO; - NSData * data = nil; - - while (!didStartup && (data = [outputFile availableData]) && [data length]) - { - NSString * string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - if (string) - { - NHLog(@"SERVER-OUT", string); - - didStartup = [string rangeOfString:@"Jack is starting up"].location != NSNotFound; - - [string release]; - } - } - NSLog(@"Server has started."); - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(didReadStdOut:) - name:NSFileHandleReadCompletionNotification - object:outputFile]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(didReadStdErr:) - name:NSFileHandleReadCompletionNotification - object:errorFile]; - - [outputFile readInBackgroundAndNotify]; - [errorFile readInBackgroundAndNotify]; - - return didStartup; -} - -- (void)stop -{ - [process terminate]; -} - -- (void)didReadStdOut:(NSNotification *)aNotification -{ - NSString * string = [[NSString alloc] initWithData:[[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem] - encoding:NSASCIIStringEncoding]; - NHLog(@"SERVER-OUT", string); - [string release]; - [outputFile readInBackgroundAndNotify]; -} - -- (void)didReadStdErr:(NSNotification *)aNotification -{ - NSString * string = [[NSString alloc] initWithData:[[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem] - encoding:NSASCIIStringEncoding]; - NHLog(@"SERVER-ERR", string); - [string release]; - [errorFile readInBackgroundAndNotify]; -} - -- (void)serverDidTerminate:(NSNotification *)note -{ - if ([process terminationStatus] != 0) - { - NSString *appName = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:@"CFBundleDisplayName"]; - if (appName == nil) - appName = [[NSProcessInfo processInfo] processName]; - - if (SERVER_PORT != 9191 && [self start]) - { - NSRunAlertPanel(@"Unexpected Error", - [NSString stringWithFormat:@"%@ was not able to complete the last action you performed. Try again, and report the problem if it continues to occur.", appName], - @"OK", nil, nil); - } - else - { - NSRunAlertPanel(@"Unexpected Error", - [NSString stringWithFormat:@"A fatal error occurred. %@ could not recover and must terminate.", appName], - @"Terminate", nil, nil); - exit(1); - } - } -} - -- (void)dealloc -{ - [process release]; - [super dealloc]; -} - -@end diff --git a/Tools/NativeHost/WebPasteboardProxy.h b/Tools/NativeHost/WebPasteboardProxy.h deleted file mode 100644 index 887b95f4c..000000000 --- a/Tools/NativeHost/WebPasteboardProxy.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// WebPasteboardProxy.h -// NativeHost -// -// Created by Ross Boucher on 12/12/09. -// Copyright 2009 280 North. All rights reserved. -// - -#import - - -@interface WebPasteboardProxy : NSObject -{ - NSPasteboard *pasteboard; -} - -+ (id)pasteboardWithName:(NSString *)aName; - -@end diff --git a/Tools/NativeHost/WebPasteboardProxy.m b/Tools/NativeHost/WebPasteboardProxy.m deleted file mode 100644 index 6eba5c038..000000000 --- a/Tools/NativeHost/WebPasteboardProxy.m +++ /dev/null @@ -1,95 +0,0 @@ -// -// WebPasteboardProxy.m -// NativeHost -// -// Created by Ross Boucher on 12/12/09. -// Copyright 2009 280 North. All rights reserved. -// - -#import "WebPasteboardProxy.h" -#import "WebScripObject+Objective-J.h" -#import "BridgedMethods.h" - -NSMutableDictionary *WebPasteboardDictionary = nil; - -@implementation WebPasteboardProxy - -+ (void)initialize -{ - WebPasteboardDictionary = [[NSMutableDictionary dictionary] retain]; -} - -+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector -{ - return NO; -} - -+ (id)pasteboardWithName:(NSString *)aName -{ - if ([aName isEqual:@"CPGeneralPboard"]) - return [self pasteboardWithName:NSGeneralPboard]; - - id proxy = [WebPasteboardDictionary objectForKey:aName]; - if (!proxy) - { - proxy = [[self alloc] initWithPasteboard:[NSPasteboard pasteboardWithName:aName]]; - [WebPasteboardDictionary setObject:proxy forKey:aName]; - [proxy release]; - } - - return proxy; -} - -- (id)initWithPasteboard:(NSPasteboard *)aPasteboard -{ - if (self = [super init]) - { - pasteboard = [aPasteboard retain]; - } - - return self; -} - -- (void)dealloc -{ - [pasteboard release]; - [super dealloc]; -} - -- (int)changeCount -{ - return [pasteboard changeCount]; -} - -- (void)declareTypes:(WebScriptObject *)args -{ - [pasteboard declareTypes:[BridgedMethods arrayFromWebScriptObject:args] owner:self]; -} - -- (void)addTypes:(WebScriptObject *)args -{ - [pasteboard addTypes:[BridgedMethods arrayFromWebScriptObject:args ] owner:self]; -} - -- (NSArray *)types -{ - return [pasteboard types]; -} - -- (NSString *)stringForType:(NSString *)aType -{ - return [pasteboard stringForType:aType]; -} - -- (void)pasteboard:(NSPasteboard *)aPasteboard provideDataForType:(NSString *)aType -{ - NSString *name = aPasteboard == [NSPasteboard generalPasteboard] ? @"CPGeneralPboard" : [aPasteboard name]; - - NSString *data = [[[NSApp delegate] windowScriptObject] evaluateObjectiveJReturningString: - [NSString stringWithFormat:@"[[CPPasteboard pasteboardWithName:'%@'] stringForType:'%@']", name, aType] - ]; - - [aPasteboard setString:data forType:aType]; -} - -@end diff --git a/Tools/NativeHost/WebScripObject+Objective-J.h b/Tools/NativeHost/WebScripObject+Objective-J.h deleted file mode 100644 index 4b448574d..000000000 --- a/Tools/NativeHost/WebScripObject+Objective-J.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// WebScripObject+Objective-J.h -// NativeHost -// -// Created by Francisco Tolmasky on 9/1/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import -#import - - -@interface WebScriptObject (ObjectiveJ) - -- (id)evaluateObjectiveJ:(NSString *)aString; -- (NSString *)evaluateObjectiveJReturningString:(NSString *)aString; - -- (id)bridgeSelector:(SEL)aSelector; -- (id)bridgeSelector:(SEL)aSelector withObject:(id)anObject; -- (id)bridgeSelector:(SEL)aSelector withObjects:(NSArray *)array; - -@end diff --git a/Tools/NativeHost/WebScripObject+Objective-J.m b/Tools/NativeHost/WebScripObject+Objective-J.m deleted file mode 100644 index d1be2df47..000000000 --- a/Tools/NativeHost/WebScripObject+Objective-J.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// WebScripObject+Objective-J.m -// NativeHost -// -// Created by Francisco Tolmasky on 9/1/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "WebScripObject+Objective-J.h" - - -@implementation WebScriptObject (ObjectiveJ) - -- (id)evaluateObjectiveJ:(NSString *)aString -{ - return [self evaluateWebScript:[NSString stringWithFormat:@"(ObjectiveJ.eval(decodeURIComponent(\"%@\")))", [aString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], nil]]; -} - -- (NSString *)evaluateObjectiveJReturningString:(NSString *)aString -{ - return [self evaluateWebScript:[NSString stringWithFormat:@"String(ObjectiveJ.eval(decodeURIComponent(\"%@\")))", [aString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], nil]]; -} - -- (id)bridgeSelector:(SEL)aSelector -{ - return [self bridgeSelector:aSelector withObjects:nil]; -} - -- (id)bridgeSelector:(SEL)aSelector withObject:(id)anObject -{ - return [self bridgeSelector:aSelector withObjects:[NSArray arrayWithObject:anObject]]; -} - -- (id)bridgeSelector:(SEL)aSelector withObjects:(NSArray *)objects -{ - [self evaluateWebScript:@"objj_object.prototype.__objj_msgSend = function() { return objj_msgSend.apply(null, arguments); }"]; - - NSArray * arguments = [NSArray arrayWithObjects:self, NSStringFromSelector(aSelector), nil]; - - if (objects) - arguments = [arguments arrayByAddingObjectsFromArray:objects]; - - return [self callWebScriptMethod:@"__objj_msgSend" withArguments:arguments]; -} - -@end diff --git a/Tools/NativeHost/WebWindow.h b/Tools/NativeHost/WebWindow.h deleted file mode 100644 index a7feb9fac..000000000 --- a/Tools/NativeHost/WebWindow.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// WebWindow.h -// NativeHost -// -// Created by Francisco Tolmasky on 10/18/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import - - -typedef enum _CPWindowShadowStyle -{ - CPStandardWindowShadowStyle = 0, - CPMenuWindowShadowStyle = 1, - CPPanelWindowShadowStyle = 2, - CPCustomWindowShadowStyle = 3 -} CPWindowShadowStyle; - -@interface WebWindow : NSWindow -{ - NSView * leftMouseDownView; - NSView * rightMouseDownView; - - WebView * webView; - NSView * shadowView; - - BOOL hasShadow; - CPWindowShadowStyle shadowStyle; -} - -+ (WebWindow *)webWindow; - -- (WebView *)webView; - -- (BOOL)hitTest:(NSPoint)aPoint; - -- (BOOL)hasShadow; -- (void)setHasShadow:(BOOL)shouldHaveShadow; - -- (void)setShadowStyle:(CPWindowShadowStyle)aStyle; -- (CPWindowShadowStyle)shadowStyle; - -@end diff --git a/Tools/NativeHost/WebWindow.m b/Tools/NativeHost/WebWindow.m deleted file mode 100644 index 1dc25e4a1..000000000 --- a/Tools/NativeHost/WebWindow.m +++ /dev/null @@ -1,515 +0,0 @@ -// -// WebWindow.m -// NativeHost -// -// Created by Francisco Tolmasky on 10/18/09. -// Copyright 2009 280 North, Inc.. All rights reserved. -// - -#import "WebWindow.h" - - -static NSMutableArray * DisabledWindows; - -CFMachPortRef tap_port; - -CGEventRef headTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - // It's dangerous to fail in this code: could disable mousedown system-wide. So just try catch it all. - @try - { - if (type == kCGEventLeftMouseDown) - { - CGPoint location = CGEventGetLocation(event); - NSPoint NSLocation = NSMakePoint(location.x, location.y); - - for (NSWindow * window in [NSApp windows]) - { - if ([window isKindOfClass:[WebWindow class]] && ![(WebWindow *)window hitTest:NSLocation]) - { - [window setIgnoresMouseEvents:YES]; - [window performSelector:@selector(setIgnoresMouseEvents:) withObject:NO afterDelay:1.0]; - - [DisabledWindows addObject:window]; - } - } - } - else if (type == kCGEventTapDisabledByTimeout) - CGEventTapEnable(tap_port, YES); - - } - @catch (NSException * anException) - { - } - - return event; -} - - -@interface WebWindowContentView : NSView -{ -} -@end - -@implementation WebWindow - -+ (void)enableAllWindows -{ - [DisabledWindows makeObjectsPerformSelector:@selector(stopIgnoringMouseEvents)]; - [DisabledWindows removeAllObjects]; -} - -+ (void)initialize -{ - if (self != [WebWindow class]) - return; - - DisabledWindows = [[NSMutableArray alloc] init]; - - //| CGEventMaskBit(kCGEventTapDisabledByTimeout) - tap_port = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, - kCGEventTapOptionDefault, - CGEventMaskBit(kCGEventLeftMouseDown), - headTapCallback, NULL); - - if (NULL == tap_port) - { - fprintf(stderr, "Error creating event tap\n"); - return; - } - - /* Create a run loop source from the tap port, add it to my run loop - * and start executing the loop - */ - CFRunLoopSourceRef tap_source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap_port, 0); - - if (NULL == tap_source) - { - fprintf(stderr, "Error converting port to run loop source\n"); - - if (tap_port != NULL) - CFRelease(tap_port); - - return; - } - - CFRunLoopAddSource(CFRunLoopGetCurrent(), tap_source, kCFRunLoopCommonModes); -} - -- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)windowStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)shouldDeferCreation -{ - self = [super initWithContentRect:aContentRect styleMask:NSBorderlessWindowMask backing:aBufferingType defer:shouldDeferCreation]; - - if (self) - { - id delegate = [NSApp delegate]; - - shadowView = [[WebWindowContentView alloc] init]; - - [self setContentView:shadowView]; - - webView = [[WebView alloc] initWithFrame:NSZeroRect]; - - [webView setDrawsBackground:NO]; - [webView setUIDelegate:delegate]; - [webView setFrameLoadDelegate:delegate]; - [webView setResourceLoadDelegate:delegate]; - [webView setPolicyDelegate:delegate]; - [webView setShouldCloseWithWindow:YES]; - - [shadowView addSubview:webView]; - - [self setBackgroundColor:[NSColor clearColor]]; - [self setOpaque:NO]; - [self setIgnoresMouseEvents:NO]; - [self setReleasedWhenClosed:YES]; - [super setHasShadow:NO]; - } - - return self; -} - -- (void)setFrame:(NSRect)aFrame display:(BOOL)shouldDisplay -{ - [webView setFrame:NSMakeRect(33.0, 33.0, NSWidth(aFrame), NSHeight(aFrame))]; - [super setFrame:NSInsetRect(aFrame, -33.0, -33.0) display:YES]; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:self]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:self]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:self]; - - [shadowView release]; - [webView release]; - [super dealloc]; -} - -- (BOOL)canBecomeKeyWindow -{ - // Necessary since this apparently returns NO for borderless windows. - return YES; -} - -- (NSView *)webHitTest:(NSPoint)aPoint -{ - NSPoint locationInWebView = [[self contentView] convertPoint:aPoint fromView:nil]; - - return [(NSView *)[self contentView] hitTest:locationInWebView]; -} - -- (void)sendEvent:(NSEvent *)anEvent -{ - NSInteger type = [anEvent type]; - - if (type == NSLeftMouseDown) - { - NSView * view = [self webHitTest:[anEvent locationInWindow]]; - - leftMouseDownView = view; - - [view mouseDown:anEvent]; - } - - else if (type == NSLeftMouseDragged) - [leftMouseDownView mouseDragged:anEvent]; - - else if (type == NSLeftMouseUp) - [leftMouseDownView mouseUp:anEvent]; - - else if (type == NSRightMouseDown) - { - NSView * view = [self webHitTest:[anEvent locationInWindow]]; - - rightMouseDownView = view; - - [view rightMouseDown:anEvent]; - } - else if (type == NSRightMouseDragged) - [rightMouseDownView rightMouseDragged:anEvent]; - - else if (type == NSRightMouseUp) - [rightMouseDownView rightMouseUp:anEvent]; - - else - [super sendEvent:anEvent]; - - // FIXME: other -} - -// Override this to avoid the beep from unhandled events. -- (void)keyDown:(NSEvent *)anEvent -{ -} - -+ (WebWindow *)webWindow -{ - return [[WebWindow alloc] initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; -} - -- (WebView *)webView -{ - return webView; -} - -- (void)updateShadow -{ - [super setHasShadow:hasShadow && shadowStyle == CPCustomWindowShadowStyle]; - [shadowView setNeedsDisplay:YES]; -} - -- (BOOL)hasShadow -{ - return hasShadow; -} - -- (void)setHasShadow:(BOOL)shouldHaveShadow -{ - if (hasShadow == shouldHaveShadow) - return; - - hasShadow = shouldHaveShadow; - - [self updateShadow]; -} - -- (CPWindowShadowStyle)shadowStyle -{ - return shadowStyle; -} - -- (void)setShadowStyle:(CPWindowShadowStyle)aStyle -{ - if (shadowStyle == aStyle) - return; - - shadowStyle = aStyle; - - [self updateShadow]; -} - -- (BOOL)hitTest:(NSPoint)aPoint -{ - NSInteger windowNumber = [[[webView windowScriptObject] valueForKey:@"cpWindowNumber"] intValue]; - -#if LOGGING - WebScriptObject * frame = [[[NSApp delegate] windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"(objj_msgSend(objj_msgSend(CPApp, \"windowWithWindowNumber:\", %d), \"frame\"))", windowNumber]], - * origin = [frame valueForKey:@"origin"], - * size = [frame valueForKey:@"size"]; - - NSLog(@"(%f, %f) in { %f, %f, %f, %f }", aPoint.x, aPoint.y, [[origin valueForKey:@"x"] floatValue], [[origin valueForKey:@"y"] floatValue], [[size valueForKey:@"width"] floatValue], [[size valueForKey:@"height"] floatValue]); -#endif - - return [[[[NSApp delegate] windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"(CGRectContainsPoint(objj_msgSend(objj_msgSend(CPApp, \"windowWithWindowNumber:\", %d), \"frame\"), CGPointMake(%f, %f)))", windowNumber, aPoint.x, aPoint.y]] boolValue]; -} - -- (void)stopIgnoringMouseEvents -{ - [self setIgnoresMouseEvents:NO]; -} - -- (void)becomeKeyWindow -{ - [super becomeKeyWindow]; - - [self updateShadow]; -} - -- (void)resignKeyWindow -{ - [super resignKeyWindow]; - - [self updateShadow]; -} - -@end - -@interface NSImage (Additions) - -- (void)drawInRect:(NSRect)aRect slices:(CGFloat [])slices; - -@end - -@implementation NSImage (Additions) - -- (void)drawInRect:(NSRect)aRect slices:(CGFloat [])slices -{ - NSRect imageBounds = NSMakeRect(0.0, 0.0, [self size].width, [self size].height); - - [self drawInRect:NSMakeRect(0.0, 0.0, slices[0], slices[1]) - fromRect:NSMakeRect(0.0, 0.0, slices[0], slices[1]) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(NSMaxX(aRect) - slices[2], 0.0, slices[2], slices[1]) - fromRect:NSMakeRect(NSMaxX(imageBounds) - slices[2], 0.0, slices[2], slices[1]) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(0.0, NSMaxY(aRect) - slices[3], slices[0], slices[3]) - fromRect:NSMakeRect(0.0, NSMaxY(imageBounds) - slices[3], slices[0], slices[3]) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(NSMaxX(aRect) - slices[2], NSMaxY(aRect) - slices[3], slices[2], slices[3]) - fromRect:NSMakeRect(NSMaxX(imageBounds) - slices[2], NSMaxY(imageBounds) - slices[3], slices[2], slices[3]) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(slices[0], 0.0, NSWidth(aRect) - slices[0] - slices[2], slices[1]) - fromRect:NSMakeRect(slices[0], 0.0, 1.0, slices[1]) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(0.0, slices[1], slices[0], NSHeight(aRect) - slices[1] - slices[3]) - fromRect:NSMakeRect(0.0, slices[1], slices[0], 1.0) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(NSMaxX(aRect) - slices[2], slices[1], slices[2], NSHeight(aRect) - slices[1] - slices[3]) - fromRect:NSMakeRect(NSMaxX(imageBounds) - slices[2], slices[1], slices[2], 1.0) - operation:NSCompositeSourceOver - fraction:1.0]; - - [self drawInRect:NSMakeRect(slices[0], NSMaxY(aRect) - slices[3], NSWidth(aRect) - slices[0] - slices[2], slices[3]) - fromRect:NSMakeRect(slices[0], NSMaxY(imageBounds) - slices[3], 1.0, slices[3]) - operation:NSCompositeSourceOver - fraction:1.0]; -} - -@end - -@implementation WebWindowContentView : NSView -{ -} - -static float OUTlINE_HORIZONTAL_INSET = 33.0; -static float OUTlINE_VERTICAL_INSET = 33.0; - -- (void)drawStandardActiveShadowInRect:(NSRect)aRect -{ - CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; - - CGRect bounds = CGRectInset(*(CGRect *)&aRect, OUTlINE_HORIZONTAL_INSET - 0.5, OUTlINE_VERTICAL_INSET - 0.5); - - CGColorRef shadowColor = CGColorCreateGenericGray(0.0, 0.8); - CGContextSetShadowWithColor (context, CGSizeMake(0.0, -10.0), 100.0, shadowColor); - CGColorRelease(shadowColor); - - CGColorRef fillColor = CGColorCreateGenericGray(1.0, 1.0); - CGColorRef strokeColor = CGColorCreateGenericGray(0.0, 0.2); - - CGContextSetFillColorWithColor(context, fillColor); - CGContextSetStrokeColorWithColor(context, strokeColor); - - CGColorRelease(fillColor); - CGColorRelease(strokeColor); - - CGContextBeginPath(context); - - CGContextAddArc(context, CGRectGetMinX(bounds) + 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI, M_PI_2, YES); - CGContextAddArc(context, CGRectGetMaxX(bounds) - 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI_2, 0, YES); - CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds)); - CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds)); - - CGContextClosePath(context); - - CGContextDrawPath(context, kCGPathFillStroke); -} - -- (void)drawStandardInactiveShadowInRect:(NSRect)aRect -{ - CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; - - CGRect bounds = CGRectInset(*(CGRect *)&aRect, OUTlINE_HORIZONTAL_INSET - 0.5, OUTlINE_VERTICAL_INSET - 0.5); - - CGColorRef shadowColor = CGColorCreateGenericGray(0.0, 0.5); - CGContextSetShadowWithColor (context, CGSizeMake(0.0, -10.0), 40.0, shadowColor); - CGColorRelease(shadowColor); - - CGColorRef fillColor = CGColorCreateGenericGray(1.0, 1.0); - CGColorRef strokeColor = CGColorCreateGenericGray(0.0, 0.2); - - CGContextSetFillColorWithColor(context, fillColor); - CGContextSetStrokeColorWithColor(context, strokeColor); - - CGColorRelease(fillColor); - CGColorRelease(strokeColor); - - CGContextBeginPath(context); - - CGContextAddArc(context, CGRectGetMinX(bounds) + 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI, M_PI_2, YES); - CGContextAddArc(context, CGRectGetMaxX(bounds) - 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI_2, 0, YES); - CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds)); - CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds)); - - CGContextClosePath(context); - - CGContextDrawPath(context, kCGPathFillStroke); -} - -- (void)drawMenuShadowInRect:(NSRect)aRect -{ - CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; - - CGRect bounds = CGRectInset(*(CGRect *)&aRect, OUTlINE_HORIZONTAL_INSET - 0.5, OUTlINE_VERTICAL_INSET - 0.5); - - CGColorRef shadowColor = CGColorCreateGenericGray(0.0, 0.5); - CGContextSetShadowWithColor (context, CGSizeMake(0.0, -10.0), 30.0, shadowColor); - CGColorRelease(shadowColor); - - CGColorRef fillColor = CGColorCreateGenericGray(1.0, 1.0); - CGColorRef strokeColor = CGColorCreateGenericGray(0.0, 0.2); - - CGContextSetFillColorWithColor(context, fillColor); - CGContextSetStrokeColorWithColor(context, strokeColor); - - CGColorRelease(fillColor); - CGColorRelease(strokeColor); - - CGContextBeginPath(context); - - CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI, M_PI_2, YES); - CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI_2, 0, YES); - CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 0, 3 * M_PI_2, YES); - CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 3 * M_PI_2, M_PI, YES); - - CGContextClosePath(context); - - CGContextDrawPath(context, kCGPathFill);//Stroke); - -/* - CGContextBeginPath(context); - - CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI, M_PI_2, YES); - CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI_2, 0, YES); - CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 0, 3 * M_PI_2, YES); - CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 3 * M_PI_2, M_PI, YES); - - CGContextClosePath(context); - - CGContextSetFillColorWithColor(context, CGColorGetConstantColor(kCGColorClear)); - - CGContextSetBlendMode(context, kCGBlendModeCopy); - CGContextDrawPath(context, kCGPathFill); -*/ -} - -- (NSImage *)shadowImageWithSelector:(SEL)aSelector -{ - static NSMutableDictionary * images = nil; - - if (!images) - images = [[NSMutableDictionary alloc] init]; - - NSString * name = NSStringFromSelector(aSelector); - NSImage * image = [images objectForKey:name]; - - if (!image) - { - image = [[NSImage alloc] initWithSize:NSMakeSize(100.0, 100.0)]; - - [image lockFocus]; - objc_msgSend(self, aSelector, NSMakeRect(0.0, 0.0, 100.0, 100.0)); - [image unlockFocus]; - - [images setObject:image forKey:name]; - - [image release]; - } - - return image; -} - -- (void)drawShadowWithSelector:(SEL)aSelector inRect:(NSRect)aRect -{ - CGFloat slices[] = { 40.0, 49.0, 40.0, 49.0 }; - - if (NSWidth(aRect) > 100.0 || NSHeight(aRect) > 100.0) - [[self shadowImageWithSelector:aSelector] drawInRect:aRect slices:slices]; - else - objc_msgSend(self, aSelector, aRect); -} - -- (void)drawRect:(NSRect)aRect -{ - WebWindow * window = (WebWindow *)[self window]; - NSRect bounds = [self bounds]; - - if (![window hasShadow]) - return; - - if ([window shadowStyle] == CPStandardWindowShadowStyle) - if ([window isKeyWindow]) - return [self drawShadowWithSelector:@selector(drawStandardActiveShadowInRect:) inRect:bounds]; - else - return [self drawShadowWithSelector:@selector(drawStandardInactiveShadowInRect:) inRect:bounds]; - - - if ([window shadowStyle] == CPMenuWindowShadowStyle) - return [self drawShadowWithSelector:@selector(drawMenuShadowInRect:) inRect:bounds]; -} - -@end - diff --git a/Tools/NativeHost/icon.icns b/Tools/NativeHost/icon.icns deleted file mode 100644 index cd9ecb6bb8810528ef1b89898a30fd6f8c89e963..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81151 zcmeFa1y~%**7rNs5Qw`Q@q`!&aUi%8g1fuBOEUuu&L|A-?(R;I5CVjt36KzXcbQu~ zGdVl^oSb*R-@W^s=RVJu3PV@_>sQjNYIRSoz+i3a;EF<@V_Lf&6F{LbE25d0?3{dJ z9+aPxot=;(^3CcL*hzNx7q1ZFacp~bZ|M&V&bHMPZo-b|*8Pi{F)&)Hdz zR-WtQ!nCvV$S87hEGlwzD$4M%v$L>pNeRj0N^!BUFfwu=GH?z?M!G8Dwm21C)ByqF z5wyU87*sS9-P0T1hw6oUP?w39pvyfy%#IG?eXfoUCbPL^KI94ad`mNvSyw*`KSaYY z{7`eYzK+Q(ub#SdXV}Yg_|BcF@;oN9uxxB@E-RUlH8(d_kj`Xg<{#gPI6 zyzRrIaQ5D))8fSQXz|m?STPaNvBVfCHaa4LOeKaxRB{9}8c!_e!bb!11Z0Plac2h* znM}M-I$VfWQi2OL(|zzvrk`h0P7X~(n3j{1=idbrTj(yaBht<%!zRu)XAvt0}$ zUfRx9I-U_@X2fJ_8-!E5MAg(py(r-Z+Duhdo#1E<)#zwdjp$$n{}%Jr1JEeeHRfcobo)Y|)x)GCBRIWd1q zPX8azt^cY1FV3xh>W&G@|4+}|f3EM2!fI4B)N@ipg$4$*XbH~(PU2az2yJbLcm^bw z#!Sc#V!hDWx%5JGE;z$v7qwB#F>OWJcqY1_l-hwVEgc_nq^tC+fyJdn>Rsv%#& z)D-1_d}cuv`7)-eAQR-%@+-)Fn2P)~kWbDn3+cfo%gZN+^kB+zlYx|wT@uobbuln- z3+cv`WG4WLo>>&!3DxP_+UnN@cVdd-qku@w$PaFVqD-9}OrwI^F!`iVAjYQV1UEw# zmPCT3MQ}4FCk7A1sN^g{BX^deReFk*A;@B~A_IUNmY7bcyIC1l;A=3cp`M_?H8=@h$rEdAYp$znZfi`!S7MTaT|t2(J^^3O z<6vn=B9lpWmJaxGOak5!6xhLWK_%EM0~>E}@U}6?3M#?G!FHg;%AXcggbg&ci3NvP z8`Hp`A`H#n3Y3`pQpg1uimy4yn|PDRc^Hzn3Cx617(>q(at~1S@hLD(C4MWY4Quq^x!3s?;MyUKf_E8bb@?){{;CdW}?3xC!GuqPtq`L0mko#CN43k6dV}`ryfK=6aHTW(x89*Wh zOa|Y@Tx}`_Vp-dj;CZMxG@c$>96XP?Qj-hB;+Fp4TTp0Jaeh>2@GVS#6|!XVn|cYe z+?Rr)yE~$TE)ixiz2&Ju&S~f-+~7_MBTY|{!jlL$Fx{nzK+dS{#82^z!O@JeGDb8! zhM&T87R7-AN`52#6(i6Yig<~kumr&OiNA- zD2T{v3L3@s2F9j>LnQV_H4=2}<2Qf9tFlz?=6RUtnR3-X@`SD>?0FS6(_<+1;d^x!SQy%XLX3&K}rJ@-w zAZKbyH3r`}^A`c;54_M3QFIDA3gj>mv_dKaQ%H-zgDayKkP9&dbmU@4v?OvBCW%G@ z`DjW4xe}8=i3a&dGJ{->VUQz1J}j0_F2T@a!$3YHni^7sB?t-`BS|6o zSZ#4}osfJCDH3s_z=)XOTqsFQK|w4jI2RM+i>!RVu&CfH$VEz7Ny;S{tVdU5ZF`4= z2d6`dvexFZioxlaa3^aZx(A06Qn-oYas*gToJdH)ggPKA+yze{Byt-`Ur1mm$ruq5 zF$6nfAUpWL_;?90;4Ihtztqnkdj%5Iz#^WlfAank_jDn;ao`wmq)Byz= z=Dv6`kE*Pqv#YDKf~+c@jPW(s00pWh-a)b05OH~3aL|<(4+)CJc$=t#5@jQgpeU@F zl)N)IILk|!1w~;zjFdr%f`J=30^??&0P?bWE@UFcMNgJBgHk$9< zuAgt>f8@LNu!)YTf0H`c<#+$6^5@*$|I5qg|Kj>@|No=>_Md0%k2B8r{_ieFFM9BY zMgE+7uo#U(^X$L&^!1xxq}NZc9pFKu7i>HxDkl1iBqn-%6E|o8i^XDonLq)Wy+Zzn z@78X}JF4BA5aj34ePuq#rvA$dot<+h8=b={p)v1e)0uDF8CcG(Nr# zsHy)}O@Vs;#P+}`fK5i!xVVzhL8v4yuI_3NocwRqBHvDE>V+Rsu4*eV_B9H=6b^GExkd@{LepcAG8mIigO z)jqb`0n>m=MN|?gZ?q4}Bax~GI$$bLDNx7dN}y)-q8vl?QI1)?NNMHe4wwQ;$x!>{ z%GlW4%pOdoq$EKKBPm&#*#qUq##UZ#hsl5-L2Z{SVq$Ut5hSNbxPVcV3j#z=Oiab) zHkkAik#PyzrJ<%x(8Fr0X>?^=`k9GET8WO%226&Ez8S$1Yo@P~0hnyC@dfR~f_7q{ z*8XyY>BhQgnb{KTv9@MfZW-MOQ{LYS#{ec8VWOh4(z|g@Y6e#J1P7eGm4SLwdN-66 z6@^gIfQo`z`^q9CGt;}UBy|&;5C^P{i8?903(Aa)EbD89qW}{LwXm5^thtW49boLh zF};(;beF-AfQf*b`${7sGSWJ6#VUqY_8~}bhAPErolr(ZL{b(FjsR5n52^zTYns{; z9k8~hns8bN!XyAD957)}b8ks_czS9Fu3byd(vIkWv$NFGYESKe(!;|UnN&CoP(-My zw*;4oCzT>#!I zCN*K>fjRLGXuANo3Df9|j2l=s9^i=t0wpC1h5;Uk;COsOQX|#@SQg;6i9wC%DAria zwH=Zgp#(ghk`f6A0y+SyWzmU^xH1)B;~)o&y|vD;Ry|BFJv&bCK_Rh4G<$J2%-G}?FZF#<-u@#Vm;Q7WpA`?Dxn@t z2lar-bqy2ip?DZ3C56L&fcE9k3H7*4w#hN}4mE(UWSIt-Jw1U_Aq@5f6?~xT&fLJj zxP&^aH}ExNFd-pzXqa`aW?J3}bx>SjU~D20_5rjvLI(uU8MU}d4VK-}w&@|Y=ww#w zmU^0%j9Q2u5D)`+Z@_!~gU3=>hR4`D)r8byY8*M1r*Qa$P}mFbo={b1uD?HxQG>N% zTi!05Sc4AZSl)(F1JV5bqZ2}4Pe6M>l^r>Le$@DCTmfQvU~U^bD?^>j5?M4h5Ewq#0qtB8S%xlgMy|?4 zBalrKss1e59s;z7M>MSzs|PF&Zb){-=u$KhuzJD8b>XKqTJm>DSogW;B6saHeZ5uK^`#bl>&uQ1Vy;I z29vyCD?nQ!w2MnPxd@l43T%#CX(GTAS!1y>P)#KlLE$bg2yY2^3&=B;fbfM_qNTGJ z!3XW_OD#nEdJ}xGUe1<8av?$!Vm)DtAGEV`*k~aX=Is1KHHSQ635Z(2Ry|;Iz?wns zF?c5@B2bA=PWTvi*bJzqKh*pmswq%SAh+lsN5|07d??h>F(}#%HUX+J4&PM!CR-;mmLpYyde& zvh*C59_b7l(AjE$ogHB`2O`+n1#nb-$SH!QX0y}?Cs-e_dXQs;zpX8PG#kR(+WJR0 z!g@ceSwE|~kVCkijZM&K78GP-;}`A#>jG8>vj3B659|D_X0lnfstwtN`C41UqnQwF zZS5Oo2W!(&3pBN~e#i^hvX+)69mTEA(Z>S0S+JItIvoY6XlmLLeWt7+AEK?MrV3CL z|D-4YMOs6{hKQf?h44fh4Gk$e3M&SbnNTb^6QiRrLh9;s));klAvy|m_KrI0EI6LI zqlP*IdgVKL{MgYWhYyV%i*0F)P498EB|2TBkBPw-;KHZ>e19J=FzLWa5pIH#>_pKm}0dZ)=+z{Q^z4wT<7OWvLx(b$s+a1PT$g z1F#%*bo2!@`iI&M&D$?%h>&! za4TEA_mg^$t+qfn?p<$gX0gr9*YDkcTL9b4R)ARzijYFePp`pgc(Yw=dBTyUuMQs3TJv4RaT0_It(I?Q=hK6f*rr>&@)&X^- zzJ3s>gZ1?zK&@k`lYdetS!yi=)VjJWqmQ90b#)_mCgEDZ)Gzm7rInd)_%DjE&@~`bd5t{Q$0e- zL^_rn>YmDGTKntZLckP2BXa|#rQNA_aJN1DBB?|=jvDFbaXa-6)LmNI+FuJ704g6E znY~<6(gmnS@SvapiUuAM&4B7EDQW4ef%5^C2My2kBh)-L#w&~*4*Co8ibQf}jl5NqM-=$1S@ z=opx+DCIWPQB>5_Qw8S$G#eV4=_@P*C>HjOpaubmHrWMgV5t#4Fv1oVHuhA)thfkt z^=5BjVSDl|T(4753@wNbQL}H|pn(jI78B&un|upu2l%B5R_G)X!3zoij!gnK#M2>i z^Q~J2RM0j#)FTOj3kn)8m9t|f(BRG9{QS10IowS*V9X#o7mYMIH`hY~;|6ARznL@# zwdLp6gPkT4TSAZ%vxT)q$rn7y_D_3D06?;#i{rkMg>tS*R6M=qhD}SkjOR zd3m4$HVRl6n1tLKG>a~$Aj1jsibCkTygER$gDh93FXiU8B+lSQ9DuEZ=olJ#Drg2X zL}Ilc9q2HUI0Loh=GJzWumUhC(7<$ePEIqZk%!nE8Bi`^2A#~ZDKLB<;G1)DYCDTr zL71c;{7tMsFgzF!sgrOMT@OYEOz-QTcoU&(I*K>}m&?=L+1X7AH*wu;(_?7VDZ)+6 zIGHsbVExX7n^04Bc1=eiCm7Q|)s>aim~aEj@FXJFODzbwfzD=`pXkX*xB)e0WmUHq zu!1xUsDG+6GqZtl12^I39|gvYp^+{Dz8%!WQKS6bCKxxMhRn?B_IysHrjK1=8dt@( zKZZu13Yo@Cv6lmwfGWl`QlqLZj}yh|o9xKQsAo)J!@OA&Kq(FG#4cBH4dzXqu{ ziOXV716Z1PXA8U`WMtujM;0y14Km{=k!lq!Ih;^Xc1uNCT5bF!)|WLKpccW?fnbYs z@Fc{r-NDxv)TvENt7ysQ1d6hn%TrTp;wEsd$egeoEP@b7@W%xbA`q`*c|~j71XPon zTHc(+2_R)Pm!+hDT39NW7Xlqiqmp7mqOdU}D!8p-$wW^YQX?g$4Afu;lroz@jcWQh z?wSjjn-F?9a@V3p1-M+Jk3-dfY|3N>mSUld#?s_uge*ZOB>{{8OhhR{B`23QW^lqr z>5U~xNmcYQY^ZlQC76y%1DlbwU^kb?p=-5kR^9^a7KvG&mabjX6?K&=%edoc@;;%(s$6SkN+b6^=m3AGfOiU~W zHP~UL)cT@?gbLbqtT(Vc=zv-reH|}-hi%1NGPgLWdhRa_T6q9=w$X zZGv^$6FrLQ;n*ARR8Jj+${CEJ`V>~MDFRBVD`eHcl3Dgf(~@IH(a9WJli74(9h(k^ zlIsfNkW9`7Dm#ostH>ge z3P3ozfJDlwpmD-Q)IX_IPE3eWo*5gP4?@iOv9X!u6xg4&kMV=Zf6~by%7X$iA)v;@ zu;`eW%yPEs3z5n)Vq)?@=s7PYCZmi50z4=X-~noMG)s++MpPe`8e5wF4>i3smZf?_ zK#hvZ1p(>Ys3=7B2CNqp^CvY1glbSAR1;m278#iX*qq47w328LlKDyP|4Cio4)*bE zxPJi~_V92AI|>&MkEr6*h={Q)?udxg;wTUBBRVL^5$xlOQ>P*zpt!p`0>uLCy*Ucl zWt#)V2q;B4Qz=kR5l{@lK1Lhtpl6D(V5barP8d~J*ST?g@Vt)LQUX>9Jz%>&WlM%%N_hm>EP3uzV^Uf0pMCh%LnhH^AWX{MP7mP|4oj=}k492=A{{0>n|Pez5GQZFN(cmltWY3L<%Vr8QNvd!HK1o*C&H@Hd=zjc9QGM zIRR6ky1KGdS64)32S!Geki|-iodIV^d?ul` zgcIKc42aKU%P{Jw7iV3BsbEslY z{Ia-~0irkQd00;&N%;^Zth}UBEWk%*-WR8+%aa~s_m6ZqV!ihWr+R`#0 zISp$DtcO>E6nxXtERm)aq=e0q)1UxLO9W;I9&;fC@E6p-E zS|Ny#g!V)R16HbZV$u(q9ox(uiA)$>32P&@^!451 zXjnZkAHiTTDaeJ$V&oJQgOSxItQSXv-1PMkUK{XQkh!OwzP>A+iX#aFPY6{af){c# z6eiKBkgLAFou@gh1xQWE%+pR!50F@AFc(RzmG6u&dU|%AX0Rrk@vzm^b)i$R$|5qL zca&D7HA)NVSw=*ePJvu>b!|P^tOjI?u+B6xj)+(vz&?>=ly@*<9PzWEG&1Cj(5A2k zXjvUHaktUY0W{VeSUp$?eK9tYjE=pCv@IoMj?g+fHtr^{I-u3qv=fbll>qhzwrkigx5k7VWGDD}mM( z0d20XZaW$Y*{Z9X162{I3Xm>ajbN*~umVu!Asr_(H8q>j2*^fF&CE#$mj77||5=rT zv>i=VRjo(EAZt}sQ%7xB4zRNSqRIkQ2GVjcQBkoPB|=szDkctEunbV8ALq3m42sgCX+^7mV!GUZY^^_~0O?yRi-?>A$}wSKWoxr3eaOsOSy=cO*r*%<%8WG@ zoE-rh6@DS1xeFK}A%3ty*?&g}wI3Y!-8qNa2YOw%ch}AxeA~B=ZR6g)oo~m^-Fw&l zyUmFk>t{sI|L=ZA^ndsnv)@I(E%4g{f2#$yTl|O8_W#u|E#Ca;e`Ei~lQ$NBJ%H`t zx5oZ+sqU{#@SnSQ_C@{ACfN8Ny?FKr>Nft{NjTTk`Cmv)=l39GCIivs7@^Ab9dinkN7c74=*x#J}ZU5i)|D^?f-~aw*Py2Oqzy0r*tM8wF!Ti^@ z`#aR%_Wy1FUs~Yz{qOH^ufJ^LxBvZe_5Hs8{r11V^qs#0`0anc{qL6+`0amxhkN~H z8^8VUm#gph^Y6F+{iW~x9l&q@`|W?fw7_rw`#aq0FWdO-f4^LPzn_1<{qHY*=kEZ1 z``>T>`=teb``_Q;UVqufZ~yz{>ihlt`|W>!={tW1@Z0}>``<4u@Z10X4)^-YHh%lx zFIV61=ihJt`%B;XJAmK*_uKz|X@URC{SR&PcX-!dw_)>35=wEzx zI2z0C_}}QA$#h(R!~C-e&{!_s<(~hY{=HT#)V+ zgY=7-0rZZAxEHV9v@h(x(|_2$&1;tMKo~FrR{t0r#ItzimOUpa|DFCRC--h$4FjVf2aTW^M`k?U%rqVVlP9`KhKht8}|r^fj>a?-$)5!$M$YswSft3^$!9kJroh|&o`p#~E(~7*jtfZ*WiKF}ZHmzQ|kQ>ML z0O0(%1q+w0S-*vE_x?ji1UP>W<@j-sInMh2%fFEFzZ2OF{G%0tBZv0y=G(G<_0mNP zaGZM(SOACzEMB^Nze&>E$;J<1CYttjAP$zU<(U`99OjU+T9v`hAZdF7DA-QtswGIzm2ioxVS@ z{UP_~S7E)=cKhbX7cL%OUTbl<^6@=XpRm$o6_1SFcPw&M7u>i5K5i#PD{=WD$2z~Jl# z4+-fjH_|34L+uY2j+ewFtw~nb{H&5U8FQa6TAyBzm6_;7&n$WTJsGujf8%{O&D{-8 zj%{yTT*|xdkmnd#XM2tK>hHwfTlQOnnnke73{+Ap_%}aw?|p11nb>Sh|sIL^@Lit7`5(GnsQPUV2Yn>@BRLCkB74}@AJtA!;(afnVVCL;$lDCSNI}sw6i;J^Q>&hrkLv?YbH4!X3v;Y9kTOI2fDFJf+QG*aw(wwE}q$~`S%NcS<0#)>b; zFlMq+BX4?HPMoK|>zad6PdBxGCavJQ`b6BUej+bP`u_U^Zb4%43Cd%HF`$ zc{=ZO*E8R=l*8Q9S1A<@>sFq+CT=|DX=#y`Bowc7KG7;yukc{yxeI43XL0kuc4%%-@!-e#%I$3xHXmkghi$}Zyi1a9bK-!C+L+~PvS7peogY=2=X(s*Evrbll;V9txweL7L&`2aRY$Tj z{ZH^oNC#b-Cc%q4Rp)PNJk8r4woXIe4_?I-7}Pm+)HUo;>n_#dU9aup!?t*RX4a3y`PH!t?{~fxXj&{Y^}tx* z`fD++gM-5^+uwGj74&9ZxVrs8{)0DZ2lGF8>3m%q!#8rjG~S}J_)+fS>Vq%H=e~|# ziAvftyS{(KPIPFei`gZfbaSt98)2W#_qcG2j*)}~KTf=UYo7ViCWYVSmE2*!bnkP@ zec9dqz7}7Dp7^T{xvnR7+AuLpdIi z&jK3tdWBmfS6U|P2YpSXS&Uh-8#bXQ{N{D9l(ae*1g z+wFq1$G3qc&&|JeUDm%A|LsuDC+EHW5& zqCLA#?7#p167KRCwJu@w?Cn%*ezz%fzqRYx5p1&H#Is#jzS{Y(DTq5`b%(iD&1KsV zZUM#V!kCPV24RVY$iqEu&X2}*zgwQ#@Zi!%ib>dUzc*fjMMskLn2z^t1A0j#J;?e zxOgZr>EPzXx^^a?RVP!w;;C8|We*hTy|zE|LfSQcf6=q+qxhU%#_nz3I9X7*@Sf@B z12=V!&DLgfNowhA2wn1GzSA9abeR z9`w}x*dsJp42wR0)wptO<*j3J$6=3TA^hPugBoN9m|c3a>@SE`K8< z=fOLm{jOKXoC}|`UB__Y$!MbD*lZFuHvs%S4T)vXpE3>fJ8iZug0$+7pAx_{^*Nq? zxp&B5O+O$0?W1Sw=$d>bV(LN#o{5iy`ot1=18PrCwS~+yZED_R`u)+Xt1XNeb6833 zZ1<+AJ1Md| z6T0RfWayuH)*~>!e{wE}PbTFhr731$eff59UpEf>&_@Wqy|lR?WRtVtgMMYSTyUw3R1erhCdDv34DKRaXuby;%hi0iAm&}W@ z>?3`W-XF$pNxTd+q6b*)N1-;ldOb`A{ev&^YZBk=$V{qAcZ*@T#0~x>&C#phs488+ zEDVy$TorY_yxw5$4tEy4I0|><-r0$H|(G{tma?Jt&1+TND}oo zQ+u;uF5tMo@nvQEex&)BLh)4L4E&HX12gV5aq0Q1vV_MQuRc93_TYwO?S)k`s}D)6 zE-5SbJMRrmuX-M3DuC`W66ikGzqVY;+SRQ==-`yr-f5Xv0|JL9oEg(HBJvf>-sn=S z7D;^DHk~1cE|v1b#O!LhDesRGICJHZX7nSqnQb}eP7Lmfmp9*nYW#F!pnMy>QAvXT z;UY6LS^Jagt}7V6YSJ;YG-!Teqm-S|{8@bWvsJ??2TiWdKIe{Hoi)hdn#v36ODP_; zAwH&;>Mm$)a~lHkg1K2O#g(!+_l)UvWelgVntZw>h^kx+JoCVMR?X6ITC-H zZp!aBF#}gR`6XlPzmfF6o}2 z&Kc9aQu5c7XdY_v@)3`b`;R|otjwzE z<66f3)*uJUyEnOHv3pK`mfDj8u>@-iQ~i>~S=K74Ek%ztGQCOR>CW4-T_2xzno)`w ziNqJ1mzeB=xA&SjyT7bGDs#HUvcx5`5J6epXUKldw)9#+kr>cDk+~W1kq`Z#Is4JOuEn=^2@jRTokBmC+-%>|>=?Go=G4h?Oy~!PfEQfFFWo5L zOZmTt;uM~c^!!I{M;9O0t0Z4E0-sD|KzC4iQr4s8JjH!&<#I2W6r4Nz^y{^*4SBE3 zm(gN&?Xt2t4j<_h*ago_?;`{!7etFBcT34@9vFmaIr(SjAJ!!bbRVql+@fdUv8EY41LEK{%*AL?YAbL zX7%D%+$Sq-XXaX*uUc9juNDN6(6ID;z7b#FN*G>5fLniaI^RX@8<5k%n;Rr52~U zrJc5%`mD9-FtYbsAzD;&`JTennrNj@1r?d$x(=zK+gsk(jK3JW_i^1s#P(qL%KhuM zQ`he+6y@^A@oT2=tI75}h@r|d`7PfcDY7|yRBE}={_kfT*SSUKflrAYJ`vl4TUmR8 zcO;GXQSl9PXUXUeWuCa!h5D0F>;PZu0iz|6tHFLSWlQM8yGs5WB2~7VA0h^C$WX!0 zZ`}S>{pQjNs`P@14Krunqe6t<73uMm``6elx#$&~x9b}CaLno4*MdxeakB7qATH~z z&v5&pD^p=hxAgBMs8zf%^Y15iZ9H{?^0A(ew2E-mP3_UphR0GdLRAT=yTm-l*BzCh zF8O4bh!fefdq-h|$Nt`1FSZi=M6gb=nVlO6rMqk3b51!ApWG=IEz@#7Tq3yqkdm5M z(?aw|jR(p!fhZT_hi^M4AvH6_jFpzRMT8@d%9`Dj9PinEEV0(epi||;Fl9x;X|B+# zC$@xAgqH0KdS|72Wuqg1u)u7*h1jsSq-FS%;DeI)C5&Ik7Y--fzqsFR`IaLK@VWl! zmE?z-8C+bs43_|Wi_dwkWmRF_2W}62nVzcLn**WqeR^Y;bgxWGwp{pD=Gyb{Mfy2$ z5eZ&%+d60$#JJ=n?oK|_NKse=o){*2@lxXZ*W#9+lcU=XKDa|dp%!l3rflH*zHJ}h z$fX5C0@1IF-oCl?*839w@O?{q`pYmsna?M7br8%nid&*9b zZeX}>)Ln;oZA8{a?fpnm96!GGHjhY7`q-A4C$cyT`r<7wg%ji4#0SnQY+Dr~7q)bx z8Op}_-lyzuE#v zs!gQK4olwsXEaA0&V)_ml&47xIveu8%H(o9FD7!J+wTLneYs$1bWu^NLtN(B1e2i? zyXgve9c5}vn_GAuie4)`yN9A=u2t+kWby*%BdV^sEN`$C?g!GhAqZGr_&C#Ze8>4Bn$ z2rEy!bOcX9RHq|eiiR@X+#{=QiZ-w9&^3*0*xz)WP{pbZwqJBM+ z_Br;Jg2zJCPTb&mMt9B$&e9LcRyl2h(X7T>#$Jb@- zd|YmQbA&59T&QxvN5j|quRPJ-LyK*~h~GUebRz1Jh}FGfK4Qxgsxqom%)oQ_?TdwL zJ74x!&Iw;yS!uM?Ay@|ET)?-6f4ybMn}ALfs#CPJc^NvGP^ta3sHXS%fPaZjV$8PT zBSVAt&O}(|+T!945=%EO;fh_)E57-?;(Um?T<)D`h1Z21j~L$6l3r3?^h%{wV+pE% z&4#2A$@}leDr=WF5IR<`#o(?#a!xdO9%&@I#f>_>t)f^YXWgys+eDe?o4y|*d0R5| zCqvGo&|P-C`qP{`c+M)?u8KYhk3WQm6hvX)X3_aMHkjc&mo4&7N@i}`I|u3Dj2wa+QLx4r9XrtF%lt9O{% zD|~M5ds%(dJRhc_pBW51)%0#y^iuG4>~#DMfvvhXw!UHdm3Y?Kd>?ZW%T*)Lf?G7M zkmByrH#}T=@yC^cOFVw-nt#OJ^W{6t9(=!VPbRZ zWH@hrk#{4qJ8wLdrN~cro$yviPw)<1AC9?Mt0CdvtCbPMc3Y(`c?Cg4H?mbxd;QafZjOrD%ryxwy?r z#^jv%D`Giz$5myS)~-wHe2d3}S2W){BY5g|!%Ti$zIQY&`0$cROS_L|hn%|lulnzP zWpMLulCQ!t^(CI=2NFMY+LcKx{ZLI(oX>5(=NiX*{Av>4$EG*+f{Kk94mwV+v>w&# zXOxf*zC4xpsnUunbUX9y_s~9rP0p_c=PHtD* zZ@suEd3y}%CDGN;h8>q?1)`qg~dsi$PliP+@(4(jqcMV(g7bZIx4jy$!{iR$)R zO#1bP9tU0zUQ?Z_jk_|Pzz%z3gqAEPr@t-VQ4Iw_&yfINye+kC%Qb?`D)wGA>f znXvb{_dc1It3E#^rXJJU4NK<;XL(KP4{u!Wv09_U=oW9!%e0P|PxAYgmdic7zNhc1 zLf52W&#T2E`%l?s9ax;X{AjPV?{21@+ped*Pl{^PdVIR*=MDtgoTS6;m_v`%Eu~Pg zd-k`V>hhJrd};sc6M4kzNPkH_Nw{5JXt`pmTwKr&r31HZcI6I#H^%o4kG8+Q$!q3$ z$Hyo(CA4w7&c$U9kJs#p3msbU;+UDzrlN=}Je_!T+o{-eo$W$Y4eA9{Sm~KC<6c>x+ee2x87IhUcpa&@v9R}mdU++X8rY9)i?6uy-pf7s3%Hi1*Jb9ch1gO z{^g6hR)3rKpr^Q_LQcu9hBr000_gq3?r#?xicVq^Py*+woLj&`?tL@_4xLf zoWV5#TS2VAGxrw1$$XcO+!~RCn+y5&5XZLJFS4yIJsq5SLLl+&vZEpwHn}{Q^-mm( zc{=j)-Z4m{{z=@&hAO_=w^yI*ai{J&5?Q~b!YO*W>GdP!*^ykI61^xl4jpE$;IID5 zv`kB!)nCkgY{&a7cN^S8uh$a9;iuP5Xt&{~c-l5Y3oV}APmHjgXH?&AUfJyI@Y;R% znY!4P^3xY&+mjwOFFjwo{o7>Te%{Kq{20Fdnc8nK4t-}L?svaDj#52RW6-v-G@>l7 z{nO_v?1LxQx%;bO*4<~Y96J zZ{K5egQD@;=L7eJlC4cLVzcN53)6(n0%PCJm!{4yxMFg%YA5;J`M9=(%K@r|l%Y7^ zXFL1FY6b6@lw3a$dR~xw^7OHaL?l*dWVMLt@Y)%;1;!=f^)$X_b$UT zyW88Z@bHYf4tpxPzIj-XelH-PLi^T*Ck@}9TJ4v%@o?HkM^A=)m;AJKw%oSw`o0vy zCA;{GDu^$}l$V9CT!Ar_u$19ipp$sIG)7=sXYW;ssaI*-Wi{uVcPcJ4RS$b=Jp2Z=BH}~`;v`pM{cIq~xP{!NpPj9-r>$CC_ z8`W3`g@ppvuRn!7YS`gvC^-{ZT2wmnIz^@MrG_Et6ZZo70;Yw6naz~#Y(ed_KV0Eb zV)l(bqL514wBe=KIpvL43k^h4C&hUy3^XLWC%-M7yhC`h^ixpom)+BWirpdyFWmA~ zShQMO)XL-Yf@~>*){7CQ)CS6)oyR88+nPU@El(&A30wZn>^0fT_Yhv{q;SsLfrEka z50`FOYVDuF*zISC(FvPa>^XM#yWO3)?^SU&vC0i61pH|}Ge(~c>ate^&(8T8@+BOX zXsHPN)SmPXtFM&VV3@DFU24VhW8bExr?-W!IRwAk_>Z@2_O-!V7q`2=O*yD_LTWwO z?jcDsXe)E+?d(N&_zt|qx!)5|>shg@W1Gg&mm~WO?^r+gv=xJtf@StpxOsj?cp zBdaLgdO_9t$?I^*Yc($E{hO-%7A)6=<@*Jt)ss+U5g}#%QsLbZYtNrMwKgT?<7yEu z`+H7&R|MC{hmY^ED3W?NXZ!Z-sM{pE(!CuIf< z?!QXz^$=aqQuJ^V@?`=crTa7gvA9ug&e33Dg)EAlSzmZZL_2{`@MrrWc z_M<1AI*xFkJz5mS&wX3h{f*z;$-y^%Xx_%V#HDWz3YVlJZ+G)HGS|M!I6LqoWnzjY zy7E?km(m!2F{htdSwk<)T{e$Rra_>YTaA)a7+vSWarWKdJlH23m_cv7m_z@5 zYf##7S>nwmri0|_?N)SytBTJbU6dI(x*WbNE0wH&ZLnK;FD3bb#+|hw( zE{itFY#CB9%B~@oP=%@^<6v2EKE z8xv(uIgdiArqtLs74-nI9)KJAz` z;0ra1($zU6X9l$|J(zqpTBgOHj5WM7B=y9w3I_B>PQx}wMHn2(Mn&)-#g0_A!}zbQ zmltjOzMnDf8d4ok*jO6AGC# zydA!L&=2!41|%HDI3bSBlv0r}51jI?ob;OF!3%62-f*SM3j4+GJL^ww$>zq;qRcR7 z1*%{_X}oN9yp8$T2|uKU;GyH^22SKCb@Ngfh>O-AptGorPbM94msv0;2y_}`Gi*eA z+KS6QN3L%;ys^V-sdEkygYn>P^6eApUIgr%{ykASqo88Pqp{y#& z#Js~dTH~C5!eYA2)fC~FL7s&ZrM|Fqgc5h&&tvX_h}AZf;gfkimbnL}`Ywkaj|S4x zI54V0DXa=)tMow(20k8JfT(E;UT035atd!`Z$oX+Lotym0_Die$`QUe+}h2MHsv&m za-kX0<|+5yLIHhNxAmt;h!uh+yYj#DDZ`K#^nPU^g&3<{)AdfVY2_rlDM!g&XsIq0 zklbur9rgSbm6A{L8&Yupxvb%*hZS@kqUoc=nXzf2h8#Lm6#>p>69|zeLvOu+B&2{C z^R{2{aK*x1Qh^Y@HJaNLdzfyGz@rFC1E3EV(ef$dMOrOFc099KU&x{?bLH)83<5|D zSUvwv#Z-cirp@Psn3aayP0`_vx4d_F@wrV zd|Xe~IAfBy7mPa&l`@*__5M!1Jlzi*5UF>EJT>c^>Z5UOF-zRMwOIcIMd#4IC;KCq?Z6EQ0SaZ; zcTN_D5i9nCi#NYjbIaiPwiQM!mhU5gU9bnA(?nfxL6>UNbJ>H8yh#HEaFYa^t|w&oT5m*# zOSlZY&xV0k#af)Wc|1172(2ZcZB4c@u!u}U8AM-4)%atu4i=nK0n_0tL=RxJzpF$@ z+9MB0xJMTgIauv!Gm17wdV*hTVn+6sj)qJ@dd1d(d&*UFd305$%!?`Gt$$7GUTV`4U9tpP zhWoX!zSLX^z z7X0NFiQaz2$V*(^b-Gp@zDgSZ9*S4Ho4YFYX13&ZvnlP1AZT@sL0PUz$_O>q1hZxL z8?G)z{P#9kAUV(dBch{Uxta=FZ{}B*Fs&GbR+znH*Tvr{Xmye*86s`6r5YM4c$KDE z?S^I2T>OkNbFy+#cN@A+LH>IpFb8^Q{f)z)L3J<~NbvnnjTSkDD`xB?F8z6JRF^oe zUMfJPlTregZIh?4G08eLuL_7`Ou)^aHu_5b8z2G$qYd#56}2C2ZE1pj+lPTOvOc=R z*UaCT8X6&`3tyP93lj|)GHs?$=%a`g4a{a#?tj{TfOCil)8RBJHh$V9`JrfIFVI8; z=(B4px@df6k>w%@@UJSd#sHFm&u4JU0b)bj;sS9y{ zzOVcn^k`QCtHPXG?y-QwwP7|m(C32HwlgwTGWo{Lw@qibEn>f0qJjregul3p4dC0Z z>Q!jm%@b?+nUP);>Orq2#by645V93kz)4w%t+A1yc+77Ss>g=%UKRW1MkycEgOsid zE{viRMf`b4d$k*=Isg0|002SEL@%cFW!TStWwtw=`Uvd|lR^Z>oKPswFRkbyu9h~19q+g2ABN)bnnNq$q#pNji; zg8+IYR07l73x}C)xPlj{i6TD9#Ix=vg3oP(qK+|pV?d=_&)Ip05q;@^Z!bp2xy|Q1qldncoW)|PIT3Uav*eV z1d$azuJYG$J{wDFjNI45a6uuvS$tD(q8M+VxTR#0q-;;+fv66UQ#Ds&Rl zLdR+ex?i%+s-Uvh%?il{#Ka^|BP9IzuoKi1O=pu**alRCf;R6-4RYiok$Xdaf9`VO zou&E$qym5u)4Arvn14sY|5OV6>k31nqQ=~|0JiBejJgsFF8Tem6tp#UvVEzl8Q{S~ zkMrL#_wH#7(V;%dlJWS6qM&H9=0nR0hU{&dof;7n}d|1w9h_@*%M4 z{SJT99CP%EqJ^5UI;28aLx@>hA*d`g_HcP*EOD>S9xJO=clN zbbZkweZuPL^rCtsB%qWx0VdMEa}{!m>>^wqMG#;WZbvIKw&XOl2_Ex(j z$3&i?#n5&=5@TIjmo4b`@WItU7mWaY0&u4C0V5DU`uF!XJ{L8wx5Mg;6E=MaxlIX8 ziK?Tz@1h3wUm$waL_L%2 zxe%H1n3yKlP-O~G#d}C4@6S)RTy)lrHTT|d;tOhD`B-hV~*V@w^E z4s6-NMO!nv(#e9exGKrdzR(t1$8a|u!lYiWXRa|mBp|9J(?zX{-k45Vh!qN@%Uq;@ zZh%vB+GC!tLtT2rA^d8_m(x|iKlEPaiav=DB?3A9iGGtk`@6Hk6c4l~ugCA>B2Ny{#b*l}}#yq{>Fktptgdth-Wu8z z@@|WX81Bpn;}#e7f+ESFSOu)K^82hC6LQ7?mCi>jC2hN0@`x_1H%TS@=pQzQE*&0_ z!<{IGGEH_YJ(tW%=L%}A&LHOJTW(W-p%)gUVwSb9N(Hu?)+6M<9jQUj-&jMUSox$E zL3D3m^;0*-htoe|-F(f-Z3_Y?-WMv8G+3upQ#i^o?dh*+?^D${Vc3#UF7nF7QJG#6q0`IN_7ILtr+HA6&w{<9e-=50%r(H&KeW&s^*DtFb zmp^Q$3%AyckthC$C+U6&j7jGjnz(p~ZnFpVi0p7nH_MadBh@@ZQDieug-e<1QV%9B zNMp{C;=@n30z!%Xu9W59iWX``QX9!ahE* z%YOSlbB)#o8`s`6$0Q%KDoo&U`Cz3!y#RG16j;I!_Dz*>oZozgjcNq9;~<{aOV8%i zuZK6KRn=&5xP{DVRd7aEiMi#&nb;_P)lt0q&f3Mhp}rZz9I4BN1#$RRtTz4Ww&OCT zP1Y?)mw?jqXaDmdRT6nIkM{1OAnxE9b_T}+bW)JT(g9-qV6+kjXL5$sG-9A<@{&Dr zQ>Egs6)C-s(HOA<{2l}|1cm*`7ZkOG3MByyC}G*;`sP1^co|VDA1p=1ei@_{)p6%V zLjtBSvc%Sy?#l0(hn3(<#qiiU64sH%naM26=C=fvFC<@e3GNg{7Y64UX(bmUzT-1b zVCFsh9S?wY(dT>n?3wB1an%P3GRp8m>L?CYK}UVgT#jE*K(ONx=$Eisth>8q$2?8i4fE0p5N=r6%O6Jea# zcbww`c=Rn5-)UX%r*?=%$bU}RzPq|bWs|f;Wf`%-tW)w*{B<%}E&Jwn7SPOH;yIW2) z>~{Umc&p7Zv>7oBj1}m0S%9&-JHDT`wstqMo@SW*F=f129*T8~+$_qxjt>@O*!)Kl zijJ`;$3bP`W4iI_#`ZJ2(RTa%uM-UbFxJBU`y7D-xd2^m^I9}lcwgU5AQ$L!HKIQ( z%wrf2fubaSaX>4PcQO_ez9@pg4ulAASskt)&3S$7kEf8C4?t>VqC`1L8iR(#@s$7o zR{30VBdYtt@Kd(FPQG#Zw50KUn z)=d3!Hz&|*0GG62;>Iy3!GYmWokA|Kc`w8b)7F?PQi#|hgAv;1g%+RrvFaVck|oL%3dFJy zI_&Hfq*g%C8hJ;*WDY!XT#E5a8PFB~S|VA@@Yhc|WciJZP%S3h(~kTz2z44TqUEdBbi&=j~{=&4i-72SeUcKi{M^#m6CxX%?c9q zZm-90)3jxpu-sHfk47Hi5eWYDq;o4af=U(!hIhPBj*kASQ25)Na|I(?=pK*dNLHy| zECxm#cl(a*bL$Zv-udQeC0}ySn4<=WPFCpL5fzp1I5JZTFeJ~q$niwM|_iqF*UXPTf? zcx&v9XcHg;!XDIIQkj1wK6R&?K{sS{6H1k+tqn4k) z|AJbO)u3Yuh1lBE4Y4Km4fLSY$342K=a6;%fK`21Tet>9J+1vf}MlW7_%epk*4>n<-$AXZXg%E$~sin^PK zcV`@klA+%L@S%Mj1?R-ljuO~nl^Ai^etY%5J89pa_sN#re*2SucPTqncNK58twV8i zw{FtkAscKlm7`OY1ojHXR;o5pGU5usJzN@TT|5;#Yp)0}2jkYdQI-%Y8!=XW(KTW!Xd+h{rD1s{;dH8QvwUd$1T_Bx*l% z;A4G*7z0OvHXWFp!zLS%*|{KWXjHfj>2xFs6dKMPqbFRC0~=)pEz~3pfc@dZB2|eo z6dR9o!_*9yB-MyV)PTP2lX30JXwDfp5KZ1Vn2UU5z&5)p zq#yyzVtn>jHyjr|821q}Nhk3iyKnmn2y>Sn!h4J)#rjwZur5}<^)}}Nb-4XHR7Q1C z`ou<4IGtd-2mkd=&J;HlUfoyu0u$x~xznt@;C5+o zF%QM`Ms7E;*X{SV?;NED*^~Zhl9q@;3v;zpUq^0T_yzS&54?HD#AVn3*GUbPHkX zI#>e%Jv=VC&feo5`dg@Uho&-J!Tx;L0lfC_?_lMbiI5hJ!G^@(HgNhw;b#xza-HXKm&N|#1`_{k3al$Bl65*y(FSjfa> zvd)G`IGw`REoShDxAmC>6##mcl&VlbQOX0zyjlkl6wasQW^@cCKJzbzD3Gcwtn;)C zDOu=xmXkE^Y3tC;itWBi;FnXX@;-8)XVc}OV_QrjwZFSByP6iZ4~^lVr<SIP!@IV4(y;P&xz&9H*UIKfeqm$h5BKQo##DkF8je^aLE?8^yPAeWB{ z&k}Wjl)4Vb+Md`np;(G!gy(avnN&t}^?9o=Zc{mh6}%8V5Mbnm2YP@MvN)C*3I|-l z>(MRY&)^L&rn?iH5O(${o{fbsotkH*Yg!LJ09l%F&fU3Ub^WEo(#YH(a`YidHnY4E zay(Wc?MlnjFL-|V2~#Do=f4%McZBuw*V5!iw!dkv61nCS5IK7nH{pAAuRxQIwpX$0q|Y31Ozff(7F`63xX|7Y+(0sAHTjQ4tyg2o z)a-1b2@bb-Ewv4xM*+0t2(tCRyaS^zER(*|#tSCGqDA`(zVM@&?Lb0@A*(Nog-@+U z94y@_UVe$v;gdAg+wY?NxmpMpFbM+qYqVNu*0cjVs()|=bDa+SY$U|V4o7+atEB@u zh6XU_=IyZHQ)|YViQ)jEk$|>FrK9?tthlElp%P3}K&!T|U_b>TI{UuMl6qI_Fqggr zejtK0r21!E@iYe0BcEpiV_^c3Nv#%GL{MeiYPopcCX>Mg-Kv@bb*O z;+;JR>`K?EO8;ynJ5_G9LYv8Z;3`%f{lJo-zih9HAt&#m(WJpB9pbHvwo=!Avs$lY ztNg@Kp|pRc3zZDp1SU*x%{I~+bGTIg_6W|x-#Cc1ee0X?V{rgsT+?HM_8SS8KK<%g zo;6%dSm}w8$j>MdP5$`BiYr+*eKK9aNlvtxa3CdU!yml)!=>X$=9sRs_}h!66YD=% z!c|-pzligV9b&tm$+P)&dZmhe(!Ws8tJc2#Hn;AJd)M_v{Wb|_={fcB7;j~ z!{;^@YM1I`O^eDF5~3yPNj@x+Mx&JvG+uHRfjFur$H=^U ze+@mm)&YX2$UTTGU0U@XfN7+3>rxrIEOD5mp9ho!Dh}u7zAO> zOk8`98Qu$1tJQzBS)Xx%Af1n$TNYJB4GxddI`Rt-xW3z5rf@IGwqS4^KIW@M?J^)N z?)0HHkWdNB)t=c@kEZZHMd>9XFaR#UKCpO3Mo`Bppj`mpxu^uw1f zoBz21nnS>?>{gxqch8}mNMrMh?kFBV;7h`Wd==NX%M}A@4#kTY%roNOm0gx25Olwm z*vh_~jtEYeErVdYBgnB?8Da@pHl&n8J@HV^A|r4ZvX)-zTNXUL~KFWrIqFQ zGRuC>tc|%q6G4OLnnJ`@X;XV*bREV6Kwk5nLHG?wW3MaQ{?o9{q0Jm>ElTbH`p!c! zw{jXYDhY5oA))JifjjX3eCY7SXcR7QO|er28vS5FDjV*n|CS0$fAv(qLgKV2P#}n! z47~SySf1b?MWT>0y==B9!5BV+;Z$km z;RtJ01Fic4zI#Yjc?tYiUH(#ez8LH$VIq`OTp%e90P4yUA-nBcG;FnCP??AZXpe}n zsy2O5GSkDyiwV4GSEgtysM&*CtYu(WDA(Fbvcogdn}rB^K&AriDZU1i2%E}Iux_bM zt5Re4hwR!cqjX`S8Z=4~1kV&46&l|jq@HF9^`^JXE6_d{vf(}abH#mJ*51UD_!G)z z#D8?Y;MOV3WR%9dZp;G?h6=2YS*2$B+G=VIf!M*cgl4^|}-mt%x~rvraI@sk;{)}8h>Z3mf&VN}x~{S|xXqXWiJkYn_*0RD?a zkayS!4XaYgFpeagPwew1kXJ2DGn!c|h{`gj9&HwTc=aWJ&{`vV!yy6t>6PRTfOU-a zcje~56ImOoaXVnsoIFVh70zGf*Ne#Sd=$prYN6<#Wmn5Wvwy4@qVjwn{VLLR!%Z{1 zR%3W8`4e`1BWSGsNseu)Sc3}o6qA>fOfy8?x_&A$zJ9tLs{z zH1KkQG3;3QJs>Ar1G1CRbV40$isXyaYU|<`LRDlPxzPTU3yZSuk?yycS}&#cjcC8K3hEm|FhtbVvTZEDy1VDCeUOAAP2-lm;hFZ(1;1O=^5k_9d@9k^B35_ygS zYK@``d^vq{Dp*oq#wHd-P$!flk1LLp2)_0O#ly8@%EPFMuKgNd9`pPmB{AtRu)zNk zyVk~J$eai+IjJSz0v4~>RuGZMWjYj|ImsnbiY!(0e4FX8Y0!mP(}Ve(W3El^QAy%% zF)+NQ;_KMmEq#HjdKzjoOPrXlwa6Wn5Oqja@h{O-*57bxj^M-%Sv2z{xN?f zvK#Lx#Wqj@w_TFi=xd=ikYL5CF+o_anv8l`0Y6578>3*d^>Jc7Q+*Z48`v4++JL*-0it@(WgJfZezG#HwELh`Ntfn@C340XK$}7*6<|!~ zeoj89-?yuHx^qlk~}(e%d7XOF~>r*!)0I>0D#1U%=)M*f11e7;KfbIIBKJO zI2H0WR2vn0K+$sntHl3#tu^kPp-kYv`aW5DSlNOw<*Mg-j4u@=n+X;WT$dy0qFGK! z5pC&c|B6V>g zW(UvcP`_84IqV2}SHW^Q{J8|~rA?*4C504(zZ7YFe}?0YZS+`|aCeeM_H-oT3mAB} zKMN(Qbs_1J9e)emT!{qrGbc8w4|$^QfXZCy@~x!A*cMXl)7%?M4d?C9zG@GMJfDU{ zvV$V}{|6>Q;6e8fGuIyu?h4jA`<%x&t5hE5qrVGcX$w)s<;<>+ha>lnA$gcyvaH2g zu(0!>P3Q$jre&{?alfE;;*O+^sMQG;ij>-$W_to!P_8k`0CdYRoFL88A@pwdGHW4<-B;|RcK?bE{ z_?cT^|0Kv2Sv!}{K15AfgLJ)VH7Al+jC~4q{R!@B&O2@KMhv3^+*+HO2kwq783wIs zTT}aLh1r(mOri^J&;FqUNUGVWtKe~mrKXG0xhnG|`c3Hke%z8G08DT)hmOv$!OTuG z>+@sWh2^+>;PdxG!)ST`5!_PxT_xYpW82g_TnQDg_zoR9+3gUUiEe{B%du=f-QJHA+alQvRwl|kNmJB8eO<)gG( z$R%T63i@aTL~D9}&*?Pe%b`P-f9>&5{lp?%^SdYfgGD&`7U?u)d2J?+AG~1%h2!x2 z9P2Y?PKf5qE-II#Zfl*iXh6J5vHhzp%95B)VS%0&_|tMDCKAZ+>oD}2a<;Zn;vRVu zzZ@3VIFH|gI{k6^=a8=DG$T%y*tZyfSne0m#{rAC_;dqw{sA`k@A^c!ZojV7PfnO1 z>%Sfg!e*I3|L|cJdq~w>23OO4Ts+)FI;2x$L>SadHUQbP{5tJvB@(fArD zxAY3$7x?pxzE}x$+*qZS*HeoM3n(abLB;o7WmB$JZ=Z` zJust9_v3_)`kCGk#gGgW<-%{&rmrRUVKBT#G6{{glk;L6BOXS5m)d^Jh z$l4$UY5v3{sJ*ebAvKNt#UzL!&k?m$aqPnC=Ar{!kE=1#LvN6RpR=0X4^RYicV24M zry4zRV-&MV?Mc{G)=E_Yrlgc>iTg&XZ=#HT;mz2>sMMho8ifHv`qg7Xw(5!-F+dpG z-VOzXI3Nqq9dsa2-}+=?nBZqi{ z*D$7?$rk`n+VFS!ms)$|m_0E)w+our-ENsa+ct*Du)pr@wbda-v3jffs7986x@&Y#bbV<#mZB^{JCFKCW4vG>>00@xb<(e_{w3G*hZD zsLb=869FJ1JwGl;wkTWcF=ICOYQkI?qOzT+Re}rbHWQ{ z&`jyb47IaCspm{r_QHI3{w1!lz@ZtfVZg4R|DrCzVWR3cu-!$AoTI6$av1%Go4ht4 zmZ?cfA3nKHh6V27gup5wsm=_3ItLTljae696%au{pX74s`x-6~-?J%PcEY)jc(M<( zoPP~Iv}yCZoyhe&U#FI`qQ&5nl_fPtbzWhJckhF0jhD(B)Ks4D-+rb?BN+VSlFxBa z5-e4GzC*9vbeoe|qrdpQ7Db5^fum6PXUE$*5%Si-g%dc?%6rM0-FqJFL7#i4C{zfJ z@bv|Ls*VlK!er^|%8d8CJKQnnYib&haEfZmq?WWYcg&zJrsO+heHKRu?Uwk@=*pI& zlMu(cfz?np8L}J<9ka8drTbavM$f$YBtCjQS#^urhwp+}>{XcYy#Dfqry=}bW1+*A z(#*wsqof!8F_3zqx+>~8mQcVGDV}nwN2%e>Nxq`~Zshq9tuqW}s25ibp}VJZ`;NRH z2oYa+_2Hg23SWEt+^&tL#FDze_lpmWMQc2=NxAvUyU-kkP4Sb0O;&*{|4>1>( zD?|H)Vpjv#9|Q*3oDhOnn;%`06Gk&gWk3&Q02>+hS$zy9J#VlDhV6E?bM{16-`%R`sTQsxv5z5d2ybZ~C!p~4rv4P)V;$OxK=M9pz(nJt$=C#ze z?$#jFavwANsfMX_$*Szh{^Ak%y<7k3;0N1(!viUd^=sP_a!kLL=m!gAR@4#ru2ImDo0%w3e850G+Ip-74frR5-bos zc19D&PDE(>97)SbL1qd4x`tXJZ#0Zj*kA5i>C|VYu*k5X7W<#vM8C`>rB;R1^1#$2 zHEkY1A5>FmMlLPK4E%A6!@mSdR|}g;&qJ3Zr~A5690h>T8wQy>d|zcPhaUD45GsbE zG&tFZWaSlM=8XnxbuTFvz4w z-$dJI5LHGqf@Dqjxy6qJjbC02-{qE>0V6uzUT6VmFklYI_ZdjOxv*4DsS-aNgWdGg z&REbbf;<0QDgPfAJjh)lpLO6@6c8%;Gm`vRfWUO{qj4~t@1T1o-S7P{(wSX~!G&%w z*_$a>qx(6Mi>e_xn=v){|YqMLb%6>xBB`84iu{ku5dK`^~o_j_)_8j-8?yNQC$N>EaQN@P|ecV>hXGZPG_)c9ii8cJk{ zZm$B(dIw@h3-(nEXqFx5DNNxo;kqV=|QSHHuYyu%sA-;E!KZj!{B0 z9|P%Z0|Ov($ApsfobG4`V`&0I$a&UXPG2S|3?N{+Gl#^F6+Ma)Uro?;`VDa0L*_!9 z@UvG?G5UyVD)Bzp zijGkl=i@{r6KGaH5y5zJPlkKL>L*I3SVe%@3y%&|D{gK}vTF8=7-FU-UoPo>yyRRx zzqRwIBc4VVXlFMCN}ltXYlo=Ee@F}G1W~KCO3~3`&axIYylsX;9L{BRn4y;g z%!6v;UlKUEDotY&4sRsEj<5`#zac$zhL~HuMGjB?IDAd3bw($!4})^X)nYvE_$i4a zhFL2P#=Ra1VsZ81Bus|d2l16n(4p$YTyKldYs@)rve_86Kkn);d7 zohyrf@>C5VkS`8_MXPXA(_3UO_ctSt?hqaYja(mTvA z!$dRFwKiw`CfNEJVMci=#P*U)g)b;aMIW;0ipg2~ceDRCKKf~w+~I!(Fj&<-nSCkO zR;EseV$~~4@nkwIR(C}$t<8Yt-PX+bLCxY|r@$rQU!J7fhuWqzJXn4T7QB}b4n%A( zXt!n_V2D3#(#@|&Nnr+-etR3Mrllz|g8okJ!;?pn{khgPt&y#lP!*km`DLsbee|k# zd)Ba$<&a4Oy7XE_ZR;az<=Zw9cc)Jwh{J_=fm@5n`b^530Kpi7#xVL8>{D874<2>5 zbK563gPRYDCDQdi&>A{~IxuePma8_i;ntyD`F2t7rAYoK$V|Vd0QKbCoP~Fcf`lHQ zwzCXI1%FEqE-{tF&j7J`{8cK+-}ae0mL^o&&wBgJ%xtFh@zblB(wuBGTc)SEC_?aC zPMer)W3dK!rk}hKhxv}$l2vhCX{fsBg3@w3kS3+*vXT7)PXnH&g8b* z#0}TpA|*poQDhd3VZ+BQ+_m;7rU)L@Dmjs)2hMwrVoCT!8|yRJh&J$I))$b&1EvTQ z(f8azxGMWeo%S|uobDW6gh)#bZ?=j$ojb9E#GKC5q3Q(jK=altnW`!2_iHh&jafwX zc=!@PowU0Ctod#)rkv!)_rPEl#?kBiZ1GUxk~GP05m2rn5^kMDlhEDiTy(??{uK#3 z7z9%4FC+1GTP|y}LT*pY6opamYx+c5Faw7_Q!2r#W-kCjPiLvin{cIb$eZ*u@#VO2 zIA9Mq{beDnnx(_WujjS6`lo@y_`-==GDT&Ys&`EEOe?G$-LlRV#7~{yi!gvj?)D8j z5lW|(ULr7@yl){_=d21wVgw6c<3_nVUSNTWRg5_=@0JI z|Fa}BAOUqZGHBV)RYdz7i}_;|E54BW^J?KU2KDc3&G7ZE5=EH$8tQVryy!Z1@(r=k znlr@&1lGSI`Tf6O`zgTCU5$|b(ANdhJB<|haG=z9A%Mhq9XwovG^lxZF( zUb7K#&s4GRXG*P^K_KlzG}7$gVoMnn$%fw%VmuE2(?+?Q^r@Hbb|b4rHd2BV`CVL@ zv!bW)lYu!MJVyZN^KMANN|A)Nb#;rA4OBh3_jjBLITN^EASW;&u==CR@8t`caB>rW z`Yi_lCg%P1f5-5Q5Ddb=*bv`lyqBg1xK`a)_Z$SGw{|0z)6V|On*1G>Q^Rv9_O6Yx zz6|(y;Y2cK2g{i^bnsTxGCTXUOMGGJCb?E$C z5DDMp$9OZF_6H6{uvA_(H&I%o;1+*!X}Dk0Lhnw})z|2r#lt zCZ@^-Mg|g3B9kZ`^&zZ#`|IAU0l4zhf2stYp@cq34{l&b=bB*qYulg0)FS}sr0EOzp(K zAyHrqk5HJ-c1BVLdp+kIazrF0z_i6>8GYfa9c7E<;RL{W^1&ddlgfa)@@aGeJ<=QZ z_w!PxeXgb9_n$MIx(nQ3$9SZL@pK(B&GA|$*!#Q7d}hY|-;$~(U91N!xWVMtGY}4@ zx-xm87=4o7jFG*HMP+rL&Uzwol@GS{B?X6 zkJc%W_}xLh;RHv*;`#OZW7EZ(g{ma)i1?DuVuFBMbWQekYAo&hs}%=|C}Y%dnWrnv zRk|eNrR~E5qHV+2#i+v#-W(RK4WZKLWZq-mVs?BfE81uuu88d$TitM}0yNFv(WMS3 zDB%wz^~-$DkJ@m!LkfQ>9E^_=P-EU}2vD--4av50H*VR=N;`8UVr63g>n^I{7F}FW zip%-)XMM!(wY{p9!6G1TcBlpPmG-e`$92PF9TZ(cSZ;qR)7{7&w0Z#l%Pk&9L@{Ec zxxrTBZ1E1Q-Zjbwnd_q&rlV5jFI2mws7Bs2Bw?L|9GYvG01A?&;qBJk0B#>NMqjQQ z+N2X2*TSqt>2qXZVAe7Ub)phBwj*4>vnIpCpU<|v4@bBZ zmQio`wOaI6sI7(?TQTR?^{?rYNw7vX9gEVi6${lJ=Z)G4MQy2HvBbQUHTS9q*WoC7 z{uEB+Nq$p~$a+0PnJ&xhcEM^%VW>%xzBxt2Isd!A_xTR0y+S&14}?;^#PQ=lX?hrL z84;kHPJ(=`ns`1o$@eMxMGVGRcH(*tCa#FlLoiWay~-W1oZbmKMbI-MM&j`;KA%wRt1%JRx%SUc$!^cyR(r2NIGhK=r<6a=Eqz=9kq5 z|1`1hvA?exQeV@*1u>T?G1~xu$mP(K&PPBqKdQ?o|KT49#OLOyTw7J&#%L4dh05Em zgvSNd){?kNy&60^p76cJGTl0N-?w$EiWTmNNqtX}f0`V;n3hoXMr=6etKT(J#2D1J zvi}UYhoErO(I))I4!C61y?eaChvx&EfUr>VM03SXl)WcAvFAKS9!uhd{s4;Ys&`eg z%KwuX@wsbF5BGdf|CObcvmr{g3mhT!Yn~5Wo_ImEJ=C9Cz7xlvC$fB-!#5VbthrY8 zk9q{lgcsjKtv_6DM#iB5dc^XqV*|q9vk*6~V&9!eE?Qzr3^nk?8Ztwj%wc}8f`dv-*{;hg|fKK+gD%OgS8e_=C8La znwgiWGi0d3!u(M?KewyS%A|RWu1jzHw=GiYyLILjPr@?D=sU!7=$aZ6GEr#qh5#2C z%94R$heVe#k^-6HUoSGA#U9ZuGlr~p{x||X9Qz;7d@dF|Wy{s57OH&u?SLY7*WP7M z4=O}uBk#)7_rHGSGGP)dL1{glIpUjDSVG>6sVR^`8Na+jLuJGEmP+|sA%w@)+UQ4{HT2=E2fEPuhhC&U=(9MjuJJ4HVnj2!4g&Ua- z#EXh(E88>@DZF|M#a*xW56yxt zGo}jnRz;(M<`yHmex_pkZtjZaJ8fVe2=yo{$YO~YvHI4Ql+G+Lk`D3r1fP>P&Z4Fk z$mhp9M^@D{@CUmeq+^GH1qjxy6^=|sg}%UA{S;SWZd<#=RMc8C_ni~4v6)}czDB4f zbCp&(ljJB0kt7^{`vfkv!0&HsMRtRXzL@{%CMx!h%l$FCh>|UAz$;tEV*e&zXd5;3 z&AJs52y#>1{z97O9o2BGab|x^pO#CA+=WxeF9ZdBfhpv2)--2Pk(7IPJ4kfejKpV#+7OB(e3KN{JwhiYAewyHccKR~>`zl5d2<`2kUE&Ewsw zoC&^*k28hOMek5CV5RK6ad*y@y`&H$aBbRw6)1>1T#&uJ ziiMf5Jh(*kk)gRXfY;V=2Kb$Qo9S|aA9bl$5ip9c)Q2)jvkkCaOs9KW*Jf4f!-;>D z3$+E2xBEgWSCy&1b(%u2WzQ6zxbaP%)MQHWd6wREckDTWxvC13;_wRA`l1{#N zTMZt%1>TV}YaB-If?sD?PL)-DU!o5Aj z=Y`x3m0hhjA-hXdQ+R=iP|ccMi;+=&IWsimxx})lUAN-0^p~&!oWTE z-g7h3U)8jKf6uwAImJSJ3a2T|xveG@y^(g|;}N=6;7K~zYEFTuDp44R-kUq9xRCsr z>lXzKaXqbq)`zk_g?|~BQ}$Z@DvqP25HNTT!TDTa!w>$3_clTO`vk{*0_804_~cxa zY+S_hLqQ<3OF<#O)cQLbAk8ZawrQP8`r5Mx2<%woP9a~LjU*r5!+)SPSQ9`umJ&bu!)V_`}}5mWiFF#gG+~}81f*)JL^J z+d>~y`-MS`>AO|RQ`g7O&Di^{)d#`Dnjbyd*fJ@Xn+KxKu-)P$4*UGAEwm&aNV<== zQC#>QOwm&-`lh?E8$^c_epc{So#jqiPETDPdV*tK%|-x2r1eVQ<)88Ow-Z$Ylvh)+ z{u0k3fcs5TPyGZlH2vPwze=ICV{Pc=grYq$5|c(!CamFJO|*FOSvbhGE%-kc`tT7BN5pkBb)Z3pSkWKuGLPnNJ7N5?cZS z!{#m#fm8(_ONPtB)waQU)m|Z&BqoI1AWv%^R;_Et9#yX%l!I`grNB5ze++d$WYI_= z8h|vo6lOqU=~pr@XD#J4*c#jUW&sej@aZ?K;{sI0zhRC-x+I%=^MBN2}0+Ugp;HX`Pq8+ zt027&@D2gLBh2`=RYptr{u?3%!7n7_5A}tTy~xK3dEP%~0HFTy0JFhpx^ic_D8n1+oM;4z+IiAKr4EmLCzv;9SpBh27a3`NP9r-!-pb&c4I`Xw2 zWa`7Zo3#q*{kb~(xFKU*iZ;!~W-8f-0>Hl2K>`&VG-?s1@jmiDLf=OU*u72ge?$1# zL$PF;yPK27Cf18`FQl3NWGkrnGa>XcY$MUYI{51VvA`z2meeK_XT{fGhkBbtS%~mV zlQpk@KgO#_p3*G<#GFeI}c#g#sA=XY*y+%pmY zfbrB7Y7bF?VMOrbv_9yad?dfpqDK6`MgG1Jj%0`W1W%h*p*un$O_F9bRg?r_>$YkV zR$9>AGm=YNg1rCjlLVNj<70U?d{zpIqJNu7X_~WWRHn2H=2#ka5 zv1KBGfc?BmH4eRc(eLo8yU`G8hn*hh8-qLneNZY3&it1SDE;___Wb$SNa^=CU0*`J z#pY)Eh>+xq913pr3Dqi0>$JRu$~^w7dgtGt{rA-v3D#RHxjtZ^OciO)At_Cxzqm2d z=<2D1UXL(uipv-r6e#d6HFx&|G7k9 z*h6$I4g`Gc3pPWsxNiiD%4kk9)3`eh^=$QIXa)Lm{g=@Cizx?_>GU( zZD6z0mp^FTBzdcfKQm4|ApP7A;H#Ze+do6yE3+&pi zr;c?YDVH2yg&kjmBUt~+U3Nz01!7Ph>SGR|9uqCwK)=&k2wIzn&5jPsBwJ*DGjXYz ziOTXY1miAPP_Xj#W;6KG6X?EGwPuDx+ld7n~IG1tXKSA?d>>N7d19;d2WyTe`uO!Zn8YZKi4I@dK zt+W(yR#8{zsujKP&GiAcV;%C>cKLWK3xOuCqgq3BUSJ~2m2y!4l^?!dd1^X_1@^qz zoWPhb&X)%%-JqQZ7BnZoqm6iyR03XY2E%z~rFG=#qgDJt)nd`Z{X52FC$+oBe%xIm z&e{Fad<_V3mMd8$-VVfU;%+|^9InnZg$`6<3VHqv&C?s+_gVC#b zAe9rxn~vaqj|t5ww_!@ft5SV;R1RsNF)E}nnKp`>3Z5a&R{(7eKIS~wf!Gj%|Lj&z zn|$-WGE;;dEQq}|C5O^kK7Ia$MDeq;Oe&@?y@xl&n$9<@oUSo%H3|_qmP-@|3QMQD zs8QW86uJXaXrt zQRbesbUsz+_xqCH7}gSovxwL=+LY-Y@ao|}2JfHfuO*@gJQ_<0CUKvWaN+*NF>y?A z2aLF&loDip6)j3Wu|iQN9tf-^-Y|anl4vct>0jlEo?xc;Mcj^qh-HZ~c1;~2Cn(ag z*%Ult4$XcJ#igS1BpaBSZ?@UrS-*8Tt~16EsGFvwv?4pVkK7d^J-h*(+TSQaOwdaR z9i!t(7^CU=(#saYt*nQ?sv>3p6KctzC2w00$yvjlYA%pvp{rTY;XE#?dkG+DJKJ6V`!*z1u(7@6=iBylFLAgIQmAJZ5KsXMr~?Irx&?%piIc?r z&otkc=GfjguT~qB>o}T{QCvw>m~=(pcNHG--<@=oS&&k!u6pS zY-{LFs|bXp3X16loep8}0{F}RQ<5RVhm4nn`>J61bWAtL4x8)oI_o9mL%XJehmIUw zEK#7QrN3Mn5pI{0`-m7?xeH>S6x6;PQby{1O8HHJ#Cox|E8H6M2O(YqRa);e?#DWh z*bKcmNBgXBONGZp5T?{Ile105>WZ{No`ryWQSAvU*``JmM40hg^_nAe{v${zSPr2< z+cCvQ5QJG!SkAdoNK>}fky5Sn9B9>M_<#{n>9gA>U-|AhrgrUs*l@yDEM$_}Eq;e*4CiPN~NX%~!t}&KsKiw73JIv)Ba5Ns=V! z`jw;5Y?+ENo16bJV_Xag+CSfZFo8tt(Vkz|^FJGRg1=YsG!h72E283rs@;C3?tB~N zsCH0U}AocfBs{3R6akHbG=UqcHNh=U7jFqss3lQR(oMr zT;#dBUr^Lp%m!=FoN1tTd{Q6#pqn%6dzBfTbbeaQi|?PG#q}Z4I~>HbP#{jJ%)@{g zV~VVH`Q?)X>Cx5vq#$KI$M|xi4y;2vSbLmG0X?6l4qXK-?b;~DN0a{`RvN>_K6*Xa z4@SqOy7gt?I(-%025gvTb|DGdv~ucQp|2=T`s^peP?Ky+Ex^dK<~~g-IE67~WEbJe zaUQ0{WZ)0bukPESPAtXhYQR{En6&GYwhoP(NK%5Wu6E(C7Zw#M`x@Ff$|%l4ekzKZ zgIRM?!*K{4R@LO)WZiD;9bD>@^4${N#r?UMyl99ena=h3aRCXc{nM! ze(>_oSUOVHH?uJWtfa~r45#0T>s2rBSRBg7SK9myXm&7uo0dMJcMv{wq@s8xyiBV01N28^+>DM60=}|Gw@{_~4sPXwAhBOMq~5+% zR4(eVcS@^BGk<`~ek9mW{exz~FZs3nwlS@{Why{F!YS!}_yuboff6UzQk`qPTW)ll zouqtA+(BpP4&aqJB%b_848lT=)>IMQ8DN@izg*_ue%(GRFXeF-q>H%vQIWbhe)~+d zTWj$PlZ6t}dnigaPTkpQ3I>BbYwner7Qa3$otblLBsqF{Y5r?2 zo(PFR`!h>A>YCtbA8V)gAhQUrE-pRhL8>rAKkQ1Un zVV=TMzb*rck9C*21b(W~_wND~vOk@&QV^v9T8-QgSN{RUP%s~DFA>9FoF=xj6KnJQ ztWW@hGt|sg8^2zr<=CYy^j1GaNoP8SuFmllV-0JX-YbZ3_jSJKa4!^qmXT>xi`_b{ zNvvA9cy%Nh$ZA4fR@ExD{G)nou^||78bjvvvKyO^imtX6(}G<2A;<`Qj(WJk>C|cM zwyT@Kz5Rtq0`jA79YK*7r_4WmD+`+Q8~8D2QS!Euo)w44B6Q0 zkS0xrKj6&b4CcjNL?2PK@>y%ikQEQal_*VrTMnNjQExJGoCohs)qaiN(JlL8*w4k0$ zajM#h-Wy;pOt}WnNcf&*L{gO0#;q=J>{zpUIwX|5+)nqE`1hS) zN#qS*hhV6Jglal3X)P=nbF3{P4*~Zb=5}3V%ur%PU>Da8g?Rx2Nhd4qL{BfmQN|06 zz)9Ph8JktqBVR#r84cxp4hbiRMffs`P5PRVFHFMp*Cm;^MPx7XHJMMCJ)HVI?(Dg* zuVHy7&Pv~D=_G+J30yNKHaKHnO&IX@!Ti8lqjqwkIW^`~@RJq7Nw4Hjg1ceCim&SkkoD-g+z+0M^u zkXCs^isgVbzkvS`uGb_&plK3bKC$ZvcQm4Jl9GRs>jG+e=Ey>iJizEA-R!(Q7A*N4 zr<@MS=H_{!hP3=FFf0>U)vcPy&ew0rQ$ugxV*#U*O%0ZQD8(3;=)eLa3X61HmnM zKXa&_-(g}fccTW>7QK&UH^9L|P87>!{$S&ib^Tc)VSsV=iRED8=Zay_POx)J+fK&U zh)_N^uG44lt~sY0=@+OmaK*TR?3mB)27Of{hib<$7jJaM4Z}wTYT4KB_yLsj)dhwN zaKIpP=YtZ=uo5lRAcHMm+9}Bk#hkjYWxMtJlO-JzJ~rVlneGEr@ zdD(udb6k5W_r({YX)|=9yM2MKPQ{VxK;*bA^J$ws0E)EGcI1t#?Mw15|1`i9rm$*% z7_C_dKDxr_SCLK5=C5|{%S?Vv3f~F8L>8$EC5XIYMv48o0tobS5E(vJO)|Y@?`Jcb zXhIoFE+5>LxqtT6V>k`vY8q2IcQV*NIwaPE>R3XvWc>vxN^|D+8m--?Wm%gIoUEoHI^#tnb6Fp+<6UJ!!B~;jill8lgHxf4-ygIz{uEt%GRv%E)Ft;e zvPP&6=kW&yzB~iC1fb8FAEJzP_PLKhAZ5Nf%1&QI%h``>C8i95A;}*cs{h+fQBSQR zlBi$`Au9ShsTZpvri(b4gX*+Dxm%JF!WHTr9jq)C2Wn|=5!C)Ar92P!8F!Qav!l9o zqHvG3GaKhN;)av8qv{4xOTT-;=vy450#(A=_5mIm?K7DY!c>ku)X*6V0gc~A>FQ(5 zOPMIY>{;W&Zc4<=AWbo`bbMB)SHvpQ2f3z0B+Bzgvot}%*7bEhB!?nI%YUhR0Ay%{ zhNXpfuVgFVKOsqKJocLwkU~7%co?65LSOtBMGOE38VP{A;`;9Z)(H+9J4~`{s(bBaEv{q4cdC)1I7F?J za2camXh{$^zcJ0m1=0j_S7LWQx#gAMY;5&j390dnh6NhgfLzieiAAzKiRgkW)$l)E zpI`ptc>@6H1@Dww!u}tbs4tJ7L(K4=^g+NXng|gtITEe5gG{YDHBqo)xu3vhfEej; zf18G_UjPnq)!PY-vst338@ADk;J~tKq9d$o+huc*ql#KvJ_4{{6Ot2Q-F3LE|DxZC~bH!#T|nDV&{#q&>>3YU<{HY`|u zW1pHOierYU0&4K1qifFhRe#!$I=Ovw5=uFcFI)ROLo~Z)$JJpA4sX}x zGoMBBLctU_`shsGq-rG#SJdwfd}}yF^|6TYC@yKqb&2P;Tx{Qma31`H0pQk z1)S7Z_-9ETO=Ho~NaI~6s5y2&6dtiRmbJ*ZFYBOshUTIeggG34%<(I~wyoy5bp?Kv7gyMX30j6fu`k6Zf+}04Bfu{fA-b*l1K}7MeHz`%*IevK zqww*uPw%+Y9Du0C&fim6^ue$i>u>MjkDmLMOi1FKW_|AZ6!>%sXNjz8R9pMGl}1n0}LY_b|yj- z5wIq0$8Wt&8(h8*5Wu>Vq29o0(=eV2!AD+#3(KRh8Upj)ab*av%1af;&7o)B^5og< zW~Fh~@!%<;7Sz)=t(I?HFsAk>XpWxP+Ml|?ekk$IGa;invJ?`QJK9yrX{aaenAwCv z3b*}ERT7G3C&`=~j_|L=@-7eJ=55kzNoKW5 z0)HvgbbKMHyeOkUk~MxJI9!U7=jCo>ZW11lab*6<1hL>uwxH!6QIjSR0-)h*bfTro z&+DP}n1REK_jY!3U{x|^Cx523LJj|FZ^C(fgI+aA`=h!RgP9kmH#`gXh(A|Mk;;H_ zUG{p}Kj8~OuI5C&4^*btwXMkWq^KzxH(^r1T1~TPIsiL(u-EgrQoGU_b#+Th>D>Zt zsok%EU7`8;q(&^`l6>byRUqi|eaEIPM${kYcNCnJ2j511fq*ZUlyNy({6!A`0s_T) zA+Jqf7PQ+V0kce0go=)nu&#O1;oeAYffI}fQbD1t=*8=YKB>nGWiGF?Y@U@hP}@Nu z-&0axZ?}lhM;}WCOd(Y{$D=pE?e+ESmr}08lVqOrJ>kHG#>b_ zhRD3ELJU$yJ1f%uXH5+!n5Z*j@#nr%PIF+;%8Ux&!vy_zgPfnFe_CpWSdGPZ(B)D; z1W}tv(a1*qidMX62Lm%)qE}Y{@F{`cn0U$RKlDX(h%e?L>?>5cpHkCq<1-QQq=gb6 z{Sp3HdinH?yQLPg~e@v#f2tM%JfkcrWn#S2bOX+mbg(k`7@7QQ{=1K-^Y|?S@Csse~Xf!{nA?8|_p2UPx;NGJ?Ch`0k%?!Oi#R#c)YVV#NH=Rvc z?xTay%=EZ34;I)giyJiL(8~=REnWtP`u4Et1_j_}Kw(`*+5?6vX~DRbz7b`{*^G)} zbP1oOO#E6h3xksq@qHne@&R^5z^AJ-QZmc!K41VHANTPPn{)hZ``IrDWpX`BVoE=2 zzIR>GJQ#3m9Hkl(D2IuNK65-232fUZ8m*@jkzf>y1CM8HvCK5Duf086(l#M7&H)T0A?gcUORlu z?UK)z+gPwnf}*5a>sA3D5G2e?EeGZ@S~^JdEiRmq`mcfxkZLN}9%`d+Wb9i0jLJcg zJP4{6DzS%d8oafQX&JqR?k*kSzN+(p+}8kTZEdSE{33Yh#*MxCSa8b>CF4!rX976(|FY|0W8YD?;rcjXIFiuZR^#qNA-5tt z@Ek;U@up$&MDyx%=Xqx(!C$TB-v#ri(z4R!Te;a6yDh-us?WovOMSQqQqvpi*BBb! z@Ohcc<$nlp$!#opE6Ur3{qdeT9umM<4aR%K@d-p`p|Fps-iwDQQkI7g0FuyL0(yp6 zP{%ykxJK;O*M<-&%vm&21|BgBq(_C)A27fzq2^NZOMd$syw;u>T!8@Am6eQ?_FASo z_}K+Rp{UbkJdMVLP!Gdsl1;wQo;%Qb+n2b{nFDIY2No+m>2fwd_4>3CB#T$*XI6IJr_o@8BQ}n*kg~aoe1;Hxv#Kva1E<531(_W+M3;*ROQy#1Jk zlBjPnM&ad&trWcH8+P$4ybM^lVTu~p5z{;qQDUZtRE zty&L)R8#Dle?dJXt(Vn2iSEk9Sje;YF9tUCABkh|j28rt1H}lobewut@gyj&N0xnH z9;6hri@uhs8Qm5Xj_t8JXALxLkI2XUTzzyO*78BKRJ%csJ<7_)13Mx!ZCV{2T3i6~ z>q>IU6tewVfQfRH$C(WsJWD71J<&so@kg9d?)wJ3%tSGO@f)0fd&N7#}V_kea0d?I`r(HpwdR;c_5BGLuj`D-ez& zsB!_YiLk9qf>E-gcs{OJwZdIGfD56Y8$((u*e5=1Z!198CS7gyDTI=rKtTuIROp)@ z`7A1-W~V$R94F0I2@vlJdMMr^yPb9HN|w+Uu;3TfOrZ1T#6UR9;g>*IWgjqi34m8J z^@e^GiExPJVEMJHa6LuhIsHkb@ir!g1|}^6#JXIxxtmhX(dY5^XF85=LO^I#H_@NbY)s8ziTiam$}GlV4t&vJ|$$4B}+!_`zHj z@=MZ${lJC(4f}lnf^g>NWR$}ln;ShT)hrxIU!F_qC(kJ57?Fo`*%KRfZQX z+Szw`3UW-p?Ti5P(c6nzuJbwmB)#+J8J&o?gfAbA$UsH5Cf1$Ufgo3wl9?(iJ1Jbr zy=`nc7P{b=*Xp>Fg2MD7QJWAt&GYa;F?B@g5kDQ@m>pl96ilw^OR3J55}NTd)pTsalOMkv_Y> zCb2}+S1GCuuzq_fT7-lAwBkREAca}7usi}{Fb~sUnicD$zoDJ^GZE;rFA%L&z*QJk zCnv$*6o1VcEC4C`ixG0*GnP$0H-wEvB_@(}F|5ejTF80dbCY&4q+Z>2hgr`6>%ogi z+V{#L)k*|#p{R9gpV zLu9qWw=+8+b~>P#L)}Y&U_C`8dVVAv`Q@YS-}gx>C7$O3K}b6>>Q)o8m(*RI953mp za>40S(CP&$N_b6A^H9@duWhlEP8pL5%+=j+?d}H@9z`H%UVyn3VJ-YJe1lB){v0Iy zm@htJdT7aJ=s;A+KM*1kyb2wedKW4fqslMC!uE*b^Iaav?<+<}O)+~XYXW$)`eiFa zdL#FptK&|a|5(5n#+i9$(*;DD0cSG5~)8 zS+u^GXb($ypa**kGjeL2qe^xeIt3jY*5OoSLn&c^sP9-wI7nXP8&5Lf#-CGU5LBob0NM&|mT*x2ODi zgD#!u$Goxd1$y74ZL1g@A<*`SsBx`8;u1-!Z3=euhKKdCz0Mo4zvidjFVFIA4b@L&n`0HD$S(D*aQM-*E+X|ub0im06AOl(I4 z^zlui8xqariLF(M*S2Ko&X!GCKgFBK4B|9SCsKed_OY1{zx;U!97%nMnBs~;``h6R z64)0IKK~sfA9)iQghYFdm7kEPcs!{?frQ!A4fiL9zGHo9yW>%z1*DYN;~lE%xpGSJ z@itsZv2?+YfF-yaRYV~Q!aVS!U4t-p;4gG^RQ!*l-k~3hx};2hki^43{*)sSkAjt7 z3oCvsIFhTnb?L$Le5vRHq8ba>*!-5x_yqEj)zTo0>Sr{KKgi}C;8=f>|FHd2bK zL|ckcg=2zP=k*hD&IXmrHr zWLRI9&#q9Az4p!13CkQe&SzvL@@OSu@M~~diFLuu|4x@(u4az*u?2BHQ02U?7!kT| zgnt&JzZMvbo$)U>JF-&4EWV9OVrz-_7PcDSTbgdAGilSLD0}T4o+7mgUDpKrT2y>M z)%(h6Bn`D(ds1aHcTuoCmpf=y-D8$wwke~k+> zEHh+67gZ&x0b8KOS%_M`UB~64Br+8!*B4qfrH@2tw49fjW&#dnp?)4~dDZzIBc*dCeD-0~w08x(vhL_vm_+4D+9~$+$$7cM3Yr zN@Au-Vff#|E?3nt5UW>&t2Z-;p~?ApRK3MW8PsnNx}J)U2vA;YSGNN*;&v7FJ=ri0qJ88$G)XXRJ_rSl2^^5lUPPCBoIc*ZF1h%d2tgI zU77wU=x?+R)o?f)z64^#@xz}OlNXJJ{7@354t7JFW;`wH8+;p4M+acaWQNG{p*;gIQnGwZ`1 zDhJ|rUWRb+R}ZZuPS?7Z@t<@dQC|^4z^B7IJrDC%1~RHHN3njF*K~k~%NLV?$1EEI z!}lEk$Huh!Yzn+yy3*+Y+M;F-l-;f80x(ASOE&bN^|?a!-c)-$FQGFIIJUp6#0djK zm5`}iL7&*C4nXA8wvl|gUWq?E=&3_?E4YQJVR68XtXCi*?5BgL8JJig2w&_nOL!g{ zNy-yAg)|jsO_qj`GD@$#yd^K0ICW%&uo=#@2y;5lx2imCg73(R8h&3+qwS=7IkyAt zjn`zRa_L2^pDR4;W&3veKyoUdD0^}7SOfu@&wJ3nDyk%EX)T@6zkqP4x ztFNbfq5ByqZw3m#1XF@0rLZ|3Dt=ALQfwxh<$<-s9eZE}FZl_$Rab@IZ^2|@k8k>{ zcR2eZAk(9s5$ggo%7zg7CUL?M%ALKJxR>C|wKNBVhx974U^TA=J9iVkzx)7XQ0-59 z5lBoql=1gLP);FsYrCFqR~>e0T_vV^)6M@R-h~v$LE_KQd7Q};CFq4c!0O1P*(E*Y zuuT?>6>FTlL19W2&`V*}VbM}o7hH+`0}VT*v-rb5@VG_@=>VfYp`GxGuyXrY9R?M9 zR3dCRsJfbx@5>+{4uRht<2n~UE&<4wB}-y--a~@+;IQ238)Xy;9x@_N{w7CyqimK; zQY+Rxy^x%&KUM~ z_ZxXm!WRly02u!wbg%33XO86DAiH#hPAcsD$jG6Iuvq%rRzzs;a*F2VZLDG&9U{MG zUWF++l$+&o?xUhY zpnPa13`yxf^|^n6{-|P-O#85K6ske~SOlZ-!7d+$4r}wn8Wvc>EsTZvMpIB&xdE8t z)I@0<*`g^ZNe)@MBUWANn3xX2~=T~gd01UDEit!ruyrsD$9`7M+3$uao z38}5DXUa|L_nJ(paoYFyJ&UEZ^1)t3VE2_cN+%%M1MHhBUZ|l+x5N8=d9?0#KzNqz zUn?zh;Anm3=l@^BOXI3#4Y~0l+E9xS{M!`N1AGeb(O|@v@>>me!ecyZjzE7M) zvQJnTLXbH=&Y?FrI7GvzB2^G5$nyW~r>7`~UVvzuq&wNSPkZ`=l~ucZ1qf_h{rdz> z89oLF9%fIs!~}jbY)Hy@>A)PH9Lu!MiF8vxx`Is5J%N z!NHAS%s(MSET_PNRp-eCOu{})^qc1Hr^A)8jKq^&*C_8)?k4Xn6$#N~z7CSq3L@oI zZPOmYUu;-O3e4N^>gMM|VvI{)_q%3H#p1gcx)552vCuEDDFB;2FP}@cxLxaliMMY@ zoYs017=NoKMiik1C8>ghE+pk3`UcZI;fN!SXUCvUBZCTU_JqRpnm6JNQXEUIE|c)t z{mit`gv4vD^1@fHXxvey}-dDa7LmfKG@vPfUi&V`V{)BF@~FoIt& zR}ZfV#myBOl5d)`x%wGDy?Ih0K86(7pTze^1RRSDTdU^dsBzARXZBXwj)r!6^Y*qx z9FOD=nr3^28B_kDDqziVzOwx`t&Un`T+ag>95 zkAp{j7V$?cvkY~`@=$Dx#24QwX0{k>24wJBx@3gl6ErSDs{y z%P!Ylsr}=ER!1F!pt8jCw3k)S$-E(kfW~WL#XO-832ZkaN)vN1A?y_P=TKT>e(@v| zx|ej?OIo=1sF_v|#v&l%{$mcrwW2(?Uc8!_Esod_!__F!+oWG)&`9^61>9caOOSTj z9%650e3`qkj0r{=Wm(nz={rrwk~f6Jw)T?X*W{MucanGh1Qh)7`Ey$Rd8B|15(tXB zP(^{Eie@Q%J5I?1=Ih4SQpMc^UT0G(r`-?2B$`tI{++_ucwKeN0QZ7ZVYIvxvr@9< zCu_(M$-?6zdT3e4bzG_hTgVc2haQz!`q^%Zkto)t`;? z`o5#r9>Rc67;`-*4VGh8Tqm5)~IpUc%R9(OX2t4B`zN1N9lUo zx<|73BgrP%0rzXT)J!ol;?eD zgMI8@nT1g|7@2~6>E_|B5KE^05{1)Zv2q|k?mkGnLTul0C5tLCM88sb+_n_c&=ss# z^66q2RQRR}O@>Miok7bY*zY<00z;|Ygrt&X-o>+N%D8UOoh?1bJl7QmJZBHf(_-WmaJ%i3a1@J5d_@n$J`-0HOf(({ z$pSO*8#GVOS&TI^u+5{TTbvXSf3|qdi1-GgF?fXrJhTNX?03eK2v8y3Uy$Bi`sszt zS4QPRsy+T1_E{7O)sT^&#iGT^L`D)zqH?JdesJ)INlucYW#~I^9jv>&_f}qaX}ZzY zOMiSjZs(OZy#(@k0{IYbR+*BN^r|#MjE>L;%;W*CJsZMZix>&+$Y`M zR2i6ba#74A`j;{GI<5DbH>u7SM>@8>Q4Y)eTywvhAC@@~4}S-e(X@ALADwO=({FcQ zgq}ZoUHl|!jcR!fjTN z=qN(U(S4+uZxr@5AvOL8{^5+a=2JxuwpIBh4JV{Lb-E>d9IRzhlc10MngDrn;F$L* z502b`c6qR=-{R11dt?L9<~LRLue7q4LU8rBK&`AD`&Q!Xa7>I)Kg8psqs~o3%XOJ- zDUukByJQ7}By&Fcby*#|v{4X{UT=&fW@1(_Gi^L9#UzFk%6Zef}&GZ9lXNFg9v+&9|h^4^3*X z;hvZM`xCTjyxWBdVvuOyKn_<}wkj_h1PZI9D} z+std~am4R$i1eG!oF$gg)gUFpHTZjZbNl*#Wnh8!nfS5(bVlw)G%OSyLpa+Dd48K> zLx70n-qKMi0iC~@0h(Y~xQp-R8xDTBqzPj`%4GIkjuCGxeogWD!Uj)UhxK&?`3#T3 zQS1;UV~`OKLhANgcWItLvS(VxvrPY~NBqx(kXIwVX;S={3ab6}Q(He{c%e&<$mb5i zVHLl^*NTf5=C*7m9Mt z0{n#|SW`yMhWo(ok9XkVa@e#|HF1qp%)Y|Mt-yLx#Yhb7M)zFt=2VR#xmEj9e-A05 zejUBl!jJf-s@whD+X7`cc;PCpv=weRR8l~QPA>riT$I`K`SeD(RhG=Vr`@1v`x74l zhX*_c5qWB2F#mBaSVq~FwQe&Fnyg%>+$;kavFP@PrkiyVsUo z;m!Jl=>4(oSN4OilFQ0JsRHPlOpS$zKbu)%wQu+!DdF;x<(|q2z>7ud?vr9Od8u^n zx}&Cq#hiKET9Q^mw@_4E*Y2DdA&O!1iG?d&6(6*zuH>z2G>A(K7h`(|jc3YeW2*32 zmZPWo*w<>CFRJwYiE^}?hGK*znF+B_+~V35EAiKjWFBteRj;hR^%!qoQXP3rjHe^es-rS~Q`4n8D8fW_*q<`jgCVm9u!d&dTXte$`}N zS1*=#6L^Y}-2aJMJ|TDA?z?Y+L<)$RJEww!8w13DQ3SFMT4}+*3z;}WlBy(nLTy7HG z09|gpeEevRQed?ByCLS9zxSd?%gB3#?ZQ+mT~3BSe*(}6t~)o_&eAUh{)fHFx25?DCSHQ z62^&`^#Gjq?*r8s=uXvweVFqHP(1ye80ytw+Fpo*{71vdjuQ=$e^Z9nyxTLgh~fv* z-s*leV8Onl7O_vV6yzpe18PCf$A<^heqT^yl>8CNHGQL(4Pxo}gSPy#?I_Tk@RrBY z62H&SpK?l?kOz~I2Bn^(V+De5Ck}|w4IdKkoNs{p0|1y1BF?92#&dk5(3)|IR{JQ! z7IIqqy8-RK!kAp&_}2cW?QXA)d}F>}B|BRJJ~B%&iuu98!O;F6A<+|Osn=Il6b!PD zuQmi6Yy&K=q@L#n1cJL;f+e`SySokU?(XjHFnDmcV8JyI z+ycyDr)T*fI6n$=9~f|V1P4t7GJ9V54pTR#&uaDz9BC>W>Xh$ z0!*hwOfq0rv8W-%&8_e6Nf9VRd|Ey7lZs+oA_b6S3><513^sZy*!Mo^0n5+qFezEU z`nee40_(2YehWL&D4v!2p1t4$K3}`yry+lDu;AO05qxCXY}Nt^7ZQ zUlJG5)$pyY@1X|pko4=gq(x_)6pS#(hTkF-iQmp#x7cHty6XN3vT8>>@;>3xdVB%x zBBfJ}-7gBzh-M-I0*qgj4GSNZ$Y!rtKNFv>6sQ;GmNu{TGLC1wq% zbSK2={0xw5ZwX4E^27I8GxWo@SZl5?wiJx@LE~v)>*$=)A>_3EDh!B;bIW$+C78xC z8>_)1Dg^t}qsMqxIeMv0Pz0SaY#4rhVPp*0jlYM-_~?(mgv(_g^)Brp-XsnX1?_Di zOBTM81|E4V7=kmwe!C~ZbdMct#F5U0O-lVuvlQM`8FQ(>!J1je8p3?aV!_wz7siR( z5Tf|n+#H>HLWYz^b(I;IqzE%d(z{yx#OfIs4GOD@{GlE8ANscn+*cRAEpC?fL-95! zL?@XIFqRD3!-hO8nerm@uRxPb{Uj<$`}%i|#Hm5AwWhk<%0Ikl0j~x_m?K>NJ!NLm zi>$y99p_}meW1rs3A7XOAajO#Gz!zpuT_E`ImAr^)`#h;1S7JMxdO}gOeZ^56L3z# zqkp2u1r=-rG1lWwhxA`AsCNDGctquPUvw3bA16PRSejCvu>>7utWqzR2dANE+1^2X zlWd-z&FPVWKa=8LXO*M+j~V>u;TlD^vLm>SIn*r-4)Omy=t(pTq(mHIYN#WSF0x7P z@#mVF28yqB?-n>!va&zrRz$%z2XN{+XrkVeHH?a8!?$q4>WDwWp_`FtUVTzdF3E$k zcDt(S2&XkFnSF81Zi1h@93L!5TuZ|)XY^*hcLVW7n3!d^7x&3NA$Yl3)ZX^nssBis zoF*)7@D@xw!P;+7OTAIbcpDOk^j4ssSU~`*^U~vp$?$z75qhtm*(k~3y<%!W&EsLT z6qV3l_KjxqHppw~$sz$JLfz1z1arGUis zOtfic_Ohh*4ROa?gE$FiO;21FhaTJL2zoij(_{lxJSsw-h4OLahAt8YjrIls))P)u z>}w-;du{oxs0-)(4KNo`cW%uh`&jaZg;|jrXQB9-d7+Yee-6FW|^K_PPK2;_IpuHtmV%mnnBx?0Fe?#si* z1r;_&6v!?0>Je@WLY5(2I2JoaYdkkj0Q9{* z&-yk#xnYMUK<&NkVInB9C@aAu*XQmg?u29meV`HvY7AG)G*rF^C9Xenq;9zGjh?H+ zL9^wuXjmrc;w6 z-glzd$e4dZbX3dr6gnenFQNZH&rHa16u@OcUauv7HBP2H3;f8m4@X@+!AERr{d94+ zl)dG?jYJ;mIz0PTD9-Huxv>!Ac;2eSvRx++EozR}WmQS|4NM^uO0BV@9enO*r^DJJ zfSbN;tM29vsjR3HSw^#hJJbTz6#P^4$rLX1g@sK1BuL4b_%m!D2668KNtrsL!^2P> z2Q~VvE1upWfao-1_=|v%F;hleRrTDaYQ@)Rm>J6Wg#8JQwl7r~KR+w_c#fe@Xkn>d zr#C4T(XdJw?1ZE|eLyXq37JZJ%%Gq+7wH&PV zzKF@RMgW$zl4^s>VUmImZ>yzF9%@7CgV>Last1^OmO(hF>(5J)*g& z?lZn>)K-LWR9umT#%pwBIQRrw;_ecsamd_rWxZ;UjI9_UX1 z(#z7LX+Bbb=y~`lOm^bszGO4@mAcE6nI`_%TkD}kqZ1%wmAGIz+7U6?mq4j9?gl3c zGRpy|T~(N#)U{%z_8wa5X{?{rQ%n5a=2g$eqM8APXN$1CxF`9jVG(=lfydX3;H?qY!P71FI026WgWRQ9MdInO$O}H zZdj^V{OooE4zEXq6Vb-+ls-_YJu+SFhE1K$e;Iqp4=K04fp_&_?@BTOt08JkRLc>pNAnm6ILQDX#VmH?IY+r6IKT% zP4bCF**ETgc_5on0h3ldo!9sH`3PzXkv8O^Z-S^BAHBKtF|3ErKnXwhIiJw{q&5() zsq{xvnOh&d;N87)Kr6Ojgvz#^(++pCkfO`p119dFnJeg+?I&ffj9Sl?X~KH=aZSB7 z$npjQPTYEB8yPqQ7BLRXkjmy!JqL-=HvTikL6I$kWyyg(IYV-|yv@N}PSohWMj@2+3s!xW zRLRimpNTz-BEw71L)WZJhhrBhQMJ?57^do(G1cS7!#c~}jUPUbImU6Plu4?6+`G-s zEKIMSLm8q!iC{$l)C)FfQMiRjE7#uvay6n7N5KQWqk+9VHg^f7_?PiBBciMfv$UlGWKwG=_ojJ#Ws+Obm0D$Gdk%1y&gKW`qMR{gPl ziT^3=px^;Nq?5?KG~1$CR@q?j;ewlPSmm>aEk;#&<`L6__c9i4>$xLARYMJdAS9A8 zh^4#AtPxV|6kdwTG@?UU_$?}=KH%UR3cc^(r{zT-C(-rM6B7wz8)aekgufHl0lytS z)J?@?l;F<9E+3as3HnS{c` zV&i5aO!QT2*0Q|6zg}Dm{eJG-nH!z2hUDvhd$2{ZZQ;MsSmE5s`PK$HcSJ<=%1R~2 z?&K3i*P3Q2=8bkMM zR0oumFlATj(M?zE-NGE(1Lw9ps8+y~^I4@877;x@itzhM=p8BZ=FtW{!$t%45Jgnk z1$Gx}8uqgp`9+J#u|{Owps=d6K}4HLM0&_{g?`Ebj>wW(4JP`D%_wU_^im+fp~jAr zx?YhSFitm|En782Z@-}oG$GyCGA9nNa;_Gq-6Qw7t{F^AYC>v%_bBM`i<*w&A>)3V zfvQj`cQfH`eY&W=qRR(h7N(VrrDxba8#AC4)WltDH**)YC3!ChL$>*2IX+2~-n7O4 z<-2X7fFH6GQJ?H}E~Am>nqoj=)rW{83w7Alv-Jq=vGU8|Xj~CerxPPf4-vr_crxV% zc83umh5@6FLZ!@@?KrL@PxTXWww72TYPtIoMQ+0)Vn3JrnPfHIe+dmVh|=D#OwF4D z;0W3yeztjNoC4JOTYix_wMv>hrfr~_z=tWu(UE8rpwn0r=fP*$-C zuszsp%paBPcSEpPPI|lloP3=oV(`cAr$-f8)(?BbJLJO8u%szZ&VTs_SQ0k%28a_o zJXV1Np$Pxjv2mtYG=|C7VM2EhkFn$u@q>JAEEB5yN zLu*`EPw8_Vh9y1!yY@+xPZao>K2!1t`nNZ`i1%^oA?4pg;tX3o!o02rV0v(~5G7w4c(7cwD?@Z~46lXg?=>Qn4+)FAQ-gb_4j`zPWJ-nzsvMB<3PTw>lBfPsbF zfcVm~ZH9WulkMESkLV#_pqz67n@P$iTk|!GZ@!s$a6g#fP$cFEgIKbhm@5Yi;cT ztMmKgc4Dau8CeJJzL5Cd=T=xDU{OOksL|(8^wBQR83ZQe%wheF&`|vl4D}n!wOqSP zO1?6G0R4zp90BZyI%pBy-uD~d*vYiNSQ78{5UK^H96~eZe@}Ng;$OiCLxbNJ>pzHM zu3*Y~qz9@Za^PGlbY>IjozpPLi1g>P>e+FO@IsN1pgoWllt0QD{YyEX5%EcO4uCDT zWI<1OBCAG$lknZxCl_f$;m!h#+mY?wH?6e>80NlQQU?#t-iVwS^H|?|7ZOipvOw~$ z))jy#6JSqrQ6Z?w6?yJ+Kot#2Xr%_3&vo{*+nwv925_uu)ch=V=cfB#D^#B;aUr`C zFRh@;BSKq`;$k*_vbC85VXmjuY^lN~gU1foA;5bVdf|b?;=JMAS*AYN39?X>#}Sd8 z|By?A9=%cfN~aue1*b?Q&a*qcZ0SwIVzD2lNn!Z-cd&?}OiGlukss3L9zi?&*d4V^ zBR(^V^#V>{xrb}x2&Y{m1rBW_FGr+xgQiFK4Q3A9$~C?A9PgljSAbAL{Ico7DM5z6 z$6P?Z+^27s?w9>h^{RkWf~GJSXM);biHqs}CmK^W$aU1P@I)5q3#+VZ^Ua4n^j*=; z1{ioP2P@B9@;vudqW`l+Q$fpjQ=*phfP@z7u&Jg=wr4uD3Il`>#*u^rO^<9&SpY52(;t+uj1WxnoE}M1g+<=AF@Y&6@Kryd`*Dsy0VhB1TTvkLmZw zmBC-Hs(xZ!l&MKoP7sSYCy`i5q&3~vNBmO#^=CMA56DBi4qQjj_DnAz`GCf_)h>x*V0?M%|9_mbR(9Sz{m*aZZk-&>uq44 z%u)Xw^^Uyt)m~FjcheWFw}v=p=pigEX8q?JA=F-W7Fz_%;3$0d%a>n^&|=($7~wDO z01IdWOG&EuUhDH8UW6>|e9-SNG#aDh<_I`aT<3R|$DmlTmYYd~AjNoS@JqH3gVOUa zcPt#r-a*M7(~dS=L2teAxg>cvb>nG=xv#AjzHm^-xbRAkc1V$LTywvWr}{a9CGCdi z)S=Mcrnw^N-8Q(6=DR(S@^H8$?x0z|5nX*m+M&!KS$%9o@%V>MNbvk8_Q@j4-MksLUYJYxO}7qrg!t79|u z|JLxK%wfTlLB0L$_5a=ifea?M+4}fZaADcCgJ4PzBtsM#!L|kRobGqZDk^}+QiZuZ z-9=JeA8X@;*lvLm@BbKJ66c+LGDi?UD9q=l$_JMcet@N6D*NGjkA)d^`H%ahk;^6) zIHmOk1P!UwJcn^=e0O$Ws%)wf-_IDQBlyF7Bh#jCXIgE8?GF>zz*Gl9B>&+D%Ywi z>!oCbhvmxr_9DFzuUe(C^6ZyPKqv|Osmq(?eaH=(d3i6K(;gh#$ldD?$s z>W_V`{WpnU($!Iexu2|UW#z1s_r|61U?KVR#mhcULyH-tIabZgb|OA}AN z2;WM(OW`RtN~be*#S82A)AJ)X1t!?~xZ*V}476&V>K>6~I_%H8m|M>2JAzs$IAXy? z;->b+6J8cic=cMeeM^SVnG-vckY2c+DQnJD8fOg=Nt$1c(EZcASXs;Cla>Zwo zt#*x;Wzc>!97oeP6Gz}~vhvUh5r z^3qpH{mQzX*HY_0as$#&7Yd1D-)3CSU3p+md29u!)9s(^WlQEpMM@OH92H^VVBheQ z^-IywjOp+hQm-Cak1(e?CN^cV;tA{-EFbhUyq(P6xh}~IoUSbx{+s#@7g;*M%l0au zHu0?A{Li`%dn5&?0z#>ZfqN%~6EhdqXFYFdMo3-BiB@R>E(#wpzyi%atMVDMA?MS}() zX)ZtSOt2Nb0pt}I;u-k4#{l-D30g*M>HI&V*f#-?JodiFB&i^@ zv-(Yya-2X)muI3z&xn^#?BjK{6WlEUBMP`y#^LdYG+&(j%WJP$h6Ty$HvDe_komc8 z6RiJ^SY)fg0o(J_V74?&1bSClz;)(>3wJH5^0 z!Kkpd`MAOAwor3)2{(-2m4?JI%}GeaE5Rh!2K9ypuPpO z%}r~kf$dK0Pa5#N9knSEmkz4XJ33%il``SX(P3=yY}!m1uKzaX!j)Hu-z0$**>+@y-rS zvbc@A^SdP@^_f!H7~^Yw>}Vy*fRf8H0)c_26ZannPMhQk%NWsfJgt z0%VCIkRm7O0@JuCc-&4Yg5qZ@BqZ0+nVG-1Y3uDwH{KRA&<%1k`Ql|ZmmHbEz#NWn zOG+O^C>xYx$gn}|xz}Iejhp)Zx6&z)W{5_9RRdAKA(A+lq}%_mzR>+&|2V@}YO4vQ z-4BS~p*bj*WZQCZ8EPVk*)k>AAA56RK+jSUn23m7nnMeDyLn(EuFOV)`>v%?otj{U z_!MDrbg4A`EKV6Tf5`E%BLm#mkiIo5rV=tPly&OCPfjQuoIvkb`J-7n;J(ab#Wp9Z zj3-@>cM^3=S%usRb#ny8Mg}*NuWc{dO3-K}rz!RdKbkk_KX-E=eNqfz2t5Ek9cMAV zw1%Oz0d{7hk~-GBpEFe|z#^0ebSs<*oY+3cxFDQR*6T0W~Vr}ODp@VPDYnccChad4z z&gRb5en^}>-ntjP*{XP(SXm&~hQOR!S`UtEjY=ZW@}5jE3j3PD=7^B`wK)MWKGivx!8PZe*nWjh$Y~q4 zZ=)DxILd*oDQw+!WzEU_n=Quw>zDW9wG81Nk}9#={qhg`V#QHaOmXfJ(7X3a{oncZ zuaIPE1JqpD7r5Z>)=Qrg#?PS9ot3iQ3~9}+ zbk`dT=tG)!h}`*o*t6OC;MqhSCG1V~d*(6D!Y+y&70e&_xn9*{n-R8X7076BM{Bzr zhpr>wBSQKu^+2xWDJ2ZP1`Q!1Ir6@FSpiyWRx0QQ8tbN4o}RUxonX`9rLEcoZZ{$v z;6Q@8DmoW@J(A+eY%u#rGt@Hp`!sSP@iY!xe-oav8w*)2`u-(t0GOTI0G2Y`!Sq(( zXg~~%)Ykq?7`W9!yF%71HN5^%+(M4U(!yY(j*1}MDK7X~m2fNy!6B2CZ1eEba}I?q zYWuy*YRY#GVBb@1TXURhm+Q4I^5@(5Z*Mp7Wd7Xqdjfvu^%**J>=@)V+Exz6^??JQ z`bvLw`}xy4)6D`V4^8q!C)qIgho!Nd8syeN6?+2! F{uh$X`~(01 diff --git a/Tools/NativeHost/main.m b/Tools/NativeHost/main.m deleted file mode 100644 index 2a040439e..000000000 --- a/Tools/NativeHost/main.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// main.m -// NativeHost -// -// Created by Francisco Tolmasky on 5/24/09. -// Copyright 280 North, Inc. 2009. All rights reserved. -// - -#import -#import "Application.h" - -int interactive = 0; - -int main(int argc, char *argv[]) -{ - if (argc > 1 && strcmp(argv[1], "-i") == 0) { - interactive = 1; - } - - [Application sharedApplication]; - - return NSApplicationMain(argc, (const char **) argv); -} diff --git a/Tools/capp/Resources/Templates/NibApplication/Jakefile b/Tools/capp/Resources/Templates/NibApplication/Jakefile index a25464947..fd053cf00 100644 --- a/Tools/capp/Resources/Templates/NibApplication/Jakefile +++ b/Tools/capp/Resources/Templates/NibApplication/Jakefile @@ -82,18 +82,6 @@ task ("deploy", ["release"], function() printResults("Deployment") }); -task ("desktop", ["release"], function() -{ - FILE.mkdirs(FILE.join("Build", "Desktop", projectName)); - require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", projectName), FILE.join("Build", "Desktop", projectName, "__project.nameasidentifier__.app")); - printResults("Desktop") -}); - -task ("run-desktop", ["desktop"], function() -{ - OS.system([FILE.join("Build", "Desktop", projectName, "__project.nameasidentifier__.app", "Contents", "MacOS", "NativeHost"), "-i"]); -}); - function printResults(configuration) { print("----------------------------");