Merge branch 'release/0.2.10'

This commit is contained in:
Bob Sun 2017-11-10 19:47:13 -08:00
commit c45a08b929
No known key found for this signature in database
GPG key ID: 1F86BA2052FED3B4
40 changed files with 505 additions and 229 deletions

View file

@ -2,7 +2,7 @@ platform :ios, '10.2'
use_frameworks!
target 'passKit' do
pod 'ObjectivePGP', :git => 'https://github.com/krzyzanowskim/ObjectivePGP.git'
pod 'ObjectivePGP', :git => 'https://github.com/krzyzanowskim/ObjectivePGP.git', :tag => '0.9.0'
target 'pass' do
inherit! :search_paths
end

View file

@ -2,7 +2,7 @@
# Pass
[![GitHub release](https://img.shields.io/github/release/mssun/pass-ios.svg)](https://github.com/mssun/pass-ios/releases)
![Swift 3.1](https://img.shields.io/badge/Swift-3.1-orange.svg)
![Swift 3.1](https://img.shields.io/badge/Swift-4.0-orange.svg)
[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/passforios/passforios)
[![Build Status](https://travis-ci.org/mssun/passforios.svg?branch=develop)](https://travis-ci.org/mssun/passforios)
[![Donate](https://img.shields.io/badge/Paypal-donate-blue.svg)](https://www.paypal.me/mssun)
@ -11,9 +11,14 @@ Pass is an iOS client compatible with [ZX2C4's Pass command line
application](http://www.passwordstore.org/). It is a password manager using
GPG for encryption and Git for version control.
Pass for iOS is available in the [App Store](https://appsto.re/us/DY13hb.i)
with the name "Pass - Password Store". If you want to join the iOS beta via
Testflight, drop an email to `developer@passforios.mssun.me`. Thank you.
Pass for iOS is available in the App Store with the name "Pass - Password Store".
<p>
<a href="https://itunes.apple.com/us/app/pass-password-store/id1205820573?mt=8"><img alt="Download on the App Store" src="badge/app_store_badge.svg" width="150"/></a>
</p>
If you want to join the iOS beta via
TestFlight, drop an email to `developer@passforios.mssun.me`. Thank you.
## Features

129
badge/app_store_badge.svg Normal file
View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="US_UK_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
<g>
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
<g>
<g>
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
</g>
</g>
<g>
<path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
H49.755z"/>
<path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
<path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
<path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
<path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
<path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
<path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
<path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M49.05,10.009c0,1.177-0.353,2.063-1.058,2.658c-0.653,0.549-1.581,0.824-2.783,0.824
c-0.596,0-1.106-0.026-1.533-0.078V6.982c0.557-0.09,1.157-0.136,1.805-0.136c1.145,0,2.008,0.249,2.59,0.747
C48.723,8.156,49.05,8.961,49.05,10.009z M47.945,10.038c0-0.763-0.202-1.348-0.606-1.756c-0.404-0.407-0.994-0.611-1.771-0.611
c-0.33,0-0.611,0.022-0.844,0.068v4.889c0.129,0.02,0.365,0.029,0.708,0.029c0.802,0,1.421-0.223,1.857-0.669
S47.945,10.892,47.945,10.038z"/>
<path fill="#FFFFFF" d="M54.909,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.009,0.718-1.727,0.718
c-0.692,0-1.243-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.712-0.698
c0.692,0,1.248,0.229,1.669,0.688C54.708,9.757,54.909,10.333,54.909,11.037z M53.822,11.071c0-0.435-0.094-0.808-0.281-1.119
c-0.22-0.376-0.533-0.564-0.94-0.564c-0.421,0-0.741,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.714-0.191,0.94-0.574
C53.725,11.882,53.822,11.506,53.822,11.071z"/>
<path fill="#FFFFFF" d="M62.765,8.719l-1.475,4.714h-0.96l-0.611-2.047c-0.155-0.511-0.281-1.019-0.379-1.523h-0.019
c-0.091,0.518-0.217,1.025-0.379,1.523l-0.649,2.047h-0.971l-1.387-4.714h1.077l0.533,2.241c0.129,0.53,0.235,1.035,0.32,1.513
h0.019c0.078-0.394,0.207-0.896,0.389-1.503l0.669-2.25h0.854l0.641,2.202c0.155,0.537,0.281,1.054,0.378,1.552h0.029
c0.071-0.485,0.178-1.002,0.32-1.552l0.572-2.202H62.765z"/>
<path fill="#FFFFFF" d="M68.198,13.433H67.15v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
c0.362,0.349,0.543,0.87,0.543,1.562V13.433z"/>
<path fill="#FFFFFF" d="M71.088,13.433h-1.047V6.556h1.047V13.433z"/>
<path fill="#FFFFFF" d="M77.258,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.01,0.718-1.727,0.718
c-0.693,0-1.244-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.711-0.698
c0.693,0,1.248,0.229,1.67,0.688C77.057,9.757,77.258,10.333,77.258,11.037z M76.17,11.071c0-0.435-0.094-0.808-0.281-1.119
c-0.219-0.376-0.533-0.564-0.939-0.564c-0.422,0-0.742,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.713-0.191,0.939-0.574
C76.074,11.882,76.17,11.506,76.17,11.071z"/>
<path fill="#FFFFFF" d="M82.33,13.433h-0.941l-0.078-0.543h-0.029c-0.322,0.433-0.781,0.65-1.377,0.65
c-0.445,0-0.805-0.143-1.076-0.427c-0.246-0.258-0.369-0.579-0.369-0.96c0-0.576,0.24-1.015,0.723-1.319
c0.482-0.304,1.16-0.453,2.033-0.446V10.3c0-0.621-0.326-0.931-0.979-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688
c0.438-0.271,0.979-0.407,1.617-0.407c1.232,0,1.85,0.65,1.85,1.95v1.736C82.262,12.78,82.285,13.155,82.33,13.433z
M81.242,11.813v-0.727c-1.156-0.02-1.734,0.297-1.734,0.95c0,0.246,0.066,0.43,0.201,0.553c0.135,0.123,0.307,0.184,0.512,0.184
c0.23,0,0.445-0.073,0.641-0.218c0.197-0.146,0.318-0.331,0.363-0.558C81.236,11.946,81.242,11.884,81.242,11.813z"/>
<path fill="#FFFFFF" d="M88.285,13.433h-0.93l-0.049-0.757h-0.029c-0.297,0.576-0.803,0.864-1.514,0.864
c-0.568,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.611-1.853c0.395-0.44,0.879-0.66,1.455-0.66
c0.633,0,1.076,0.213,1.328,0.64h0.02V6.556h1.049v5.607C88.248,12.622,88.26,13.045,88.285,13.433z M87.199,11.445v-0.786
c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.379-0.635c-0.195-0.171-0.43-0.257-0.701-0.257
c-0.391,0-0.697,0.155-0.922,0.466c-0.223,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
c0.227,0.31,0.533,0.465,0.916,0.465c0.344,0,0.619-0.129,0.828-0.388C87.1,12.069,87.199,11.781,87.199,11.445z"/>
<path fill="#FFFFFF" d="M97.248,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.008,0.718-1.727,0.718
c-0.691,0-1.242-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.713-0.698
c0.691,0,1.248,0.229,1.668,0.688C97.047,9.757,97.248,10.333,97.248,11.037z M96.162,11.071c0-0.435-0.094-0.808-0.281-1.119
c-0.221-0.376-0.533-0.564-0.941-0.564c-0.42,0-0.74,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.715-0.191,0.941-0.574
C96.064,11.882,96.162,11.506,96.162,11.071z"/>
<path fill="#FFFFFF" d="M102.883,13.433h-1.047v-2.7c0-0.832-0.316-1.248-0.951-1.248c-0.311,0-0.562,0.114-0.756,0.343
s-0.291,0.499-0.291,0.808v2.796h-1.049v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.92l0.049,0.737h0.029
c0.123-0.229,0.305-0.418,0.543-0.569c0.285-0.176,0.602-0.265,0.951-0.265c0.439,0,0.805,0.142,1.096,0.427
c0.363,0.349,0.543,0.87,0.543,1.562V13.433z"/>
<path fill="#FFFFFF" d="M109.936,9.504h-1.154v2.29c0,0.582,0.205,0.873,0.611,0.873c0.188,0,0.344-0.016,0.467-0.049
l0.027,0.795c-0.207,0.078-0.479,0.117-0.814,0.117c-0.414,0-0.736-0.126-0.969-0.378c-0.234-0.252-0.35-0.676-0.35-1.271V9.504
h-0.689V8.719h0.689V7.855l1.027-0.31v1.173h1.154V9.504z"/>
<path fill="#FFFFFF" d="M115.484,13.433h-1.049v-2.68c0-0.845-0.316-1.268-0.949-1.268c-0.486,0-0.818,0.245-1,0.735
c-0.031,0.103-0.049,0.229-0.049,0.377v2.835h-1.047V6.556h1.047v2.841h0.02c0.33-0.517,0.803-0.775,1.416-0.775
c0.434,0,0.793,0.142,1.078,0.427c0.355,0.355,0.533,0.883,0.533,1.581V13.433z"/>
<path fill="#FFFFFF" d="M121.207,10.853c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.014,0.466,0.164,0.821,0.455,1.067
c0.266,0.22,0.609,0.33,1.029,0.33c0.465,0,0.889-0.074,1.271-0.223l0.164,0.728c-0.447,0.194-0.973,0.291-1.582,0.291
c-0.73,0-1.305-0.215-1.721-0.645c-0.418-0.43-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
c0.406-0.504,0.955-0.756,1.648-0.756c0.678,0,1.193,0.252,1.541,0.756C121.068,9.77,121.207,10.265,121.207,10.853z
M120.207,10.582c0.008-0.311-0.061-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.342,0-0.621,0.142-0.834,0.427
c-0.174,0.227-0.277,0.498-0.311,0.815H120.207z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -874,10 +874,12 @@
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-passKitTests/Pods-passKitTests-frameworks.sh",
"${PODS_ROOT}/ObjectivePGP/Frameworks/ios/ObjectivePGP.framework",
"${PODS_ROOT}/ObjectivePGP/Frameworks/ios/ObjectivePGP.framework.dSYM",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ObjectivePGP.framework",
"${DWARF_DSYM_FOLDER_PATH}/ObjectivePGP.framework.dSYM",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -910,10 +912,12 @@
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-pass/Pods-pass-frameworks.sh",
"${PODS_ROOT}/ObjectivePGP/Frameworks/ios/ObjectivePGP.framework",
"${PODS_ROOT}/ObjectivePGP/Frameworks/ios/ObjectivePGP.framework.dSYM",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ObjectivePGP.framework",
"${DWARF_DSYM_FOLDER_PATH}/ObjectivePGP.framework.dSYM",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -1196,7 +1200,7 @@
SWIFT_INCLUDE_PATHS = "";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@ -1241,7 +1245,7 @@
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@ -1264,7 +1268,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).passKitTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass";
};
@ -1285,7 +1289,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).passKitTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass";
};
@ -1319,7 +1323,7 @@
PROVISIONING_PROFILE = "d25c9029-bca6-4b2d-b04e-4abc9d232740";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.mssun.passforios.find-login-action-extension";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Debug;
@ -1352,7 +1356,7 @@
PROVISIONING_PROFILE = "cbd86628-6f3e-40f3-b518-20d2330db545";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.mssun.passforios.find-login-action-extension";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Release;
@ -1368,7 +1372,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).passTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass";
};
@ -1385,7 +1389,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).passTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass";
};
@ -1444,7 +1448,7 @@
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Debug;
};
@ -1493,7 +1497,7 @@
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -1529,7 +1533,7 @@
PROVISIONING_PROFILE = "2e72f4af-b935-4970-9cd3-44d4cc24b646";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.mssun.passforios";
SWIFT_OBJC_BRIDGING_HEADER = "pass/Helpers/Objective-CBridgingHeader.h";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@ -1567,7 +1571,7 @@
PROVISIONING_PROFILE = "ee6e841d-ef77-4f00-b534-d7f1fd25dc1d";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.mssun.passforios";
SWIFT_OBJC_BRIDGING_HEADER = "pass/Helpers/Objective-CBridgingHeader.h";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View file

@ -425,13 +425,13 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LfQ-Af-j2O">
<rect key="frame" x="62" y="0.0" width="343" height="44"/>
<rect key="frame" x="62" y="0.0" width="344" height="44"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" tag="1001" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✓" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Scc-5J-bu1">
<rect key="frame" x="23" y="11" width="16" height="22"/>
<rect key="frame" x="23" y="11" width="15.666666666666664" height="22"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
@ -439,9 +439,10 @@
</subviews>
<constraints>
<constraint firstItem="Scc-5J-bu1" firstAttribute="leading" secondItem="1uB-oE-kfI" secondAttribute="leadingMargin" constant="15" id="8Z8-4c-oDD"/>
<constraint firstItem="LfQ-Af-j2O" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Scc-5J-bu1" secondAttribute="trailing" constant="20" id="I9d-Au-QVj"/>
<constraint firstItem="LfQ-Af-j2O" firstAttribute="top" secondItem="1uB-oE-kfI" secondAttribute="topMargin" constant="-8" id="OPg-oc-KZy"/>
<constraint firstItem="LfQ-Af-j2O" firstAttribute="leading" secondItem="1uB-oE-kfI" secondAttribute="leadingMargin" constant="54" id="TCp-fd-Sim"/>
<constraint firstAttribute="trailingMargin" secondItem="LfQ-Af-j2O" secondAttribute="trailing" constant="1" id="dDF-2l-XhB"/>
<constraint firstItem="LfQ-Af-j2O" firstAttribute="leading" relation="lessThanOrEqual" secondItem="1uB-oE-kfI" secondAttribute="leadingMargin" constant="54" id="TCp-fd-Sim"/>
<constraint firstAttribute="trailingMargin" secondItem="LfQ-Af-j2O" secondAttribute="trailing" id="dDF-2l-XhB"/>
<constraint firstAttribute="bottomMargin" secondItem="LfQ-Af-j2O" secondAttribute="bottom" constant="-8.3333333333333357" id="e3U-qA-37g"/>
<constraint firstItem="Scc-5J-bu1" firstAttribute="centerY" secondItem="1uB-oE-kfI" secondAttribute="centerY" id="eyS-Gb-VOi"/>
</constraints>
@ -471,10 +472,11 @@
<constraints>
<constraint firstItem="wbx-rk-i8H" firstAttribute="leading" secondItem="p3u-8b-h3U" secondAttribute="leadingMargin" constant="15" id="1gS-CT-W2C"/>
<constraint firstAttribute="bottomMargin" secondItem="Ezz-76-a53" secondAttribute="bottom" constant="-8.3333333333333357" id="NW7-VO-yjh"/>
<constraint firstItem="Ezz-76-a53" firstAttribute="leading" secondItem="p3u-8b-h3U" secondAttribute="leadingMargin" constant="54" id="Ols-7H-4Lb"/>
<constraint firstItem="Ezz-76-a53" firstAttribute="leading" relation="lessThanOrEqual" secondItem="p3u-8b-h3U" secondAttribute="leadingMargin" constant="54" id="Ols-7H-4Lb"/>
<constraint firstAttribute="trailingMargin" secondItem="Ezz-76-a53" secondAttribute="trailing" constant="1" id="hLu-eh-HXR"/>
<constraint firstItem="Ezz-76-a53" firstAttribute="top" secondItem="p3u-8b-h3U" secondAttribute="topMargin" constant="-8" id="jVn-3g-0ax"/>
<constraint firstItem="wbx-rk-i8H" firstAttribute="centerY" secondItem="p3u-8b-h3U" secondAttribute="centerY" id="jwk-j5-WsJ"/>
<constraint firstItem="Ezz-76-a53" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="wbx-rk-i8H" secondAttribute="trailing" constant="23" id="xcB-Dt-05o"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
@ -487,7 +489,7 @@
</connections>
</tableView>
<toolbarItems/>
<navigationItem key="navigationItem" title="Git Server" id="gXX-yl-9oj">
<navigationItem key="navigationItem" title="Git Server" largeTitleDisplayMode="never" id="gXX-yl-9oj">
<barButtonItem key="rightBarButtonItem" title="Clone" style="done" id="sgQ-zB-rxv">
<connections>
<action selector="save:" destination="ynQ-64-MfA" id="HNL-Da-fXT"/>
@ -596,8 +598,8 @@
<outlet property="delegate" destination="3WR-HY-zYj" id="kqI-mx-f0D"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="PGP Key" id="eK3-bb-419">
<barButtonItem key="rightBarButtonItem" systemItem="save" id="TNt-ne-l7W">
<navigationItem key="navigationItem" title="PGP Key" largeTitleDisplayMode="never" id="eK3-bb-419">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="save" id="TNt-ne-l7W">
<connections>
<action selector="save:" destination="3WR-HY-zYj" id="uLA-oz-lPI"/>
</connections>
@ -634,7 +636,7 @@
<segue destination="rRf-7l-IGe" kind="unwind" unwindAction="cancelAddPasswordWithSegue:" id="G4F-ci-BmD"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" systemItem="save" id="FtF-nT-zRJ">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="save" id="FtF-nT-zRJ">
<connections>
<segue destination="rRf-7l-IGe" kind="unwind" identifier="saveAddPasswordSegue" unwindAction="saveAddPasswordWithSegue:" id="eVU-Kz-JU0"/>
</connections>
@ -662,10 +664,11 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="scanner output" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lOI-p4-BGb">
<rect key="frame" x="50" y="562" width="314" height="45"/>
<rect key="frame" x="57" y="562" width="300" height="45"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.5" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="45" id="bdi-FH-dMP"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="300" id="zBX-AY-wU0"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
@ -675,14 +678,13 @@
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="eYa-Io-fXF" firstAttribute="top" secondItem="lOI-p4-BGb" secondAttribute="bottom" constant="80" id="9iK-9H-fuB"/>
<constraint firstItem="lOI-p4-BGb" firstAttribute="leading" secondItem="a0T-JY-UcS" secondAttribute="leadingMargin" constant="30" id="RCL-aq-Ywc"/>
<constraint firstAttribute="trailingMargin" secondItem="lOI-p4-BGb" secondAttribute="trailing" constant="30" id="qNb-4K-GGl"/>
<constraint firstItem="lOI-p4-BGb" firstAttribute="centerX" secondItem="a0T-JY-UcS" secondAttribute="centerX" id="IVH-ax-fJ3"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Scan OTP QR Codes" id="Hlb-5I-bfE">
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="KBZ-N2-OGE">
<connections>
<segue destination="0gD-ix-2NF" kind="unwind" unwindAction="cancelOTPScannerWithSegue:" id="nZe-B6-MNt"/>
<action selector="pressCancel:" destination="A9p-Qb-WmU" id="SYK-Qh-Cs7"/>
</connections>
</barButtonItem>
</navigationItem>
@ -691,7 +693,6 @@
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="rqh-SR-bIq" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="0gD-ix-2NF" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="7059" y="-1012"/>
</scene>
@ -776,8 +777,8 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="ZmJ-0Z-N04" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Settings" image="Settings" selectedImage="Settings" id="6Xa-be-Z8g"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wWs-15-HDi">
<rect key="frame" x="0.0" y="20" width="414" height="44"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" largeTitles="YES" id="wWs-15-HDi">
<rect key="frame" x="0.0" y="20" width="414" height="96"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@ -809,7 +810,7 @@
<segue destination="HB6-Yu-Y3J" kind="unwind" unwindAction="cancelEditPasswordWithSegue:" id="B5h-gu-WUv"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" systemItem="save" id="4l7-58-u8N">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="save" id="4l7-58-u8N">
<connections>
<segue destination="HB6-Yu-Y3J" kind="unwind" identifier="saveEditPasswordSegue" unwindAction="saveEditPasswordWithSegue:" id="1sb-Aa-Qdy"/>
</connections>
@ -838,7 +839,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3dt-Ph-4As">
<rect key="frame" x="20" y="10" width="374" height="726"/>
<rect key="frame" x="20" y="72" width="374" height="664"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<string key="text">K7PBbkoaJf6mLyVX3EBU
username: passforios-demo@email.com
@ -853,8 +854,8 @@ Phone Support PIN #: 84719</string>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="3dt-Ph-4As" secondAttribute="trailing" id="2IV-7r-9eG"/>
<constraint firstItem="7JD-uM-IyS" firstAttribute="top" secondItem="3dt-Ph-4As" secondAttribute="bottom" id="3yp-aL-exH"/>
<constraint firstItem="3dt-Ph-4As" firstAttribute="top" secondItem="XeK-cv-AXf" secondAttribute="bottom" constant="-54" id="5y9-J3-Luj"/>
<constraint firstAttribute="leadingMargin" secondItem="3dt-Ph-4As" secondAttribute="leading" id="jgf-j1-lNa"/>
<constraint firstItem="3dt-Ph-4As" firstAttribute="top" secondItem="XeK-cv-AXf" secondAttribute="bottom" constant="8" symbolic="YES" id="yN7-0c-t4Y"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Raw Password" id="c13-zM-tLf">
@ -969,7 +970,7 @@ Phone Support PIN #: 84719</string>
</connections>
</tableView>
<navigationItem key="navigationItem" title="SSH Key" id="DrT-Wk-L5K">
<barButtonItem key="rightBarButtonItem" systemItem="done" id="DEb-eH-FHf">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="DEb-eH-FHf">
<connections>
<action selector="doneButtonTapped:" destination="hqC-Ic-NMi" id="gIV-JX-4hk"/>
</connections>
@ -997,7 +998,7 @@ Phone Support PIN #: 84719</string>
<outlet property="delegate" destination="ljx-el-KZL" id="suq-rR-a60"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="General" id="aAM-Iw-iBA"/>
<navigationItem key="navigationItem" title="General" largeTitleDisplayMode="never" id="aAM-Iw-iBA"/>
<connections>
<segue destination="RcF-UZ-Tde" kind="show" identifier="showAboutRepositorySegue" id="X49-Em-78M"/>
</connections>
@ -1129,7 +1130,7 @@ Phone Support PIN #: 84719</string>
<outlet property="delegate" destination="Rqu-AW-ZNQ" id="FIc-7F-8PL"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Advanced" id="tc7-wf-hG7"/>
<navigationItem key="navigationItem" title="Advanced" largeTitleDisplayMode="never" id="tc7-wf-hG7"/>
<connections>
<outlet property="discardChangesTableViewCell" destination="Jm8-B5-wKx" id="rfA-G3-2OE"/>
<outlet property="encryptInASCIIArmoredTableViewCell" destination="tHt-Ro-0HF" id="tOi-Sj-mLJ"/>
@ -1155,7 +1156,7 @@ Phone Support PIN #: 84719</string>
<outlet property="delegate" destination="ZcQ-fs-QEW" id="GET-cd-P5Q"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="About" id="Pel-JD-Z5x"/>
<navigationItem key="navigationItem" title="About" largeTitleDisplayMode="never" id="Pel-JD-Z5x"/>
<connections>
<segue destination="yb5-mG-DI8" kind="show" identifier="showOpenSourceComponentsSegue" id="1lz-OC-pgC"/>
<segue destination="NEk-KW-Ogp" kind="show" identifier="showSpecialThanksSegue" id="nzG-Je-gqo"/>
@ -1271,7 +1272,7 @@ Phone Support PIN #: 84719</string>
<autoresizingMask key="autoresizingMask"/>
<attributedString key="attributedText">
<fragment>
<string key="content">GnuPG supports a command-line option --armor that that causes output to be generated in an ASCII-armored format similar to unencoded documents rather than the binary format.
<string key="content">GnuPG supports the command-line option "-a" that causes output to be generated in an ASCII-armored format similar to unencoded documents rather than the binary format.
</string>
<attributes>
@ -1324,7 +1325,7 @@ Cgo
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyB-oI-1fS">
<rect key="frame" x="15" y="8" width="391" height="144"/>
<rect key="frame" x="15" y="8" width="391" height="143.66666666666666"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
@ -1362,7 +1363,7 @@ Cgo
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lrQ-Ln-ZOv">
<rect key="frame" x="15" y="8" width="391" height="143"/>
<rect key="frame" x="15" y="8" width="391" height="143.66666666666666"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
@ -1396,8 +1397,8 @@ Cgo
<outlet property="delegate" destination="1gA-jh-frD" id="jKb-Ie-lOh"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="PGP Key" id="V4w-cf-d9g">
<barButtonItem key="rightBarButtonItem" systemItem="save" id="lVZ-mz-KGt">
<navigationItem key="navigationItem" title="PGP Key" largeTitleDisplayMode="never" id="V4w-cf-d9g">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="save" id="lVZ-mz-KGt">
<connections>
<action selector="save:" destination="1gA-jh-frD" id="dfU-DP-Eth"/>
</connections>
@ -1517,7 +1518,7 @@ Cgo
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="23o-MP-wQY">
<rect key="frame" x="15" y="8" width="391" height="143"/>
<rect key="frame" x="15" y="8" width="391" height="143.66666666666666"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
@ -1549,7 +1550,7 @@ Cgo
</connections>
</tableView>
<navigationItem key="navigationItem" title="SSH Key" id="gNq-BH-pj8">
<barButtonItem key="rightBarButtonItem" systemItem="done" id="X6m-eX-dl8">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="X6m-eX-dl8">
<connections>
<action selector="doneButtonTapped:" destination="WgM-cY-mig" id="7Yj-rw-y05"/>
</connections>
@ -1651,7 +1652,7 @@ Cgo
</connections>
</tableView>
<navigationItem key="navigationItem" title="Git Signature" id="pPi-jd-x5U">
<barButtonItem key="rightBarButtonItem" systemItem="save" id="kMD-4J-wBb">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="save" id="kMD-4J-wBb">
<connections>
<segue destination="M5P-Ab-cIc" kind="unwind" identifier="saveGitConfigSettingSegue" unwindAction="saveGitConfigSettingWithSegue:" id="RGN-ff-tuP"/>
</connections>
@ -1680,9 +1681,10 @@ Cgo
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="scanner output" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="U8O-Md-w8e">
<rect key="frame" x="50" y="611" width="314" height="45"/>
<rect key="frame" x="57" y="611" width="300" height="45"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.5" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="300" id="JcM-Sy-Hw8"/>
<constraint firstAttribute="height" constant="45" id="q3X-BT-aK8"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
@ -1692,8 +1694,7 @@ Cgo
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="U8O-Md-w8e" secondAttribute="trailing" constant="30" id="Sok-Wi-SXQ"/>
<constraint firstItem="U8O-Md-w8e" firstAttribute="leading" secondItem="CA8-A9-019" secondAttribute="leadingMargin" constant="30" id="opY-C9-XIS"/>
<constraint firstItem="U8O-Md-w8e" firstAttribute="centerX" secondItem="CA8-A9-019" secondAttribute="centerX" id="OWy-pk-0Ip"/>
<constraint firstItem="53A-gx-tky" firstAttribute="top" secondItem="U8O-Md-w8e" secondAttribute="bottom" constant="80" id="tzL-K0-lE7"/>
</constraints>
</view>
@ -1719,9 +1720,10 @@ Cgo
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="scanner output" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fsL-pq-A5q">
<rect key="frame" x="50" y="567" width="314" height="45"/>
<rect key="frame" x="57" y="567" width="300" height="45"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.5" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="300" id="7Qj-pb-GoY"/>
<constraint firstAttribute="height" constant="45" id="IPT-kM-arz"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
@ -1732,8 +1734,7 @@ Cgo
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="QZv-Im-xZk" firstAttribute="top" secondItem="fsL-pq-A5q" secondAttribute="bottom" constant="80" id="76J-7g-eVO"/>
<constraint firstItem="fsL-pq-A5q" firstAttribute="leading" secondItem="GYE-sh-yvu" secondAttribute="leadingMargin" constant="30" id="IOo-JD-FMG"/>
<constraint firstAttribute="trailingMargin" secondItem="fsL-pq-A5q" secondAttribute="trailing" constant="30" id="ymC-G4-bdA"/>
<constraint firstItem="fsL-pq-A5q" firstAttribute="centerX" secondItem="GYE-sh-yvu" secondAttribute="centerX" id="pev-xD-1vH"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Scan SSH Keys" id="bov-FI-Hkg"/>
@ -1805,7 +1806,7 @@ Cgo
<image name="Settings" width="25" height="25"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="iCM-Fy-hkk"/>
<segue reference="yyD-4H-pLE"/>
<segue reference="WfV-6d-ZUj"/>
<segue reference="UfP-k3-XeR"/>
</inferredMetricsTieBreakers>
</document>

View file

@ -10,8 +10,8 @@ import UIKit
import passKit
class AddPasswordTableViewController: PasswordEditorTableViewController {
var tempContent: String = ""
let passwordStore = PasswordStore.shared
var defaultDirPrefix = ""
override func viewDidLoad() {
tableData = [
@ -24,6 +24,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
lengthSetting.max > lengthSetting.min {
tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"])
}
tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix
super.viewDidLoad()
}
@ -38,10 +39,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
}
// check name
guard nameCell?.getContent()?.isEmpty == false else {
let alertTitle = "Cannot Add Password"
let alertMessage = "Please fill in the name."
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
guard checkName() == true else {
return false
}
}
@ -56,9 +54,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
plainText.append("\n")
plainText.append(additionsString)
}
let encodedName = (nameCell?.getContent()?.stringByAddingPercentEncodingForRFC3986())!
let name = URL(string: encodedName)!.lastPathComponent
let url = URL(string: encodedName)!.appendingPathExtension("gpg")
let (name, url) = getNameURL()
password = Password(name: name, url: url, plainText: plainText)
}
}

