Skip to content

Commit

Permalink
Merge pull request #32 from hyperoslo/improvements/security
Browse files Browse the repository at this point in the history
Improves the security in ImagePicker
  • Loading branch information
zenangst committed Sep 23, 2015
2 parents 31c8ca5 + 08f055b commit c16fc17
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 106 deletions.
10 changes: 5 additions & 5 deletions Demo/ImagePickerDemo/ImagePickerDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -396,7 +396,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down Expand Up @@ -474,7 +474,7 @@
29D699F71B70ABFC0021FA73 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = Debug;
};
29D699F81B70ABFC0021FA73 /* Build configuration list for PBXNativeTarget "ImagePickerDemo" */ = {
isa = XCConfigurationList;
Expand All @@ -483,7 +483,7 @@
29D699FA1B70ABFC0021FA73 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = Debug;
};
29D699FB1B70ABFC0021FA73 /* Build configuration list for PBXNativeTarget "ImagePickerDemoTests" */ = {
isa = XCConfigurationList;
Expand All @@ -492,7 +492,7 @@
29D699FD1B70ABFC0021FA73 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
defaultConfigurationName = Debug;
};
/* End XCConfigurationList section */
};
Expand Down
12 changes: 8 additions & 4 deletions Demo/ImagePickerDemo/ImagePickerDemo/Base.lproj/LaunchScreen.xib
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6214" systemVersion="14A314h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="15A282b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6207"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
Expand All @@ -13,17 +14,20 @@
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Ramon Gilabert Llop. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ImagePickerDemo" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<animations/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
Expand Down
4 changes: 2 additions & 2 deletions Demo/ImagePickerDemo/ImagePickerDemo/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<string>no.ImagePicker.hyper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<string>ImagePicker</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
Expand Down
4 changes: 2 additions & 2 deletions Demo/ImagePickerDemo/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ DEPENDENCIES:

EXTERNAL SOURCES:
ImagePicker:
:path: "../../"
:path: ../../

SPEC CHECKSUMS:
ImagePicker: 32becfa25b8e9179e60c45411b577340d35e3e32