View file

@ -27,12 +27,8 @@ class EditPasswordTableViewController: PasswordEditorTableViewController {
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "saveEditPasswordSegue" {
if let name = nameCell?.getContent(),
let path = name.stringByAddingPercentEncodingForRFC3986(),
let _ = URL(string: path) {
return true
} else {
Utils.alert(title: "Cannot Save", message: "Password name is invalid.", controller: self, completion: nil)
// check name
guard checkName() == true else {
return false
}
}
@ -47,9 +43,7 @@ class EditPasswordTableViewController: PasswordEditorTableViewController {
plainText.append("\n")
plainText.append(additionsString)
}
let encodedName = (nameCell?.getContent()?.stringByAddingPercentEncodingForRFC3986())!
let name = URL(string: encodedName)!.lastPathComponent
let url = URL(string: encodedName)!.appendingPathExtension("gpg")
let (name, url) = getNameURL()
if password!.plainText != plainText || password!.url!.path != url.path {
password!.updatePassword(name: name, url: url, plainText: plainText)
}

View file

@ -28,12 +28,21 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
return uiSwitch
}()
let rememberPassphraseSwitch: UISwitch = {
let rememberPGPPassphraseSwitch: UISwitch = {
let uiSwitch = UISwitch()
uiSwitch.onTintColor = Globals.blue
uiSwitch.sizeToFit()
uiSwitch.addTarget(self, action: #selector(rememberPassphraseSwitchAction(_:)), for: UIControlEvents.valueChanged)
uiSwitch.isOn = SharedDefaults[.isRememberPassphraseOn]
uiSwitch.addTarget(self, action: #selector(rememberPGPPassphraseSwitchAction(_:)), for: UIControlEvents.valueChanged)
uiSwitch.isOn = SharedDefaults[.isRememberPGPPassphraseOn]
return uiSwitch
}()
let rememberGitCredentialPassphraseSwitch: UISwitch = {
let uiSwitch = UISwitch()
uiSwitch.onTintColor = Globals.blue
uiSwitch.sizeToFit()
uiSwitch.addTarget(self, action: #selector(rememberGitCredentialPassphraseSwitchAction(_:)), for: UIControlEvents.valueChanged)
uiSwitch.isOn = SharedDefaults[.isRememberGitCredentialPassphraseOn]
return uiSwitch
}()
@ -58,10 +67,11 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
// section 2
[
[.title: "Remember Passphrase", .action: "none",],
[.title: "Remember PGP Key Passphrase", .action: "none",],
[.title: "Remember Git Credential Passphrase", .action: "none",],
],
[
[.title: "Show Folder", .action: "none",],
[.title: "Show Folders", .action: "none",],
[.title: "Hide Unknown Fields", .action: "none",],
[.title: "Hide OTP Fields", .action: "none",],
],
@ -98,11 +108,15 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
cell.accessoryView = accessoryView
cell.selectionStyle = .none
hideOTPSwitch.isOn = SharedDefaults[.isHideOTPOn]
case "Remember Passphrase":
case "Remember PGP Key Passphrase":
cell.accessoryType = .none
cell.selectionStyle = .none
cell.accessoryView = rememberPassphraseSwitch
case "Show Folder":
cell.accessoryView = rememberPGPPassphraseSwitch
case "Remember Git Credential Passphrase":
cell.accessoryType = .none
cell.selectionStyle = .none
cell.accessoryView = rememberGitCredentialPassphraseSwitch
case "Show Folders":
cell.accessoryType = .none
cell.selectionStyle = .none
cell.accessoryView = showFolderSwitch
@ -176,13 +190,21 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
NotificationCenter.default.post(name: .passwordDetailDisplaySettingChanged, object: nil)
}
@objc func rememberPassphraseSwitchAction(_ sender: Any?) {
SharedDefaults[.isRememberPassphraseOn] = rememberPassphraseSwitch.isOn
if rememberPassphraseSwitch.isOn == false {
@objc func rememberPGPPassphraseSwitchAction(_ sender: Any?) {
SharedDefaults[.isRememberPGPPassphraseOn] = rememberPGPPassphraseSwitch.isOn
if rememberPGPPassphraseSwitch.isOn == false {
passwordStore.pgpKeyPassphrase = nil
}
}
@objc func rememberGitCredentialPassphraseSwitchAction(_ sender: Any?) {
SharedDefaults[.isRememberGitCredentialPassphraseOn] = rememberGitCredentialPassphraseSwitch.isOn
if rememberGitCredentialPassphraseSwitch.isOn == false {
passwordStore.gitSSHPrivateKeyPassphrase = nil
passwordStore.gitPassword = nil
}
}
@objc func showFolderSwitchAction(_ sender: Any?) {
SharedDefaults[.isShowFolderOn] = showFolderSwitch.isOn
NotificationCenter.default.post(name: .passwordDisplaySettingChanged, object: nil)

View file

@ -93,6 +93,8 @@ class GitServerSettingTableViewController: UITableViewController {
)
)
}
// Remember git credential password/passphrase temporarily, ask whether users want this after a successful clone.
SharedDefaults[.isRememberGitCredentialPassphraseOn] = true
let dispatchQueue = DispatchQueue.global(qos: .userInitiated)
dispatchQueue.async {
do {
@ -113,9 +115,21 @@ class GitServerSettingTableViewController: UITableViewController {
SharedDefaults[.gitURL] = URL(string: gitRepostiroyURL)
SharedDefaults[.gitUsername] = username
SharedDefaults[.gitAuthenticationMethod] = auth
SVProgressHUD.showSuccess(withStatus: "Done")
SVProgressHUD.dismiss(withDelay: 1)
self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self)
SVProgressHUD.dismiss()
let savePassphraseAlert = UIAlertController(title: "Done", message: "Do you want to save the Git credential password/passphrase?", preferredStyle: UIAlertControllerStyle.alert)
// no
savePassphraseAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default) { _ in
SharedDefaults[.isRememberGitCredentialPassphraseOn] = false
self.passwordStore.gitPassword = nil
self.passwordStore.gitSSHPrivateKeyPassphrase = nil
self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self)
})
// yes
savePassphraseAlert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.destructive) {_ in
SharedDefaults[.isRememberGitCredentialPassphraseOn] = true
self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self)
})
self.present(savePassphraseAlert, animated: true, completion: nil)
}
} catch {
DispatchQueue.main.async {
@ -257,7 +271,7 @@ class GitServerSettingTableViewController: UITableViewController {
case .http:
message = "Please fill in the password of your Git account."
case .ssh:
message = "Please fill in the password of your SSH key."
message = "Please fill in the passphrase of your SSH key."
}
DispatchQueue.main.async {

View file

@ -14,6 +14,9 @@ class OTPScannerController: QRScannerController {
var scannedOTP: String?
@IBAction func pressCancel(_ sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}
// MARK: - AVCaptureMetadataOutputObjectsDelegate Methods
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {

View file

@ -120,7 +120,7 @@ class PGPKeyArmorSettingTableViewController: UITableViewController, UITextViewDe
// no
savePassphraseAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default) { _ in
self.pgpPassphrase = nil
SharedDefaults[.isRememberPassphraseOn] = false
SharedDefaults[.isRememberPGPPassphraseOn] = false
self.performSegue(withIdentifier: "savePGPKeySegue", sender: self)
})
// yes
@ -129,7 +129,7 @@ class PGPKeyArmorSettingTableViewController: UITableViewController, UITextViewDe
let alert = UIAlertController(title: "Passphrase", message: "Please fill in the passphrase of your PGP secret key.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
self.pgpPassphrase = alert.textFields?.first?.text
SharedDefaults[.isRememberPassphraseOn] = true
SharedDefaults[.isRememberPGPPassphraseOn] = true
self.performSegue(withIdentifier: "savePGPKeySegue", sender: self)
}))
alert.addTextField(configurationHandler: {(textField: UITextField!) in

View file

@ -45,7 +45,7 @@ class PGPKeySettingTableViewController: UITableViewController {
// no
savePassphraseAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default) { _ in
self.pgpPassphrase = nil
SharedDefaults[.isRememberPassphraseOn] = false
SharedDefaults[.isRememberPGPPassphraseOn] = false
self.performSegue(withIdentifier: "savePGPKeySegue", sender: self)
})
// yes
@ -54,7 +54,7 @@ class PGPKeySettingTableViewController: UITableViewController {
let alert = UIAlertController(title: "Passphrase", message: "Please fill in the passphrase of your PGP secret key.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
self.pgpPassphrase = alert.textFields?.first?.text
SharedDefaults[.isRememberPassphraseOn] = true
SharedDefaults[.isRememberPGPPassphraseOn] = true
self.performSegue(withIdentifier: "savePGPKeySegue", sender: self)
}))
alert.addTextField(configurationHandler: {(textField: UITextField!) in

View file

@ -19,12 +19,6 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
private var shouldPopCurrentView = false
private let passwordStore = PasswordStore.shared
private let indicator: UIActivityIndicatorView = {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
indicator.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height * 0.382)
return indicator
}()
private lazy var editUIBarButtonItem: UIBarButtonItem = {
let uiBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(pressEdit(_:)))
return uiBarButtonItem
@ -85,10 +79,11 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 52
indicator.startAnimating()
tableView.addSubview(indicator)
editUIBarButtonItem.isEnabled = false
navigationItem.rightBarButtonItem = editUIBarButtonItem
if #available(iOS 11.0, *) {
navigationItem.largeTitleDisplayMode = .never
}
if let imageData = passwordEntity?.image {
let image = UIImage(data: imageData as Data)
@ -134,7 +129,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
self.present(alert, animated: true, completion: nil)
}
let _ = sem.wait(timeout: DispatchTime.distantFuture)
if SharedDefaults[.isRememberPassphraseOn] {
if SharedDefaults[.isRememberPGPPassphraseOn] {
self.passwordStore.pgpKeyPassphrase = passphrase
}
return passphrase
@ -174,7 +169,6 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
private func showPassword() {
DispatchQueue.main.async { [weak self] in
self?.indicator.stopAnimating()
self?.setTableData()
self?.tableView.reloadData()
self?.editUIBarButtonItem.isEnabled = true
@ -407,7 +401,11 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
}
func openLink() {
guard let urlString = self.password?.getURLString(), let url = URL(string: urlString) else {
var urlString = self.password?.getURLString() ?? ""
if !urlString.lowercased().starts(with: "https://") && !urlString.lowercased().starts(with: "http://") {
urlString = "http://\(urlString)"
}
guard let url = URL(string: urlString) else {
DispatchQueue.main.async {
Utils.alert(title: "Error", message: "Cannot find a valid URL", controller: self, completion: nil)
}

View file

@ -75,6 +75,9 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
self.tableView.sectionFooterHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionFooterHeight = 0;
}
override func viewDidLayoutSubviews() {
additionsCell?.contentTextView.setContentOffset(.zero, animated: false)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellData = tableData[indexPath.section][indexPath.row]
@ -101,7 +104,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
let minimumLength = lengthSetting?.min ?? 0
let maximumLength = lengthSetting?.max ?? 0
var defaultLength = lengthSetting?.def ?? 0
if let currentPasswordLength = (tableData[passwordSection][0][PasswordEditorCellKey.content] as? String)?.characters.count,
if let currentPasswordLength = (tableData[passwordSection][0][PasswordEditorCellKey.content] as? String)?.count,
currentPasswordLength >= minimumLength,
currentPasswordLength <= maximumLength {
defaultLength = currentPasswordLength
@ -258,4 +261,45 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
tableData[additionsSection][0][PasswordEditorCellKey.content] = additionsCell?.getContent()
}
}
func getNameURL() -> (String, URL) {
let encodedName = (nameCell?.getContent()?.stringByAddingPercentEncodingForRFC3986())!
let name = URL(string: encodedName)!.lastPathComponent
let url = URL(string: encodedName)!.appendingPathExtension("gpg")
return (name, url)
}
func checkName() -> Bool {
// the name field should not be empty
guard let name = nameCell?.getContent(), name.isEmpty == false else {
Utils.alert(title: "Cannot Save", message: "Please fill in the name.", controller: self, completion: nil)
return false
}
// the name should not start with /
guard name.hasPrefix("/") == false else {
Utils.alert(title: "Cannot Save", message: "Please remove the prefix \"/\" from your password name.", controller: self, completion: nil)
return false
}
// the name field should be a valid url
guard let path = name.stringByAddingPercentEncodingForRFC3986(),
var passwordURL = URL(string: path) else {
Utils.alert(title: "Cannot Save", message: "Password name is invalid.", controller: self, completion: nil)
return false
}
// check whether we can parse the filename (be consistent with PasswordStore::addPasswordEntities)
var previousPathLength = Int.max
while passwordURL.path != "." {
passwordURL = passwordURL.deletingLastPathComponent()
if passwordURL.path != "." && passwordURL.path.count >= previousPathLength {
Utils.alert(title: "Cannot Save", message: "Cannot parse the filename. Please check and simplify the password name.", controller: self, completion: nil)
return false
}
previousPathLength = passwordURL.path.count
}
return true
}
}

View file

@ -39,7 +39,6 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
uiSearchController.searchResultsUpdater = self
uiSearchController.dimsBackgroundDuringPresentation = false
uiSearchController.searchBar.isTranslucent = false
uiSearchController.searchBar.backgroundColor = UIColor.gray
uiSearchController.searchBar.sizeToFit()
return uiSearchController
}()
@ -48,10 +47,13 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
syncControl.addTarget(self, action: #selector(handleRefresh(_:)), for: UIControlEvents.valueChanged)
return syncControl
}()
private lazy var searchBarView: UIView = {
let uiView = UIView(frame: CGRect(x: 0, y: 64, width: self.view.bounds.width, height: 56))
uiView.addSubview(self.searchController.searchBar)
return uiView
private lazy var searchBarView: UIView? = {
guard #available(iOS 11, *) else {
let uiView = UIView(frame: CGRect(x: 0, y: 64, width: self.view.bounds.width, height: 56))
uiView.addSubview(self.searchController.searchBar)
return uiView
}
return nil
}()
private lazy var backUIBarButtonItem: UIBarButtonItem = {
let backUIBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(self.backAction(_:)))
@ -172,8 +174,17 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
DispatchQueue.main.async {
SVProgressHUD.dismiss()
self.syncControl.endRefreshing()
let error = error as NSError
var message = error.localizedDescription
if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? NSError {
message = "\(message)\nUnderlying error: \(underlyingError.localizedDescription)"
if underlyingError.localizedDescription.contains("Wrong passphrase") {
message = "\(message)\nRecovery suggestion: Wrong credential password/passphrase has been removed, please try again."
gitCredential.delete()
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(800)) {
Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil)
Utils.alert(title: "Error", message: message, controller: self, completion: nil)
}
}
}
@ -192,14 +203,21 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
override func viewDidLoad() {
super.viewDidLoad()
tabBarController!.delegate = self
searchController.searchBar.delegate = self
tableView.delegate = self
tableView.dataSource = self
tableView.contentInset = UIEdgeInsetsMake(56, 0, 0, 0)
definesPresentationContext = true
view.addSubview(searchBarView)
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .automatic
navigationItem.hidesSearchBarWhenScrolling = false
} else {
// Fallback on earlier versions
tableView.contentInset = UIEdgeInsetsMake(56, 0, 0, 0)
view.addSubview(searchBarView!)
}
tableView.refreshControl = syncControl
SVProgressHUD.setDefaultMaskType(.black)
tableView.register(UINib(nibName: "PasswordWithFolderTableViewCell", bundle: nil), forCellReuseIdentifier: "passwordWithFolderTableViewCell")
@ -223,8 +241,11 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
searchBarView.frame = CGRect(x: 0, y: navigationController!.navigationBar.bounds.size.height + UIApplication.shared.statusBarFrame.height, width: UIScreen.main.bounds.width, height: 56)
searchController.searchBar.sizeToFit()
guard #available(iOS 11, *) else {
searchBarView?.frame = CGRect(x: 0, y: navigationController!.navigationBar.bounds.size.height + UIApplication.shared.statusBarFrame.height, width: UIScreen.main.bounds.width, height: 56)
searchController.searchBar.sizeToFit()
return
}
}
func numberOfSections(in tableView: UITableView) -> Int {
@ -242,18 +263,16 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordTableViewCell", for: indexPath)
let entry = getPasswordEntry(by: indexPath)
if entry.passwordEntity!.synced {
cell.textLabel?.text = entry.title
} else {
cell.textLabel?.text = "\(entry.title)"
}
if !entry.isDir {
if entry.passwordEntity!.synced {
cell.textLabel?.text = entry.title
} else {
cell.textLabel?.text = "\(entry.title)"
}
cell.addGestureRecognizer(longPressGestureRecognizer)
cell.accessoryType = .none
cell.detailTextLabel?.text = ""
} else {
cell.textLabel?.text = "\(entry.title)"
cell.accessoryType = .disclosureIndicator
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body)
cell.detailTextLabel?.text = "\(entry.passwordEntity?.children?.count ?? 0)"
@ -351,7 +370,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
// bring back
SVProgressHUD.show(withStatus: "Decrypting")
}
if SharedDefaults[.isRememberPassphraseOn] {
if SharedDefaults[.isRememberPGPPassphraseOn] {
self.passwordStore.pgpKeyPassphrase = passphrase
}
return passphrase
@ -445,6 +464,14 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
let passwordEntity = getPasswordEntry(by: selectedIndexPath).passwordEntity!
viewController.passwordEntity = passwordEntity
}
} else if segue.identifier == "addPasswordSegue" {
if let navController = segue.destination as? UINavigationController {
if let viewController = navController.topViewController as? AddPasswordTableViewController {
if let path = parentPasswordEntity?.path {
viewController.defaultDirPrefix = "\(path)/"
}
}
}
}
}
@ -478,16 +505,15 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
private func reloadTableView(data: [PasswordsTableEntry], anim: CAAnimation? = nil) {
// set navigation item
var numberOfLocalCommitsString = ""
let numberOfLocalCommits = self.passwordStore.numberOfLocalCommits()
if numberOfLocalCommits > 0 {
numberOfLocalCommitsString = " (\(numberOfLocalCommits))"
if numberOfLocalCommits == 0 {
navigationController?.tabBarItem.badgeValue = nil
} else {
navigationController?.tabBarItem.badgeValue = "\(numberOfLocalCommits)"
}
if parentPasswordEntity != nil {
navigationItem.title = "\(parentPasswordEntity!.name!)\(numberOfLocalCommitsString)"
navigationItem.leftBarButtonItem = backUIBarButtonItem
} else {
navigationItem.title = "Password Store\(numberOfLocalCommitsString)"
navigationItem.leftBarButtonItem = nil
}

View file

@ -40,7 +40,7 @@ class QRScannerController: UIViewController, AVCaptureMetadataOutputObjectsDeleg
// Initialize the captureSession object.
captureSession = AVCaptureSession()
// Set the input device on the capture session.
captureSession?.addInput(input)
@ -90,7 +90,7 @@ class QRScannerController: UIViewController, AVCaptureMetadataOutputObjectsDeleg
// MARK: - AVCaptureMetadataOutputObjectsDelegate Methods
func metadataOutput(captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
func metadataOutput(_ captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
if let metadataObj = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
supportedCodeTypes.contains(metadataObj.type),

View file

@ -33,7 +33,7 @@ class SettingsTableViewController: UITableViewController {
if let controller = segue.source as? PGPKeySettingTableViewController {
SharedDefaults[.pgpPrivateKeyURL] = URL(string: controller.pgpPrivateKeyURLTextField.text!)
SharedDefaults[.pgpPublicKeyURL] = URL(string: controller.pgpPublicKeyURLTextField.text!)
if SharedDefaults[.isRememberPassphraseOn] {
if SharedDefaults[.isRememberPGPPassphraseOn] {
self.passwordStore.pgpKeyPassphrase = controller.pgpPassphrase
}
SharedDefaults[.pgpKeySource] = "url"
@ -61,7 +61,7 @@ class SettingsTableViewController: UITableViewController {
} else if let controller = segue.source as? PGPKeyArmorSettingTableViewController {
SharedDefaults[.pgpKeySource] = "armor"
if SharedDefaults[.isRememberPassphraseOn] {
if SharedDefaults[.isRememberPGPPassphraseOn] {
self.passwordStore.pgpKeyPassphrase = controller.pgpPassphrase
}
@ -259,7 +259,7 @@ class SettingsTableViewController: UITableViewController {
// no
savePassphraseAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default) { _ in
self.passwordStore.pgpKeyPassphrase = nil
SharedDefaults[.isRememberPassphraseOn] = false
SharedDefaults[.isRememberPGPPassphraseOn] = false
self.saveImportedPGPKey()
})
// yes
@ -268,7 +268,7 @@ class SettingsTableViewController: UITableViewController {
let alert = UIAlertController(title: "Passphrase", message: "Please fill in the passphrase of your PGP secret key.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
self.passwordStore.pgpKeyPassphrase = alert.textFields?.first?.text
SharedDefaults[.isRememberPassphraseOn] = true
SharedDefaults[.isRememberPGPPassphraseOn] = true
self.saveImportedPGPKey()
}))
alert.addTextField(configurationHandler: {(textField: UITextField!) in

View file

@ -9,7 +9,7 @@
#ifndef Objective_CBridgingHeader_h
#define Objective_CBridgingHeader_h
// #import <ObjectivePGP/ObjectivePGP.h>
#import <ObjectiveGit/ObjectiveGit.h>
#import "ObjectivePGP/ObjectivePGP.h"
#import "ObjectiveGit/ObjectiveGit.h"
#endif /* Objective_CBridgingHeader_h */

View file

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.2.9</string>
<string>0.3.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>

View file

@ -25,7 +25,7 @@ class FillPasswordTableViewCell: ContentTableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
contentTextField.font = UIFont(name: Globals.passwordFonts, size: (contentTextField.font?.pointSize)!)
contentTextField.font = Globals.passwordFont
// Force aspect ratio of button images
settingButton.imageView?.contentMode = .scaleAspectFit

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -16,17 +16,14 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="90"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="90"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="89.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="19l-R0-gP1">
<rect key="frame" x="15" y="11" width="290" height="68"/>
<rect key="frame" x="8" y="11" width="304" height="68"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="password" textAlignment="natural" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="k0U-2N-YaX" userLabel="Password">
<rect key="frame" x="0.0" y="0.0" width="230" height="68"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="9gX-VT-F9P"/>
</constraints>
<rect key="frame" x="0.0" y="0.0" width="244" height="68"/>
<nil key="textColor"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="alphabet"/>
@ -35,7 +32,7 @@
</connections>
</textField>
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hTh-ek-Xam" userLabel="Generate">
<rect key="frame" x="230" y="0.0" width="30" height="68"/>
<rect key="frame" x="244" y="0.0" width="30" height="68"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="l0l-7B-Tws"/>
</constraints>
@ -46,7 +43,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SZJ-aY-45Y" userLabel="Setting">
<rect key="frame" x="260" y="0.0" width="30" height="68"/>
<rect key="frame" x="274" y="0.0" width="30" height="68"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="D9D-FC-ANz"/>
</constraints>

View file

@ -51,7 +51,7 @@ class LabelTableViewCell: UITableViewCell {
contentLabel.text = Globals.passwordDots
}
}
contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize)
contentLabel.font = Globals.passwordFont
case "hmac-based":
type = .HOTP
if isReveal {
@ -59,7 +59,7 @@ class LabelTableViewCell: UITableViewCell {
} else {
contentLabel.text = Globals.oneTimePasswordDots
}
contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize)
contentLabel.font = Globals.passwordFont
case "url":
type = .URL
contentLabel.text = content

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -16,11 +16,11 @@
<rect key="frame" x="0.0" y="0.0" width="333" height="59"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="333" height="59"/>
<rect key="frame" x="0.0" y="0.0" width="333" height="58.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yyr-cF-QN0">
<rect key="frame" x="15" y="27" width="303" height="21"/>
<rect key="frame" x="8" y="27" width="305" height="21"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="21" id="pgw-DF-LQa"/>
</constraints>
@ -29,7 +29,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dqz-7n-uEZ">
<rect key="frame" x="15" y="11" width="303" height="13"/>
<rect key="frame" x="8" y="11" width="317" height="13"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<color key="textColor" red="0.0" green="0.47843137254901957" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@ -40,7 +40,7 @@
<constraint firstItem="Dqz-7n-uEZ" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="CVm-uc-iVo"/>
<constraint firstAttribute="topMargin" secondItem="Dqz-7n-uEZ" secondAttribute="top" id="N4y-iT-CiY"/>
<constraint firstItem="yyr-cF-QN0" firstAttribute="leading" secondItem="Dqz-7n-uEZ" secondAttribute="leading" id="TpW-bu-QIx"/>
<constraint firstItem="yyr-cF-QN0" firstAttribute="width" secondItem="Dqz-7n-uEZ" secondAttribute="width" id="ZXa-fK-0Bg"/>
<constraint firstAttribute="trailing" secondItem="yyr-cF-QN0" secondAttribute="trailing" constant="20" symbolic="YES" id="evr-4N-30Z"/>
<constraint firstAttribute="bottomMargin" secondItem="yyr-cF-QN0" secondAttribute="bottom" id="mIj-9c-ElE"/>
<constraint firstItem="yyr-cF-QN0" firstAttribute="top" secondItem="Dqz-7n-uEZ" secondAttribute="bottom" constant="3" id="sgc-hN-i8t"/>
</constraints>

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12118" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -20,7 +20,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-UZ-sLu">
<rect key="frame" x="15" y="11" width="290" height="47"/>
<rect key="frame" x="8" y="11" width="304" height="47"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="R1z-fU-Xr2"/>
</constraints>
@ -33,7 +33,7 @@
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="3h4-9E-oDJ"/>
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="FH4-4T-aaK"/>
<constraint firstAttribute="trailingMargin" secondItem="8Ky-UZ-sLu" secondAttribute="trailing" id="Nii-Cg-gC1"/>
<constraint firstAttribute="bottomMargin" secondItem="8Ky-UZ-sLu" secondAttribute="bottom" id="h72-l3-Sb3"/>
<constraint firstAttribute="bottomMargin" secondItem="8Ky-UZ-sLu" secondAttribute="bottom" priority="750" id="h72-l3-Sb3"/>
</constraints>
</tableViewCellContentView>
<connections>

View file

@ -1,14 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12118" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<customFonts key="customFonts">
<array key="Menlo.ttc">
<string>Menlo-Regular</string>
</array>
</customFonts>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -20,7 +25,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xHX-Sh-1pR">
<rect key="frame" x="15" y="11" width="290" height="195"/>
<rect key="frame" x="8" y="11" width="304" height="195"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="120" id="Tvq-j8-Nvh"/>
@ -32,7 +37,7 @@
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="xHX-Sh-1pR" secondAttribute="trailing" id="LWS-JW-9dS"/>
<constraint firstItem="xHX-Sh-1pR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="SRq-7t-Gyr"/>
<constraint firstAttribute="bottomMargin" secondItem="xHX-Sh-1pR" secondAttribute="bottom" id="UPQ-jk-QJR"/>
<constraint firstAttribute="bottomMargin" secondItem="xHX-Sh-1pR" secondAttribute="bottom" priority="750" id="UPQ-jk-QJR"/>
<constraint firstItem="xHX-Sh-1pR" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="gwb-2C-4wp"/>
</constraints>
</tableViewCellContentView>

View file

@ -143,6 +143,12 @@
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024@1x.png",
"scale" : "1x"
}
],
"info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="QHc-XA-1MZ">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="QHc-XA-1MZ">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13174"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -13,7 +13,7 @@
<!--Password Store-->
<scene sceneID="NlT-0d-7x9">
<objects>
<viewController id="DnC-Ka-AYb" customClass="ExtensionViewController" customModule="passextension" customModuleProvider="target" sceneMemberID="viewController">
<viewController id="DnC-Ka-AYb" customClass="ExtensionViewController" customModule="passExtension" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="TbF-II-itz"/>
<viewControllerLayoutGuide type="bottom" id="9b9-wt-KCV"/>
@ -25,7 +25,7 @@
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="P9f-HJ-cS5">
<rect key="frame" x="0.0" y="64" width="375" height="626"/>
<subviews>
<searchBar contentMode="redraw" showsCancelButton="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xuO-jY-YRU">
<searchBar contentMode="redraw" translatesAutoresizingMaskIntoConstraints="NO" id="xuO-jY-YRU">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<textInputTraits key="textInputTraits"/>
</searchBar>
@ -37,18 +37,18 @@
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="T2b-vj-fza" id="aVb-V4-hqg">
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="LUo-8T-I4j">
<rect key="frame" x="15" y="12" width="33" height="21"/>
<rect key="frame" x="15" y="12" width="33.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9ik-sy-sTS">
<rect key="frame" x="296" y="12" width="44" height="21"/>
<rect key="frame" x="296" y="12" width="44" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
@ -101,7 +101,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="QHc-XA-1MZ" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="WRo-Vb-Kcg">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>

View file

@ -12,10 +12,14 @@ import passKit
fileprivate class PasswordsTableEntry : NSObject {
var title: String
var categoryText: String
var categoryArray: [String]
var passwordEntity: PasswordEntity?
init(title: String, passwordEntity: PasswordEntity?) {
self.title = title
self.passwordEntity = passwordEntity
init(_ entity: PasswordEntity) {
self.title = entity.name!
self.categoryText = entity.getCategoryText()
self.categoryArray = entity.getCategoryArray()
self.passwordEntity = entity
}
}
@ -46,7 +50,7 @@ class ExtensionViewController: UIViewController, UITableViewDataSource, UITableV
var passwordEntities = [PasswordEntity]()
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(withDir: false)
passwordsTableEntries = passwordEntities.map {
PasswordsTableEntry(title: $0.name!, passwordEntity: $0)
PasswordsTableEntry($0)
}
}
@ -141,7 +145,7 @@ class ExtensionViewController: UIViewController, UITableViewDataSource, UITableV
}
cell.accessoryType = .none
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
cell.detailTextLabel?.text = entry.passwordEntity?.getCategoryText()
cell.detailTextLabel?.text = entry.categoryText
return cell
}
@ -223,7 +227,7 @@ class ExtensionViewController: UIViewController, UITableViewDataSource, UITableV
self.present(alert, animated: true, completion: nil)
}
let _ = sem.wait(timeout: DispatchTime.distantFuture)
if SharedDefaults[.isRememberPassphraseOn] {
if SharedDefaults[.isRememberPGPPassphraseOn] {
self.passwordStore.pgpKeyPassphrase = passphrase
}
return passphrase
@ -241,10 +245,15 @@ class ExtensionViewController: UIViewController, UITableViewDataSource, UITableV
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
if let searchText = searchBar.text, searchText.isEmpty == false {
let searchTextLowerCased = searchText.lowercased()
filteredPasswordsTableEntries = passwordsTableEntries.filter { entry in
let entryTitle = entry.title.lowercased()
return entryTitle.contains(searchTextLowerCased) || searchTextLowerCased.contains(entryTitle)
var matched = false
matched = matched || entry.title.range(of: searchText, options: .caseInsensitive) != nil
matched = matched || searchText.range(of: entry.title, options: .caseInsensitive) != nil
entry.categoryArray.forEach({ (category) in
matched = matched || category.range(of: searchText, options: .caseInsensitive) != nil
matched = matched || searchText.range(of: category, options: .caseInsensitive) != nil
})
return matched
}
searchActive = true
} else {

View file

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.2.9</string>
<string>0.3.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>

View file

@ -15,6 +15,7 @@ public enum AppError: Error {
case PasswordDuplicatedError
case GitResetError
case PGPPublicKeyNotExistError
case WrongPasswordFilename
case UnknownError
}
@ -33,6 +34,8 @@ extension AppError: LocalizedError {
return "Cannot identify the latest synced commit."
case .PGPPublicKeyNotExistError:
return "PGP public key doesn't exist."
case .WrongPasswordFilename:
return "Cannot write to the password file."
case .UnknownError:
return "Unknown error."
}

View file

@ -35,7 +35,8 @@ public extension DefaultsKeys {
static let isHideUnknownOn = DefaultsKey<Bool>("isHideUnknownOn")
static let isHideOTPOn = DefaultsKey<Bool>("isHideOTPOn")
static let isRememberPassphraseOn = DefaultsKey<Bool>("isRememberPassphraseOn")
static let isRememberPGPPassphraseOn = DefaultsKey<Bool>("isRememberPGPPassphraseOn")
static let isRememberGitCredentialPassphraseOn = DefaultsKey<Bool>("isRememberGitCredentialPassphraseOn")
static let isShowFolderOn = DefaultsKey<Bool>("isShowFolderOn")
static let passwordGeneratorFlavor = DefaultsKey<String>("passwordGeneratorFlavor")

View file

@ -47,11 +47,14 @@ public class Globals {
public static let passwordDots = "••••••••••••"
public static let oneTimePasswordDots = "••••••"
public static let passwordFonts = "Menlo"
public static let passwordFont = UIFont(name: "Courier-Bold", size: UIFont.labelFontSize - 1)
// UI related
public static let red = UIColor(red:1.00, green:0.23, blue:0.19, alpha:1.0)
public static let blue = UIColor(red:0.00, green:0.48, blue:1.00, alpha:1.0)
public static let letterColor = UIColor(red:40/255.0, green:42/255.0, blue:54/255.0, alpha:1.0)
public static let symbolColor = UIColor(red:200/255.0, green:40/255.0, blue:41/255.0, alpha:1.0)
public static let digitColor = UIColor(red:66/255.0, green:113/255.0, blue:174/255.0, alpha:1.0)
public static let tableCellButtonSize = CGFloat(20.0)
private init() { }

View file

@ -107,9 +107,11 @@ public class Utils {
for (index, element) in plainPassword.unicodeScalars.enumerated() {
var charColor = UIColor.darkText
if NSCharacterSet.decimalDigits.contains(element) {
charColor = Globals.red
charColor = Globals.digitColor
} else if !NSCharacterSet.letters.contains(element) {
charColor = Globals.blue
charColor = Globals.symbolColor
} else {
charColor = Globals.letterColor
}
attributedPassword.addAttribute(NSAttributedStringKey.foregroundColor, value: charColor, range: NSRange(location: index, length: 1))
}

View file

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>0.3.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View file

@ -26,38 +26,39 @@ public struct GitCredential {
public func credentialProvider(requestGitPassword: @escaping (Credential, String?) -> String?) throws -> GTCredentialProvider {
var attempts = 0
var lastPassword: String? = nil
return GTCredentialProvider { (_, _, _) -> (GTCredential?) in
var credential: GTCredential? = nil
switch self.credential {
case let .http(userName):
var newPassword = self.passwordStore.gitPassword
if newPassword == nil || attempts != 0 {
var lastPassword = self.passwordStore.gitPassword
if lastPassword == nil || attempts != 0 {
if let requestedPassword = requestGitPassword(self.credential, lastPassword) {
newPassword = requestedPassword
self.passwordStore.gitPassword = newPassword
if SharedDefaults[.isRememberGitCredentialPassphraseOn] {
self.passwordStore.gitPassword = requestedPassword
}
lastPassword = requestedPassword
} else {
return nil
}
}
attempts += 1
lastPassword = newPassword
credential = try? GTCredential(userName: userName, password: newPassword!)
credential = try? GTCredential(userName: userName, password: lastPassword!)
case let .ssh(userName, privateKeyFile):
// remarks: in fact, attempts > 1 never happens even with the wrong passphrase
var newPassword = self.passwordStore.gitSSHPrivateKeyPassphrase
if newPassword == nil || attempts != 0 {
var lastPassword = self.passwordStore.gitSSHPrivateKeyPassphrase
if lastPassword == nil || attempts != 0 {
if let requestedPassword = requestGitPassword(self.credential, lastPassword) {
newPassword = requestedPassword
self.passwordStore.gitSSHPrivateKeyPassphrase = newPassword
if SharedDefaults[.isRememberGitCredentialPassphraseOn] {
self.passwordStore.gitSSHPrivateKeyPassphrase = requestedPassword
}
lastPassword = requestedPassword
} else {
return nil
}
}
attempts += 1
lastPassword = newPassword
credential = try? GTCredential(userName: userName, publicKeyURL: nil, privateKeyURL: privateKeyFile, passphrase: newPassword!)
credential = try? GTCredential(userName: userName, publicKeyURL: nil, privateKeyURL: privateKeyFile, passphrase: lastPassword!)
}
return credential
}
@ -66,9 +67,9 @@ public struct GitCredential {
public func delete() {
switch credential {
case .http:
Utils.removeKeychain(name: "gitPassword")
self.passwordStore.gitPassword = nil
case .ssh:
Utils.removeKeychain(name: "gitSSHKeyPassphrase")
self.passwordStore.gitSSHPrivateKeyPassphrase = nil
}
}
}

View file

@ -84,7 +84,7 @@ public class Password {
additions.removeAll()
// split the plain text
let plainTextSplit = plainText.characters.split(maxSplits: 1, omittingEmptySubsequences: false) {
let plainTextSplit = plainText.split(maxSplits: 1, omittingEmptySubsequences: false) {
$0 == "\n" || $0 == "\r\n"
}.map(String.init)
@ -167,7 +167,7 @@ public class Password {
public func getAdditionsPlainText() -> String {
// lines starting from the second
let plainTextSplit = plainText.characters.split(maxSplits: 1, omittingEmptySubsequences: false) {
let plainTextSplit = plainText.split(maxSplits: 1, omittingEmptySubsequences: false) {
$0 == "\n" || $0 == "\r\n"
}.map(String.init)
if plainTextSplit.count == 1 {

View file

@ -22,6 +22,10 @@ extension PasswordEntity {
}
public func getCategoryText() -> String {
return getCategoryArray().joined(separator: " > ")
}
public func getCategoryArray() -> [String] {
var parentEntity = parent
var passwordCategoryArray: [String] = []
while parentEntity != nil {
@ -29,7 +33,7 @@ extension PasswordEntity {
parentEntity = parentEntity!.parent
}
passwordCategoryArray.reverse()
return passwordCategoryArray.joined(separator: " > ")
return passwordCategoryArray
}
public func getURL() -> URL? {

View file

@ -21,16 +21,16 @@ public class PasswordStore {
public var storeRepository: GTRepository?
public var pgpKeyID: String?
public var publicKey: PGPKey? {
public var publicKey: Key? {
didSet {
if publicKey != nil {
pgpKeyID = publicKey!.keyID.shortKeyString
pgpKeyID = publicKey!.keyID.shortIdentifier
} else {
pgpKeyID = nil
}
}
}
public var privateKey: PGPKey?
public var privateKey: Key?
public var gitSignatureForNow: GTSignature {
get {
@ -120,6 +120,7 @@ public class PasswordStore {
print(Globals.documentPathLegacy)
print(Globals.libraryPathLegacy)
migrateIfNeeded()
backwardCompatibility()
do {
if fm.fileExists(atPath: storeURL.path) {
@ -166,6 +167,17 @@ public class PasswordStore {
updatePasswordEntityCoreData()
}
private func backwardCompatibility() {
// For the newly-introduced isRememberGitCredentialPassphraseOn (20171008)
if (self.gitPassword != nil || self.gitSSHPrivateKeyPassphrase != nil) && SharedDefaults[.isRememberGitCredentialPassphraseOn] == false {
SharedDefaults[.isRememberGitCredentialPassphraseOn] = true
}
// For the renamed isRememberPGPPassphraseOn (20171008)
if self.pgpKeyPassphrase != nil && SharedDefaults[.isRememberPGPPassphraseOn] == false {
SharedDefaults[.isRememberPGPPassphraseOn] = true
}
}
enum SSHKeyType {
case `public`, secret
}
@ -223,9 +235,10 @@ public class PasswordStore {
}
private func importKey(from keyPath: String) -> PGPKey? {
private func importKey(from keyPath: String) -> Key? {
if fm.fileExists(atPath: keyPath) {
let keys = pgp.importKeys(fromFile: keyPath)
let keys = ObjectivePGP.readKeys(from: keyPath)
pgp.import(keys: keys)
if !keys.isEmpty {
return keys.first
}
@ -233,7 +246,7 @@ public class PasswordStore {
return nil
}
public func getPgpPrivateKey() -> PGPKey {
public func getPgpPrivateKey() -> Key {
return pgp.keys.filter({$0.secretKey != nil})[0]
}
@ -328,7 +341,6 @@ public class PasswordStore {
let remote = try GTRemote(name: "origin", in: storeRepository)
try storeRepository.pull(storeRepository.currentBranch(), from: remote, withOptions: options, progress: transferProgressBlock)
} catch {
credential.delete()
throw(error)
}
DispatchQueue.main.async {
@ -459,17 +471,6 @@ public class PasswordStore {
}
}
public func getNumberOfUnsyncedPasswords() -> Int {
let passwordEntityFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "PasswordEntity")
do {
passwordEntityFetchRequest.predicate = NSPredicate(format: "synced = %i", 0)
return try context.count(for: passwordEntityFetchRequest)
} catch {
fatalError("Failed to fetch unsynced passwords: \(error)")
}
}
public func getLatestUpdateInfo(filename: String) -> String {
guard let storeRepository = storeRepository else {
return "Unknown"
@ -581,7 +582,6 @@ public class PasswordStore {
try storeRepository.push(masterBranch, to: remote, withOptions: options, progress: transferProgressBlock)
}
} catch {
credential.delete()
throw(error)
}
}
@ -592,18 +592,26 @@ public class PasswordStore {
}
var passwordURL = password.url!
var previousPathLength = Int.max
var paths: [String] = []
while passwordURL.path != "." {
paths.append(passwordURL.path)
passwordURL = passwordURL.deletingLastPathComponent()
// better identify errors before saving a new password
if passwordURL.path != "." && passwordURL.path.count >= previousPathLength {
throw AppError.WrongPasswordFilename
}
previousPathLength = passwordURL.path.count
}
paths.reverse()
print(paths)
var parentPasswordEntity: PasswordEntity? = nil
for path in paths {
let isDir = !path.hasSuffix(".gpg")
if let passwordEntity = getPasswordEntity(by: path, isDir: isDir) {
print(passwordEntity.path!)
parentPasswordEntity = passwordEntity
passwordEntity.synced = false
} else {
if !isDir {
return insertPasswordEntity(name: URL(string: path.stringByAddingPercentEncodingForRFC3986()!)!.deletingPathExtension().lastPathComponent, path: path, parent: parentPasswordEntity, synced: false, isDir: false)
@ -661,8 +669,9 @@ public class PasswordStore {
let saveURL = storeURL.appendingPathComponent(passwordEntity.getURL()!.path)
try self.encrypt(password: password).write(to: saveURL)
try gitAdd(path: passwordEntity.getURL()!.path)
let _ = try gitCommit(message: "Edit password for \(passwordEntity.getURL()!.deletingPathExtension().path.removingPercentEncoding!) to store using Pass for iOS.")
let _ = try gitCommit(message: "Edit password for \(passwordEntity.getURL()!.deletingPathExtension().path.removingPercentEncoding!) using Pass for iOS.")
newPasswordEntity = passwordEntity
newPasswordEntity?.synced = false
}
if password.changed&PasswordChange.path.rawValue != 0 {
@ -831,7 +840,7 @@ public class PasswordStore {
if passphrase == nil {
passphrase = requestPGPKeyPassphrase()
}
let decryptedData = try PasswordStore.shared.pgp.decryptData(encryptedData, passphrase: passphrase)
let decryptedData = try PasswordStore.shared.pgp.decrypt(encryptedData, passphrase: passphrase)
let plainText = String(data: decryptedData, encoding: .utf8) ?? ""
let escapedPath = passwordEntity.path!.stringByAddingPercentEncodingForRFC3986() ?? ""
return Password(name: passwordEntity.name!, url: URL(string: escapedPath), plainText: plainText)
@ -843,7 +852,7 @@ public class PasswordStore {
throw AppError.PGPPublicKeyNotExistError
}
let plainData = password.getPlainData()
let encryptedData = try pgp.encryptData(plainData, using: Array(publicKey), armored: SharedDefaults[.encryptInArmored])
let encryptedData = try pgp.encrypt(plainData, using: Array(publicKey), armored: SharedDefaults[.encryptInArmored])
return encryptedData
}
@ -865,7 +874,7 @@ public class PasswordStore {
Utils.removeFileIfExists(atPath: Globals.gitSSHPrivateKeyPath)
Defaults.remove(.gitSSHPrivateKeyArmor)
Defaults.remove(.gitSSHPrivateKeyURL)
Utils.removeKeychain(name: ".gitSSHPrivateKeyPassphrase")
self.gitSSHPrivateKeyPassphrase = nil
}
public func gitSSHKeyExists(inFileSharing: Bool = false) -> Bool {