COCOAPODS: 0.38.2
COCOAPODS: 0.39.0.beta.4
Binary file removed Images/flashIconOff.png
Binary file not shown.
Binary file removed Images/[email protected]
Binary file not shown.
Binary file removed Images/[email protected]
Binary file not shown.
4 changes: 2 additions & 2 deletions Source/BottomView/BottomContainerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class BottomContainerView: UIView {
lazy var doneButton: UIButton = { [unowned self] in
let button = UIButton()
button.setTitle(self.configuration.cancelButtonTitle, forState: .Normal)
button.titleLabel!.font = self.configuration.doneButton
button.titleLabel?.font = self.configuration.doneButton
button.addTarget(self, action: "doneButtonDidPress:", forControlEvents: .TouchUpInside)

return button
Expand Down Expand Up @@ -80,7 +80,7 @@ class BottomContainerView: UIView {
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
fatalError("init(coder:) has not been implemented")
}

// MARK: - Action methods
Expand Down
5 changes: 2 additions & 3 deletions Source/BottomView/StackView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,13 @@ extension ImageStackView {
}

func renderViews(images: [UIImage]) {
if images.count < 1 {
//TODO: subclass view and use setimage method here to automatically adjust alpha and NIL
if let firstView = views.first where images.count < 1 {
for imageView in views {
imageView.image = nil
imageView.alpha = 0
}

views.first!.alpha = 1
firstView.alpha = 1
return
}

Expand Down
86 changes: 49 additions & 37 deletions Source/CameraView/CameraView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,20 @@ class CameraView: UIViewController {
let authorizationStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)

for device in devices {
if device.hasMediaType(AVMediaTypeVideo)
&& authorizationStatus == .Authorized {
captureDevice = device as? AVCaptureDevice
capturedDevices?.addObject(device as! AVCaptureDevice)
} else if device.hasMediaType(AVMediaTypeVideo)
&& authorizationStatus == .NotDetermined {
if let device = device as? AVCaptureDevice {
if device.hasMediaType(AVMediaTypeVideo) && authorizationStatus == .Authorized {
captureDevice = device
capturedDevices?.addObject(device)
} else if device.hasMediaType(AVMediaTypeVideo) && authorizationStatus == .NotDetermined {
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo,
completionHandler: { (granted: Bool) -> Void in
if granted {
self.captureDevice = device as? AVCaptureDevice
self.capturedDevices?.addObject(device as! AVCaptureDevice)
self.captureDevice = device
self.capturedDevices?.addObject(device)
}
})
}

}
}

Expand All @@ -103,7 +104,8 @@ class CameraView: UIViewController {
// MARK: - Camera actions

func rotateCamera() {
let deviceIndex = capturedDevices?.indexOfObject(captureDevice!)
guard let captureDevice = captureDevice else { return }
let deviceIndex = capturedDevices?.indexOfObject(captureDevice)
let currentDeviceInput = captureSession.inputs.first as! AVCaptureDeviceInput
var newDeviceIndex = 0

Expand All @@ -117,18 +119,19 @@ class CameraView: UIViewController {
}
}

captureDevice = capturedDevices?.objectAtIndex(newDeviceIndex) as? AVCaptureDevice
self.captureDevice = capturedDevices?.objectAtIndex(newDeviceIndex) as? AVCaptureDevice
configureDevice()

delegate?.handleFlashButton(captureDevice?.position == .Front)
delegate?.handleFlashButton(captureDevice.position == .Front)

guard let currentCaptureDevice = self.captureDevice else { return }
UIView.animateWithDuration(0.3, animations: { [unowned self] in
self.containerView.alpha = 1
}, completion: { finished in
self.captureSession.beginConfiguration()
self.captureSession.removeInput(currentDeviceInput)

if self.captureDevice!.supportsAVCaptureSessionPreset(AVCaptureSessionPreset1280x720) {
if currentCaptureDevice.supportsAVCaptureSessionPreset(AVCaptureSessionPreset1280x720) {
self.captureSession.sessionPreset = AVCaptureSessionPreset1280x720
} else {
self.captureSession.sessionPreset = AVCaptureSessionPreset640x480
Expand Down Expand Up @@ -173,29 +176,36 @@ class CameraView: UIViewController {
})

let queue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL)
let videoOrientation = previewLayer?.connection.videoOrientation

stillImageOutput?.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = videoOrientation!
if let videoOrientation = previewLayer?.connection.videoOrientation {
stillImageOutput?.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = videoOrientation
}

guard let stillImageOutput = self.stillImageOutput else { return }

dispatch_async(queue, { [unowned self] in
self.stillImageOutput!.captureStillImageAsynchronouslyFromConnection(self.stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo), completionHandler: { (buffer, error) -> Void in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
let image = self.cropImage(UIImage(data: imageData)!)
let orientation = self.pictureOrientation()
let assetsLibrary = ALAssetsLibrary()
assetsLibrary.writeImageToSavedPhotosAlbum(image.CGImage, orientation: orientation, completionBlock: nil)

let rotatedImage = UIImage(CGImage: image.CGImage!,
scale: 1.0,
orientation: UIImageOrientation(rawValue: orientation.rawValue)!)
self.delegate?.imageToLibrary(rotatedImage)
stillImageOutput.captureStillImageAsynchronouslyFromConnection(stillImageOutput.connectionWithMediaType(AVMediaTypeVideo),
completionHandler: { (buffer, error) -> Void in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
guard let imageFromData = UIImage(data: imageData) else { return }
let image = self.cropImage(imageFromData)
let orientation = self.pictureOrientation()
let assetsLibrary = ALAssetsLibrary()
assetsLibrary.writeImageToSavedPhotosAlbum(image.CGImage, orientation: orientation, completionBlock: nil)

guard let imageCG = image.CGImage, realOrientation = UIImageOrientation(rawValue: orientation.rawValue) else { return }
let rotatedImage = UIImage(CGImage: imageCG,
scale: 1.0,
orientation: realOrientation)
self.delegate?.imageToLibrary(rotatedImage)
})
})
})
}

func cropImage(image: UIImage) -> UIImage {
let imageReference = CGImageCreateWithImageInRect(image.CGImage, CGRect(x: 0, y: 0, width: image.size.height - 200, height: image.size.width))
let normalizedImage = UIImage(CGImage: imageReference!, scale: 1, orientation: .Right)
guard let imageReference = CGImageCreateWithImageInRect(image.CGImage,
CGRect(x: 0, y: 0, width: image.size.height - 200, height: image.size.width)) else { return UIImage() }
let normalizedImage = UIImage(CGImage: imageReference, scale: 1, orientation: .Right)

return normalizedImage
}
Expand Down Expand Up @@ -245,7 +255,8 @@ class CameraView: UIViewController {
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let anyTouch = touches.first!
guard let firstTouch = touches.first else { return }
let anyTouch = firstTouch
let touchX = anyTouch.locationInView(view).x
let touchY = anyTouch.locationInView(view).y
focusImageView.transform = CGAffineTransformIdentity
Expand Down Expand Up @@ -274,13 +285,13 @@ class CameraView: UIViewController {
print("failed to capture device")
}


previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.autoreverses = true
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
guard let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) else { return }
self.previewLayer = previewLayer
previewLayer.autoreverses = true
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
view.layer.addSublayer(previewLayer)
previewLayer.frame = view.layer.frame
view.clipsToBounds = true
view.layer.addSublayer(previewLayer!)
previewLayer?.frame = view.layer.frame
captureSession.startRunning()
delegate?.handleFlashButton(captureDevice?.position == .Front)
stillImageOutput = AVCaptureStillImageOutput()
Expand All @@ -295,8 +306,9 @@ class CameraView: UIViewController {
let bundlePath = NSBundle(forClass: self.classForCoder).resourcePath?.stringByAppendingString("/ImagePicker.bundle")
let bundle = NSBundle(path: bundlePath!)
let traitCollection = UITraitCollection(displayScale: 3)
let image = UIImage(named: name, inBundle: bundle, compatibleWithTraitCollection: traitCollection)

return image!
guard let image = UIImage(named: name, inBundle: bundle, compatibleWithTraitCollection: traitCollection) else { return UIImage() }

return image
}
}
24 changes: 12 additions & 12 deletions Source/Extensions/ConstraintsSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,18 @@ extension ImagePickerController {
extension ImageGalleryViewCell {

func setupConstraints() {
if !constraintsAdded {
for attribute: NSLayoutAttribute in [.Width, .Height, .CenterX, .CenterY] {
addConstraint(NSLayoutConstraint(item: imageView, attribute: attribute,
relatedBy: .Equal, toItem: self, attribute: attribute,
multiplier: 1, constant: 0))

addConstraint(NSLayoutConstraint(item: selectedImageView, attribute: attribute,
relatedBy: .Equal, toItem: self, attribute: attribute,
multiplier: 1, constant: 0))
}

constraintsAdded = true
guard !constraintsAdded else { return }

for attribute: NSLayoutAttribute in [.Width, .Height, .CenterX, .CenterY] {
addConstraint(NSLayoutConstraint(item: imageView, attribute: attribute,
relatedBy: .Equal, toItem: self, attribute: attribute,
multiplier: 1, constant: 0))

addConstraint(NSLayoutConstraint(item: selectedImageView, attribute: attribute,
relatedBy: .Equal, toItem: self, attribute: attribute,
multiplier: 1, constant: 0))
}

constraintsAdded = true
}
}
Loading

0 comments on commit c16fc17

Please sign in to comment.