2
0

Compare commits

..

10 Commits

Author SHA1 Message Date
Maarten Billemont
d1104e4028 Need icon 1x icon for iPad. 2020-04-30 09:32:17 -04:00
Maarten Billemont
e9f2a25c9c Project icons update. 2020-04-28 13:49:34 -04:00
Maarten Billemont
171a3f0978 Icon update. 2020-04-28 12:24:41 -04:00
Maarten Billemont
8cfb9a83c5 mpjson support on iOS. 2020-04-27 16:33:10 -04:00
Maarten Billemont
5717375e75 Improve language. 2020-04-27 16:33:01 -04:00
Maarten Billemont
cc2dca3bd0 Report missing support when trying to parse unknown format. 2020-04-27 16:32:30 -04:00
Maarten Billemont
7575924d80 Bump site links to macOS app. 2020-04-26 00:39:08 -04:00
Maarten Billemont
8bedcedfaf Enable support for internal actions from URLs. 2020-04-25 17:13:48 -04:00
Maarten Billemont
10b205c541 Open URLs in external browser. 2020-04-25 11:44:27 -04:00
Maarten Billemont
774f183ac0 Improved web support & trigger notification URLs. 2020-04-25 10:44:59 -04:00
36 changed files with 507 additions and 285 deletions

3
.gitmodules vendored
View File

@@ -15,7 +15,6 @@
url = https://github.com/json-c/json-c.git url = https://github.com/json-c/json-c.git
[submodule "public/site"] [submodule "public/site"]
path = public/site path = public/site
url = https://github.com/Lyndir/MasterPassword.git url = https://gitlab.com/MasterPassword/MasterPassword.git
branch = gh-pages branch = gh-pages
shallow = true shallow = true
update = none

View File

@@ -77,11 +77,6 @@
DA0CC5951EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC58B1EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.m */; }; DA0CC5951EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = DA0CC58B1EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.m */; };
DA24EBAE19DAD08900FF010B /* tip_basic_black_top.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38941711E29700CF925C /* tip_basic_black_top.png */; }; DA24EBAE19DAD08900FF010B /* tip_basic_black_top.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38941711E29700CF925C /* tip_basic_black_top.png */; };
DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38951711E29700CF925C /* tip_basic_black_top@2x.png */; }; DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD38951711E29700CF925C /* tip_basic_black_top@2x.png */; };
DA24EBE819DAD6DE00FF010B /* Icon-320.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBE619DAD6DE00FF010B /* Icon-320.png */; };
DA24EBE919DAD6DE00FF010B /* Icon-64.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBE719DAD6DE00FF010B /* Icon-64.png */; };
DA24EBEA19DAD6EE00FF010B /* Icon-Small.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBBA19DAD4D000FF010B /* Icon-Small.png */; };
DA24EBEB19DAD6EE00FF010B /* Icon-Small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBBB19DAD4D000FF010B /* Icon-Small@2x.png */; };
DA24EBEC19DAD6EE00FF010B /* Icon-Small@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA24EBBC19DAD4D000FF010B /* Icon-Small@3x.png */; };
DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */; }; DA250A17195665A100AC23F1 /* UITableView+PearlReloadItems.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */; };
DA250A18195665A100AC23F1 /* UITableView+PearlReloadItems.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */; }; DA250A18195665A100AC23F1 /* UITableView+PearlReloadItems.h in Headers */ = {isa = PBXBuildFile; fileRef = DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */; };
DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */; }; DA250A19195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */; };
@@ -155,6 +150,21 @@
DA5BFA4B147E415C00F98B1E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DA5BFA4B147E415C00F98B1E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
DA5BFA4D147E415C00F98B1E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */; }; DA5BFA4D147E415C00F98B1E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */; };
DA5BFA4F147E415C00F98B1E /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4E147E415C00F98B1E /* CoreData.framework */; }; DA5BFA4F147E415C00F98B1E /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4E147E415C00F98B1E /* CoreData.framework */; };
DA5E0E5524589C9B0007FBA7 /* Icon-Small@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4624589C9A0007FBA7 /* Icon-Small@3x.png */; };
DA5E0E5624589C9B0007FBA7 /* Icon-Small-40.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4724589C9A0007FBA7 /* Icon-Small-40.png */; };
DA5E0E5724589C9B0007FBA7 /* Icon-Small-20.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4824589C9A0007FBA7 /* Icon-Small-20.png */; };
DA5E0E5824589C9B0007FBA7 /* Icon-76.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4924589C9A0007FBA7 /* Icon-76.png */; };
DA5E0E5924589C9B0007FBA7 /* Icon-Small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4A24589C9A0007FBA7 /* Icon-Small@2x.png */; };
DA5E0E5A24589C9B0007FBA7 /* Icon-Small-40@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4B24589C9A0007FBA7 /* Icon-Small-40@2x.png */; };
DA5E0E5B24589C9B0007FBA7 /* Icon-76@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4C24589C9A0007FBA7 /* Icon-76@2x.png */; };
DA5E0E5C24589C9B0007FBA7 /* Icon-Small-20@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4D24589C9A0007FBA7 /* Icon-Small-20@3x.png */; };
DA5E0E5D24589C9B0007FBA7 /* Icon-Small.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4E24589C9A0007FBA7 /* Icon-Small.png */; };
DA5E0E5E24589C9B0007FBA7 /* Icon-83@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E4F24589C9A0007FBA7 /* Icon-83@2x.png */; };
DA5E0E5F24589C9B0007FBA7 /* Icon-Small-40@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E5024589C9A0007FBA7 /* Icon-Small-40@3x.png */; };
DA5E0E6024589C9B0007FBA7 /* Icon-60@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E5124589C9A0007FBA7 /* Icon-60@3x.png */; };
DA5E0E6124589C9B0007FBA7 /* iTunesArtwork@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E5224589C9B0007FBA7 /* iTunesArtwork@2x.png */; };
DA5E0E6224589C9B0007FBA7 /* Icon-Small-20@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E5324589C9B0007FBA7 /* Icon-Small-20@2x.png */; };
DA5E0E6324589C9B0007FBA7 /* Icon-60@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5E0E5424589C9B0007FBA7 /* Icon-60@2x.png */; };
DA6701B816406A4100B61001 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701B716406A4100B61001 /* Accounts.framework */; settings = {ATTRIBUTES = (Required, ); }; }; DA6701B816406A4100B61001 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701B716406A4100B61001 /* Accounts.framework */; settings = {ATTRIBUTES = (Required, ); }; };
DA6701DE16406B7300B61001 /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701DD16406B7300B61001 /* Social.framework */; settings = {ATTRIBUTES = (Required, ); }; }; DA6701DE16406B7300B61001 /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701DD16406B7300B61001 /* Social.framework */; settings = {ATTRIBUTES = (Required, ); }; };
DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701DF16406BB400B61001 /* AdSupport.framework */; settings = {ATTRIBUTES = (Required, ); }; }; DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA6701DF16406BB400B61001 /* AdSupport.framework */; settings = {ATTRIBUTES = (Required, ); }; };
@@ -166,6 +176,7 @@
DA69540617D975D900BF294E /* icon_gears.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37841711E29500CF925C /* icon_gears.png */; }; DA69540617D975D900BF294E /* icon_gears.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37841711E29500CF925C /* icon_gears.png */; };
DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37851711E29500CF925C /* icon_gears@2x.png */; }; DA69540717D975D900BF294E /* icon_gears@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37851711E29500CF925C /* icon_gears@2x.png */; };
DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */ = {isa = PBXBuildFile; fileRef = DACE2F6719BA6A2A0010F92E /* UIView+FontScale.m */; }; DA72BD7B19C1510C00E6ACFE /* UIView+FontScale.m in Sources */ = {isa = PBXBuildFile; fileRef = DACE2F6719BA6A2A0010F92E /* UIView+FontScale.m */; };
DA72E2302453B91700676D4F /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA72E22F2453B91700676D4F /* WebKit.framework */; };
DA73049D194E022700E72520 /* ui_spinner.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36511711E29400CF925C /* ui_spinner.png */; }; DA73049D194E022700E72520 /* ui_spinner.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36511711E29400CF925C /* ui_spinner.png */; };
DA73049E194E022700E72520 /* ui_spinner@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36521711E29400CF925C /* ui_spinner@2x.png */; }; DA73049E194E022700E72520 /* ui_spinner@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36521711E29400CF925C /* ui_spinner@2x.png */; };
DA73049F194E022B00E72520 /* ui_textfield.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD365B1711E29400CF925C /* ui_textfield.png */; }; DA73049F194E022B00E72520 /* ui_textfield.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD365B1711E29400CF925C /* ui_textfield.png */; };
@@ -573,19 +584,6 @@
DA0CC5891EB6B030009A8ED9 /* MPSiteEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteEntity+CoreDataClass.m"; sourceTree = "<group>"; }; DA0CC5891EB6B030009A8ED9 /* MPSiteEntity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteEntity+CoreDataClass.m"; sourceTree = "<group>"; };
DA0CC58A1EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPSiteEntity+CoreDataProperties.h"; sourceTree = "<group>"; }; DA0CC58A1EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPSiteEntity+CoreDataProperties.h"; sourceTree = "<group>"; };
DA0CC58B1EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteEntity+CoreDataProperties.m"; sourceTree = "<group>"; }; DA0CC58B1EB6B030009A8ED9 /* MPSiteEntity+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPSiteEntity+CoreDataProperties.m"; sourceTree = "<group>"; };
DA24EBB219DAD4D000FF010B /* Icon-60.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60.png"; sourceTree = "<group>"; };
DA24EBB319DAD4D000FF010B /* Icon-60@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@2x.png"; sourceTree = "<group>"; };
DA24EBB419DAD4D000FF010B /* Icon-60@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@3x.png"; sourceTree = "<group>"; };
DA24EBB519DAD4D000FF010B /* Icon-76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-76.png"; sourceTree = "<group>"; };
DA24EBB619DAD4D000FF010B /* Icon-76@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-76@2x.png"; sourceTree = "<group>"; };
DA24EBB719DAD4D000FF010B /* Icon-Small-40.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40.png"; sourceTree = "<group>"; };
DA24EBB819DAD4D000FF010B /* Icon-Small-40@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40@2x.png"; sourceTree = "<group>"; };
DA24EBB919DAD4D000FF010B /* Icon-Small-40@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40@3x.png"; sourceTree = "<group>"; };
DA24EBBA19DAD4D000FF010B /* Icon-Small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small.png"; sourceTree = "<group>"; };
DA24EBBB19DAD4D000FF010B /* Icon-Small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@2x.png"; sourceTree = "<group>"; };
DA24EBBC19DAD4D000FF010B /* Icon-Small@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@3x.png"; sourceTree = "<group>"; };
DA24EBBD19DAD4D000FF010B /* iTunesArtwork.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iTunesArtwork.png; sourceTree = "<group>"; };
DA24EBBE19DAD4D000FF010B /* iTunesArtwork@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork@2x.png"; sourceTree = "<group>"; };
DA24EBBF19DAD4D000FF010B /* icon.sketch */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = icon.sketch; sourceTree = "<group>"; }; DA24EBBF19DAD4D000FF010B /* icon.sketch */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = icon.sketch; sourceTree = "<group>"; };
DA24EBC119DAD4D000FF010B /* 32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 32.png; sourceTree = "<group>"; }; DA24EBC119DAD4D000FF010B /* 32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 32.png; sourceTree = "<group>"; };
DA24EBC219DAD4D000FF010B /* 320-480.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "320-480.png"; sourceTree = "<group>"; }; DA24EBC219DAD4D000FF010B /* 320-480.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "320-480.png"; sourceTree = "<group>"; };
@@ -597,8 +595,6 @@
DA24EBC819DAD4D000FF010B /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = "<group>"; }; DA24EBC819DAD4D000FF010B /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = "<group>"; };
DA24EBC919DAD4D000FF010B /* background@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@3x.png"; sourceTree = "<group>"; }; DA24EBC919DAD4D000FF010B /* background@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@3x.png"; sourceTree = "<group>"; };
DA24EBCA19DAD4D000FF010B /* launch.sketch */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = launch.sketch; sourceTree = "<group>"; }; DA24EBCA19DAD4D000FF010B /* launch.sketch */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = launch.sketch; sourceTree = "<group>"; };
DA24EBE619DAD6DE00FF010B /* Icon-320.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-320.png"; sourceTree = "<group>"; };
DA24EBE719DAD6DE00FF010B /* Icon-64.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-64.png"; sourceTree = "<group>"; };
DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+PearlReloadItems.m"; sourceTree = "<group>"; }; DA250A13195665A100AC23F1 /* UITableView+PearlReloadItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+PearlReloadItems.m"; sourceTree = "<group>"; };
DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+PearlReloadItems.h"; sourceTree = "<group>"; }; DA250A14195665A100AC23F1 /* UITableView+PearlReloadItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+PearlReloadItems.h"; sourceTree = "<group>"; };
DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionReusableView+PearlDequeue.m"; sourceTree = "<group>"; }; DA250A15195665A100AC23F1 /* UICollectionReusableView+PearlDequeue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionReusableView+PearlDequeue.m"; sourceTree = "<group>"; };
@@ -653,6 +649,21 @@
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
DA5BFA4E147E415C00F98B1E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; DA5BFA4E147E415C00F98B1E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
DA5E0E4624589C9A0007FBA7 /* Icon-Small@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@3x.png"; sourceTree = "<group>"; };
DA5E0E4724589C9A0007FBA7 /* Icon-Small-40.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40.png"; sourceTree = "<group>"; };
DA5E0E4824589C9A0007FBA7 /* Icon-Small-20.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-20.png"; sourceTree = "<group>"; };
DA5E0E4924589C9A0007FBA7 /* Icon-76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-76.png"; sourceTree = "<group>"; };
DA5E0E4A24589C9A0007FBA7 /* Icon-Small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small@2x.png"; sourceTree = "<group>"; };
DA5E0E4B24589C9A0007FBA7 /* Icon-Small-40@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40@2x.png"; sourceTree = "<group>"; };
DA5E0E4C24589C9A0007FBA7 /* Icon-76@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-76@2x.png"; sourceTree = "<group>"; };
DA5E0E4D24589C9A0007FBA7 /* Icon-Small-20@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-20@3x.png"; sourceTree = "<group>"; };
DA5E0E4E24589C9A0007FBA7 /* Icon-Small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small.png"; sourceTree = "<group>"; };
DA5E0E4F24589C9A0007FBA7 /* Icon-83@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-83@2x.png"; sourceTree = "<group>"; };
DA5E0E5024589C9A0007FBA7 /* Icon-Small-40@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-40@3x.png"; sourceTree = "<group>"; };
DA5E0E5124589C9A0007FBA7 /* Icon-60@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@3x.png"; sourceTree = "<group>"; };
DA5E0E5224589C9B0007FBA7 /* iTunesArtwork@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iTunesArtwork@2x.png"; sourceTree = "<group>"; };
DA5E0E5324589C9B0007FBA7 /* Icon-Small-20@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-Small-20@2x.png"; sourceTree = "<group>"; };
DA5E0E5424589C9B0007FBA7 /* Icon-60@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-60@2x.png"; sourceTree = "<group>"; };
DA5E5C3C1723681B003798D8 /* Square-bottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Square-bottom.png"; path = "Dividers/Square-bottom.png"; sourceTree = "<group>"; }; DA5E5C3C1723681B003798D8 /* Square-bottom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Square-bottom.png"; path = "Dividers/Square-bottom.png"; sourceTree = "<group>"; };
DA6701B716406A4100B61001 /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; }; DA6701B716406A4100B61001 /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; };
DA6701DD16406B7300B61001 /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; }; DA6701DD16406B7300B61001 /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; };
@@ -662,6 +673,7 @@
DA67460B18DE7F0C00DFE240 /* Exo2.0-ExtraBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-ExtraBold.otf"; sourceTree = "<group>"; }; DA67460B18DE7F0C00DFE240 /* Exo2.0-ExtraBold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-ExtraBold.otf"; sourceTree = "<group>"; };
DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Bold.otf"; sourceTree = "<group>"; }; DA67460C18DE7F0C00DFE240 /* Exo2.0-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Exo2.0-Bold.otf"; sourceTree = "<group>"; };
DA70EC7F1811B13C00F65DB2 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; DA70EC7F1811B13C00F65DB2 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
DA72E22F2453B91700676D4F /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
DA771FE41E6E1595004D7EDE /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; }; DA771FE41E6E1595004D7EDE /* MasterPassword-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MasterPassword-Prefix.pch"; sourceTree = "<group>"; };
DA854C8118D4CFBF00106317 /* avatar-add@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add@2x.png"; sourceTree = "<group>"; }; DA854C8118D4CFBF00106317 /* avatar-add@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add@2x.png"; sourceTree = "<group>"; };
DA854C8218D4CFBF00106317 /* avatar-add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add.png"; sourceTree = "<group>"; }; DA854C8218D4CFBF00106317 /* avatar-add.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-add.png"; sourceTree = "<group>"; };
@@ -1597,6 +1609,7 @@
DAE2725A19C93B8E007C5262 /* StoreKit.framework in Frameworks */, DAE2725A19C93B8E007C5262 /* StoreKit.framework in Frameworks */,
DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */, DA6701E016406BB400B61001 /* AdSupport.framework in Frameworks */,
DA6701DE16406B7300B61001 /* Social.framework in Frameworks */, DA6701DE16406B7300B61001 /* Social.framework in Frameworks */,
DA72E2302453B91700676D4F /* WebKit.framework in Frameworks */,
DA6701B816406A4100B61001 /* Accounts.framework in Frameworks */, DA6701B816406A4100B61001 /* Accounts.framework in Frameworks */,
DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */, DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */,
DA672D3014F9413D004A189C /* libPearl.a in Frameworks */, DA672D3014F9413D004A189C /* libPearl.a in Frameworks */,
@@ -1685,21 +1698,21 @@
DA24EBB119DAD4D000FF010B /* icon */ = { DA24EBB119DAD4D000FF010B /* icon */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DA24EBB219DAD4D000FF010B /* Icon-60.png */, DA5E0E5424589C9B0007FBA7 /* Icon-60@2x.png */,
DA24EBB319DAD4D000FF010B /* Icon-60@2x.png */, DA5E0E5124589C9A0007FBA7 /* Icon-60@3x.png */,
DA24EBB419DAD4D000FF010B /* Icon-60@3x.png */, DA5E0E4924589C9A0007FBA7 /* Icon-76.png */,
DA24EBE719DAD6DE00FF010B /* Icon-64.png */, DA5E0E4C24589C9A0007FBA7 /* Icon-76@2x.png */,
DA24EBB519DAD4D000FF010B /* Icon-76.png */, DA5E0E4F24589C9A0007FBA7 /* Icon-83@2x.png */,
DA24EBB619DAD4D000FF010B /* Icon-76@2x.png */, DA5E0E4824589C9A0007FBA7 /* Icon-Small-20.png */,
DA24EBE619DAD6DE00FF010B /* Icon-320.png */, DA5E0E5324589C9B0007FBA7 /* Icon-Small-20@2x.png */,
DA24EBB719DAD4D000FF010B /* Icon-Small-40.png */, DA5E0E4D24589C9A0007FBA7 /* Icon-Small-20@3x.png */,
DA24EBB819DAD4D000FF010B /* Icon-Small-40@2x.png */, DA5E0E4724589C9A0007FBA7 /* Icon-Small-40.png */,
DA24EBB919DAD4D000FF010B /* Icon-Small-40@3x.png */, DA5E0E4B24589C9A0007FBA7 /* Icon-Small-40@2x.png */,
DA24EBBA19DAD4D000FF010B /* Icon-Small.png */, DA5E0E5024589C9A0007FBA7 /* Icon-Small-40@3x.png */,
DA24EBBB19DAD4D000FF010B /* Icon-Small@2x.png */, DA5E0E4E24589C9A0007FBA7 /* Icon-Small.png */,
DA24EBBC19DAD4D000FF010B /* Icon-Small@3x.png */, DA5E0E4A24589C9A0007FBA7 /* Icon-Small@2x.png */,
DA24EBBD19DAD4D000FF010B /* iTunesArtwork.png */, DA5E0E4624589C9A0007FBA7 /* Icon-Small@3x.png */,
DA24EBBE19DAD4D000FF010B /* iTunesArtwork@2x.png */, DA5E0E5224589C9B0007FBA7 /* iTunesArtwork@2x.png */,
); );
path = icon; path = icon;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1775,6 +1788,7 @@
DA5BFA47147E415C00F98B1E /* Frameworks */ = { DA5BFA47147E415C00F98B1E /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DA72E22F2453B91700676D4F /* WebKit.framework */,
DAFC1F6F2439795000D1CD66 /* CoreServices.framework */, DAFC1F6F2439795000D1CD66 /* CoreServices.framework */,
DAB7AE5C1F3D752900C856B1 /* libjson-c.a */, DAB7AE5C1F3D752900C856B1 /* libjson-c.a */,
DA6701B716406A4100B61001 /* Accounts.framework */, DA6701B716406A4100B61001 /* Accounts.framework */,
@@ -3286,6 +3300,7 @@
DA69540617D975D900BF294E /* icon_gears.png in Resources */, DA69540617D975D900BF294E /* icon_gears.png in Resources */,
DA67460D18DE7F0C00DFE240 /* Exo2.0-Thin.otf in Resources */, DA67460D18DE7F0C00DFE240 /* Exo2.0-Thin.otf in Resources */,
DA4522451902355C008F650A /* icon_book@2x.png in Resources */, DA4522451902355C008F650A /* icon_book@2x.png in Resources */,
DA5E0E5F24589C9B0007FBA7 /* Icon-Small-40@3x.png in Resources */,
DA32D04919D2F417004F3F0E /* thumb_fuel@2x.png in Resources */, DA32D04919D2F417004F3F0E /* thumb_fuel@2x.png in Resources */,
DAFC1F73243989FB00D1CD66 /* Launch Screen.storyboard in Resources */, DAFC1F73243989FB00D1CD66 /* Launch Screen.storyboard in Resources */,
DABD39371711E29700CF925C /* avatar-0.png in Resources */, DABD39371711E29700CF925C /* avatar-0.png in Resources */,
@@ -3305,11 +3320,9 @@
DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */, DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */,
DABD39401711E29700CF925C /* avatar-13.png in Resources */, DABD39401711E29700CF925C /* avatar-13.png in Resources */,
DA32D07C19D7D784004F3F0E /* background.png in Resources */, DA32D07C19D7D784004F3F0E /* background.png in Resources */,
DA24EBE919DAD6DE00FF010B /* Icon-64.png in Resources */,
DABD39411711E29700CF925C /* avatar-13@2x.png in Resources */, DABD39411711E29700CF925C /* avatar-13@2x.png in Resources */,
DABD39421711E29700CF925C /* avatar-14.png in Resources */, DABD39421711E29700CF925C /* avatar-14.png in Resources */,
DABD39431711E29700CF925C /* avatar-14@2x.png in Resources */, DABD39431711E29700CF925C /* avatar-14@2x.png in Resources */,
DA24EBE819DAD6DE00FF010B /* Icon-320.png in Resources */,
DAA1764419D8B82B0044227B /* personal_pw.png in Resources */, DAA1764419D8B82B0044227B /* personal_pw.png in Resources */,
DABD39441711E29700CF925C /* avatar-15.png in Resources */, DABD39441711E29700CF925C /* avatar-15.png in Resources */,
DABD39451711E29700CF925C /* avatar-15@2x.png in Resources */, DABD39451711E29700CF925C /* avatar-15@2x.png in Resources */,
@@ -3363,11 +3376,14 @@
DA32D00919CF5C55004F3F0E /* icon_question.png in Resources */, DA32D00919CF5C55004F3F0E /* icon_question.png in Resources */,
DABD39561711E29700CF925C /* avatar-6@2x.png in Resources */, DABD39561711E29700CF925C /* avatar-6@2x.png in Resources */,
DA32D07B19D7D784004F3F0E /* background@2x.png in Resources */, DA32D07B19D7D784004F3F0E /* background@2x.png in Resources */,
DA5E0E6224589C9B0007FBA7 /* Icon-Small-20@2x.png in Resources */,
DABD39571711E29700CF925C /* avatar-7.png in Resources */, DABD39571711E29700CF925C /* avatar-7.png in Resources */,
DABD39581711E29700CF925C /* avatar-7@2x.png in Resources */, DABD39581711E29700CF925C /* avatar-7@2x.png in Resources */,
DA5E0E5C24589C9B0007FBA7 /* Icon-Small-20@3x.png in Resources */,
DABD39591711E29700CF925C /* avatar-8.png in Resources */, DABD39591711E29700CF925C /* avatar-8.png in Resources */,
DA32D00A19CF5C55004F3F0E /* icon_question@2x.png in Resources */, DA32D00A19CF5C55004F3F0E /* icon_question@2x.png in Resources */,
DAA1764019D8B82B0044227B /* site_new.png in Resources */, DAA1764019D8B82B0044227B /* site_new.png in Resources */,
DA5E0E5924589C9B0007FBA7 /* Icon-Small@2x.png in Resources */,
DABD395A1711E29700CF925C /* avatar-8@2x.png in Resources */, DABD395A1711E29700CF925C /* avatar-8@2x.png in Resources */,
DABD395B1711E29700CF925C /* avatar-9.png in Resources */, DABD395B1711E29700CF925C /* avatar-9.png in Resources */,
DAA1765419D8B82B0044227B /* choose_type.png in Resources */, DAA1765419D8B82B0044227B /* choose_type.png in Resources */,
@@ -3377,23 +3393,30 @@
DA945C8717E3F3FD0053236B /* Images.xcassets in Resources */, DA945C8717E3F3FD0053236B /* Images.xcassets in Resources */,
DA32D04E19D2F59B004F3F0E /* meter_fuel@3x.png in Resources */, DA32D04E19D2F59B004F3F0E /* meter_fuel@3x.png in Resources */,
DA25C5FE197DBF200046CDCF /* icon_thumbs-up.png in Resources */, DA25C5FE197DBF200046CDCF /* icon_thumbs-up.png in Resources */,
DA5E0E5624589C9B0007FBA7 /* Icon-Small-40.png in Resources */,
DABD39871711E29700CF925C /* SourceCodePro-Black.otf in Resources */, DABD39871711E29700CF925C /* SourceCodePro-Black.otf in Resources */,
DABD39881711E29700CF925C /* SourceCodePro-ExtraLight.otf in Resources */, DABD39881711E29700CF925C /* SourceCodePro-ExtraLight.otf in Resources */,
DABD39A01711E29700CF925C /* icon_action.png in Resources */, DABD39A01711E29700CF925C /* icon_action.png in Resources */,
DA5E0E5524589C9B0007FBA7 /* Icon-Small@3x.png in Resources */,
DABD39A11711E29700CF925C /* icon_action@2x.png in Resources */, DABD39A11711E29700CF925C /* icon_action@2x.png in Resources */,
DABD39F21711E29700CF925C /* icon_cancel.png in Resources */, DABD39F21711E29700CF925C /* icon_cancel.png in Resources */,
DA25C5FB197CCAE00046CDCF /* icon_delete@2x.png in Resources */, DA25C5FB197CCAE00046CDCF /* icon_delete@2x.png in Resources */,
DA5E0E5724589C9B0007FBA7 /* Icon-Small-20.png in Resources */,
DA29993219C9132F00AF7DF1 /* thumb_generated_login@3x.png in Resources */, DA29993219C9132F00AF7DF1 /* thumb_generated_login@3x.png in Resources */,
DA29992F19C86F5700AF7DF1 /* thumb_generated_login@2x.png in Resources */, DA29992F19C86F5700AF7DF1 /* thumb_generated_login@2x.png in Resources */,
DA73049F194E022B00E72520 /* ui_textfield.png in Resources */, DA73049F194E022B00E72520 /* ui_textfield.png in Resources */,
DABD39F31711E29700CF925C /* icon_cancel@2x.png in Resources */, DABD39F31711E29700CF925C /* icon_cancel@2x.png in Resources */,
DA5E0E5B24589C9B0007FBA7 /* Icon-76@2x.png in Resources */,
DABD3A261711E29700CF925C /* icon_edit.png in Resources */, DABD3A261711E29700CF925C /* icon_edit.png in Resources */,
DABD3A271711E29700CF925C /* icon_edit@2x.png in Resources */, DABD3A271711E29700CF925C /* icon_edit@2x.png in Resources */,
DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */, DA24EBAF19DAD08C00FF010B /* tip_basic_black_top@2x.png in Resources */,
DABD3A3A1711E29700CF925C /* icon_find.png in Resources */, DABD3A3A1711E29700CF925C /* icon_find.png in Resources */,
DA5E0E6324589C9B0007FBA7 /* Icon-60@2x.png in Resources */,
DABD3A3B1711E29700CF925C /* icon_find@2x.png in Resources */, DABD3A3B1711E29700CF925C /* icon_find@2x.png in Resources */,
DAA1765319D8B82B0044227B /* choose_type@2x.png in Resources */, DAA1765319D8B82B0044227B /* choose_type@2x.png in Resources */,
DA5E0E6124589C9B0007FBA7 /* iTunesArtwork@2x.png in Resources */,
DABD3AA01711E29800CF925C /* icon_pause.png in Resources */, DABD3AA01711E29800CF925C /* icon_pause.png in Resources */,
DA5E0E5A24589C9B0007FBA7 /* Icon-Small-40@2x.png in Resources */,
DABD3AA11711E29800CF925C /* icon_pause@2x.png in Resources */, DABD3AA11711E29800CF925C /* icon_pause@2x.png in Resources */,
DAA1764219D8B82B0044227B /* settings.png in Resources */, DAA1764219D8B82B0044227B /* settings.png in Resources */,
DABD3AAA1711E29800CF925C /* icon_person.png in Resources */, DABD3AAA1711E29800CF925C /* icon_person.png in Resources */,
@@ -3418,7 +3441,6 @@
DABD3B951711E29800CF925C /* pull-down.png in Resources */, DABD3B951711E29800CF925C /* pull-down.png in Resources */,
DABD3B961711E29800CF925C /* pull-down@2x.png in Resources */, DABD3B961711E29800CF925C /* pull-down@2x.png in Resources */,
DABD3B971711E29800CF925C /* pull-up.png in Resources */, DABD3B971711E29800CF925C /* pull-up.png in Resources */,
DA24EBEA19DAD6EE00FF010B /* Icon-Small.png in Resources */,
DA8495321A93049300B3053D /* icon_down@2x.png in Resources */, DA8495321A93049300B3053D /* icon_down@2x.png in Resources */,
DABD3B981711E29800CF925C /* pull-up@2x.png in Resources */, DABD3B981711E29800CF925C /* pull-up@2x.png in Resources */,
DA7304A0194E022B00E72520 /* ui_textfield@2x.png in Resources */, DA7304A0194E022B00E72520 /* ui_textfield@2x.png in Resources */,
@@ -3427,8 +3449,8 @@
DA452249190628A1008F650A /* icon_wrench.png in Resources */, DA452249190628A1008F650A /* icon_wrench.png in Resources */,
DAA1764519D8B82B0044227B /* name_new@2x.png in Resources */, DAA1764519D8B82B0044227B /* name_new@2x.png in Resources */,
DA45224819062899008F650A /* icon_settings@2x.png in Resources */, DA45224819062899008F650A /* icon_settings@2x.png in Resources */,
DA5E0E5E24589C9B0007FBA7 /* Icon-83@2x.png in Resources */,
DA854C8418D4CFBF00106317 /* avatar-add.png in Resources */, DA854C8418D4CFBF00106317 /* avatar-add.png in Resources */,
DA24EBEB19DAD6EE00FF010B /* Icon-Small@2x.png in Resources */,
DAA1764B19D8B82B0044227B /* login_name@2x.png in Resources */, DAA1764B19D8B82B0044227B /* login_name@2x.png in Resources */,
DABD3C241711E2DC00CF925C /* MasterPassword.entitlements in Resources */, DABD3C241711E2DC00CF925C /* MasterPassword.entitlements in Resources */,
DABD3C251711E2DC00CF925C /* Settings.bundle in Resources */, DABD3C251711E2DC00CF925C /* Settings.bundle in Resources */,
@@ -3444,16 +3466,18 @@
DAA1764619D8B82B0044227B /* name_new.png in Resources */, DAA1764619D8B82B0044227B /* name_new.png in Resources */,
DA45224B190628B2008F650A /* icon_gear.png in Resources */, DA45224B190628B2008F650A /* icon_gear.png in Resources */,
DAAA1D4123CD145000F3DF56 /* Storyboard.storyboard in Resources */, DAAA1D4123CD145000F3DF56 /* Storyboard.storyboard in Resources */,
DA5E0E6024589C9B0007FBA7 /* Icon-60@3x.png in Resources */,
DA8495311A93049300B3053D /* icon_down.png in Resources */, DA8495311A93049300B3053D /* icon_down.png in Resources */,
DA5E0E5D24589C9B0007FBA7 /* Icon-Small.png in Resources */,
DA25C5FF197DBF200046CDCF /* icon_thumbs-up@2x.png in Resources */, DA25C5FF197DBF200046CDCF /* icon_thumbs-up@2x.png in Resources */,
DAE1EF2217E942DE00BC0086 /* Localizable.strings in Resources */, DAE1EF2217E942DE00BC0086 /* Localizable.strings in Resources */,
DA5A09DF171A70E4005284AB /* play.png in Resources */, DA5A09DF171A70E4005284AB /* play.png in Resources */,
DA24EBEC19DAD6EE00FF010B /* Icon-Small@3x.png in Resources */,
DA5A09E0171A70E4005284AB /* play@2x.png in Resources */, DA5A09E0171A70E4005284AB /* play@2x.png in Resources */,
DA5A09EA171BB0F7005284AB /* unlocked.png in Resources */, DA5A09EA171BB0F7005284AB /* unlocked.png in Resources */,
DAA1762819D89B610044227B /* thumb_ios_integration.png in Resources */, DAA1762819D89B610044227B /* thumb_ios_integration.png in Resources */,
DA5A09EB171BB0F7005284AB /* unlocked@2x.png in Resources */, DA5A09EB171BB0F7005284AB /* unlocked@2x.png in Resources */,
DAA1764F19D8B82B0044227B /* counter@2x.png in Resources */, DAA1764F19D8B82B0044227B /* counter@2x.png in Resources */,
DA5E0E5824589C9B0007FBA7 /* Icon-76.png in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -3865,7 +3889,6 @@
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
STRIP_INSTALLED_PRODUCT = NO; STRIP_INSTALLED_PRODUCT = NO;
STRIP_SWIFT_SYMBOLS = NO; STRIP_SWIFT_SYMBOLS = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
WARNING_CFLAGS = "-Wno-float-conversion"; WARNING_CFLAGS = "-Wno-float-conversion";
}; };
@@ -3994,10 +4017,6 @@
"\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"", "\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"",
); );
INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist"; INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"\"$(PROJECT_DIR)/../lib/libsodium/build-ios~/out/lib\"", "\"$(PROJECT_DIR)/../lib/libsodium/build-ios~/out/lib\"",
@@ -4005,7 +4024,7 @@
); );
OTHER_CFLAGS = ( OTHER_CFLAGS = (
"-DMPW_SODIUM=1", "-DMPW_SODIUM=1",
"-DMPW_CPERCIVA=0", "-DMPW_JSON=1",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword; PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
PRODUCT_NAME = MasterPassword; PRODUCT_NAME = MasterPassword;
@@ -4013,9 +4032,6 @@
SKIP_INSTALL = NO; SKIP_INSTALL = NO;
STRIP_INSTALLED_PRODUCT = YES; STRIP_INSTALLED_PRODUCT = YES;
STRIP_SWIFT_SYMBOLS = YES; STRIP_SWIFT_SYMBOLS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Source/iOS/MasterPassword-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
}; };
name = Debug; name = Debug;
}; };
@@ -4028,7 +4044,6 @@
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = NO; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = NO;
CODE_SIGN_ENTITLEMENTS = Source/iOS/MasterPassword.entitlements; CODE_SIGN_ENTITLEMENTS = Source/iOS/MasterPassword.entitlements;
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
EXCLUDED_SOURCE_FILE_NAMES = libDCIntrospect.a;
GCC_C_LANGUAGE_STANDARD = c11; GCC_C_LANGUAGE_STANDARD = c11;
GCC_PREFIX_HEADER = "Source/MasterPassword-Prefix.pch"; GCC_PREFIX_HEADER = "Source/MasterPassword-Prefix.pch";
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
@@ -4038,10 +4053,6 @@
"\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"", "\"$(PROJECT_DIR)/../lib/libjson-c/build-ios~/out/include\"",
); );
INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist"; INFOPLIST_FILE = "Source/iOS/MasterPassword-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"\"$(PROJECT_DIR)/../lib/libsodium/build-ios~/out/lib\"", "\"$(PROJECT_DIR)/../lib/libsodium/build-ios~/out/lib\"",
@@ -4049,7 +4060,7 @@
); );
OTHER_CFLAGS = ( OTHER_CFLAGS = (
"-DMPW_SODIUM=1", "-DMPW_SODIUM=1",
"-DMPW_CPERCIVA=0", "-DMPW_JSON=1",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword; PRODUCT_BUNDLE_IDENTIFIER = com.lyndir.lhunath.MasterPassword;
PRODUCT_NAME = MasterPassword; PRODUCT_NAME = MasterPassword;
@@ -4057,10 +4068,6 @@
SKIP_INSTALL = NO; SKIP_INSTALL = NO;
STRIP_INSTALLED_PRODUCT = YES; STRIP_INSTALLED_PRODUCT = YES;
STRIP_SWIFT_SYMBOLS = YES; STRIP_SWIFT_SYMBOLS = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OBJC_BRIDGING_HEADER = "Source/iOS/MasterPassword-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 4.0;
}; };
name = Release; name = Release;
}; };

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 KiB

After

Width:  |  Height:  |  Size: 879 KiB

View File

@@ -34,7 +34,7 @@ icons=(
# 57@1@iphone@:Icon.png # 57@1@iphone@:Icon.png
# 29@1@iphone@:Icon-Small.png # 29@1@iphone@:Icon-Small.png
# iPad # iPad
# 76@1@ipad@7.0:Icon-76.png 76@1@ipad@7.0:Icon-76.png
152@2@ipad@7.0:Icon-76@2x.png 152@2@ipad@7.0:Icon-76@2x.png
167@2@ipad@9.0:Icon-83@2x.png 167@2@ipad@9.0:Icon-83@2x.png
20@1@ipad@7.0:Icon-Small-20.png 20@1@ipad@7.0:Icon-Small-20.png

View File

@@ -39,8 +39,9 @@
askImportPassword:(NSString *( ^ )(NSString *userName))importPassword askImportPassword:(NSString *( ^ )(NSString *userName))importPassword
askUserPassword:(NSString *( ^ )(NSString *userName))userPassword askUserPassword:(NSString *( ^ )(NSString *userName))userPassword
result:(void ( ^ )(NSError *error))resultBlock; result:(void ( ^ )(NSError *error))resultBlock;
- (void)exportSitesRevealPasswords:(BOOL)revealPasswords - (NSString *)exportSitesFor:(MPUserEntity *)user
askExportPassword:(NSString *( ^ )(NSString *userName))askImportPassword revealPasswords:(BOOL)revealPasswords
result:(void ( ^ )(NSString *exportedUser, NSError *error))resultBlock; askExportPassword:(NSString *( ^ )(NSString *userName))askExportPassword
error:(__autoreleasing NSError **)error;
@end @end

View File

@@ -704,16 +704,17 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
site.lastUsed = [NSDate dateWithTimeIntervalSince1970:importSite->lastUsed]; site.lastUsed = [NSDate dateWithTimeIntervalSince1970:importSite->lastUsed];
} }
- (void)exportSitesRevealPasswords:(BOOL)revealPasswords - (NSString *)exportSitesFor:(MPUserEntity *)user
askExportPassword:(NSString *( ^ )(NSString *userName))askImportPassword revealPasswords:(BOOL)revealPasswords
result:(void ( ^ )(NSString *exportedUser, NSError *error))resultBlock { askExportPassword:(NSString *( ^ )(NSString *userName))askExportPassword
error:(__autoreleasing NSError **)error {
[MPAppDelegate_Shared managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
MPUserEntity *user = [self activeUserInContext:context];
MPMarshalledUser *exportUser = NULL;
MPMarshalledFile *exportFile = NULL;
@try {
inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", user.userID ); inf( @"Exporting sites, %@, for user: %@", revealPasswords? @"revealing passwords": @"omitting passwords", user.userID );
MPMarshalledUser *exportUser = mpw_marshal_user( user.name.UTF8String, exportUser = mpw_marshal_user( user.name.UTF8String,
mpw_masterKeyProvider_str( askImportPassword( user.name ).UTF8String ), user.algorithm.version ); mpw_masterKeyProvider_str( askExportPassword( user.name ).UTF8String ), user.algorithm.version );
exportUser->redacted = !revealPasswords; exportUser->redacted = !revealPasswords;
exportUser->avatar = (unsigned int)user.avatar; exportUser->avatar = (unsigned int)user.avatar;
exportUser->keyID = mpw_strdup( [user.keyID encodeHex].UTF8String ); exportUser->keyID = mpw_strdup( [user.keyID encodeHex].UTF8String );
@@ -737,22 +738,26 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
mpw_marshal_question( exportSite, siteQuestion.keyword.UTF8String ); mpw_marshal_question( exportSite, siteQuestion.keyword.UTF8String );
} }
MPMarshalledFile *exportFile = NULL;
const char *export = mpw_marshal_write( MPMarshalFormatDefault, &exportFile, exportUser ); const char *export = mpw_marshal_write( MPMarshalFormatDefault, &exportFile, exportUser );
NSString *exportedUser = nil; NSString *exportedUser = nil;
if (export && exportFile && exportFile->error.type == MPMarshalSuccess) if (export && exportFile && exportFile->error.type == MPMarshalSuccess)
exportedUser = [NSString stringWithCString:export encoding:NSUTF8StringEncoding]; exportedUser = [NSString stringWithCString:export encoding:NSUTF8StringEncoding];
mpw_free_string( &export ); mpw_free_string( &export );
resultBlock( exportedUser, exportFile && exportFile->error.type == MPMarshalSuccess? nil: if (error)
[NSError errorWithDomain:MPErrorDomain code:MPErrorMarshalCode userInfo:@{ *error = exportFile && exportFile->error.type == MPMarshalSuccess? nil:
@"type" : @(exportFile? exportFile->error.type: MPMarshalErrorInternal), [NSError errorWithDomain:MPErrorDomain code:MPErrorMarshalCode userInfo:@{
NSLocalizedDescriptionKey: @(exportFile? exportFile->error.message: nil), @"type" : @(exportFile? exportFile->error.type: MPMarshalErrorInternal),
}] ); NSLocalizedDescriptionKey: @(exportFile? exportFile->error.message: nil),
}];
return exportedUser;
}
@finally {
mpw_marshal_file_free( &exportFile ); mpw_marshal_file_free( &exportFile );
mpw_marshal_user_free( &exportUser ); mpw_marshal_user_free( &exportUser );
mpw_masterKeyProvider_free(); mpw_masterKeyProvider_free();
}]; }
} }
@end @end

View File

@@ -20,11 +20,19 @@
#import "base64.h" #import "base64.h"
// printf <secret> | openssl enc -[ed] -aes-128-cbc -a -A -K <appSecret> -iv 0 // printf <secret> | openssl enc -[ed] -aes-128-cbc -a -A -K <appSecret> -iv 0
NSString *appSecret = @""; #if TARGET_OS_IOS
NSString *appSalt = @""; NSString *appSecret = @"946a6b12e6e6e004cc35bad1ea11478c";
NSString *sentryDSN = @""; NSString *appSalt = @"uBcsbZeTB8TfSS7dDw4yUq6wMZD/2nREvR0mqzqsNXvv9guh+62hkt99ly6QcJ5n";
NSString *countlyKey = @""; NSString *sentryDSN = @"tmVjdMN9DpZ+0EIrrvHi44hWfaBkwrlrxjBkdeau2rDk+zlvgSdAZkAvNj7m1V+5NUR7i8Y/NumNKOaYlWJvPynEMJ4ZBvPepSbivgVvmr8=";
NSString *countlySalt = @""; NSString *countlyKey = @"mDnMZyxwoq4ENgYnGYTzW8wsyiJQlmNKxkRLj88/nrs0mzE+zVjs6Y5LAT3+AYBB";
NSString *countlySalt = @"2COFsZd+4FNAU6jvI/HUu297mkZALzRIyKv5mD3vs55BHXDowh62A7FursCYS+cG";
#elif TARGET_OS_MAC
NSString *appSecret = @"24fcbadccb5789b2a969c0c811f86702";
NSString *appSalt = @"0N1fzSanIOCb7OQ4hEshXSjwEPXAXMhPBKQJeEcYPor8FWz76IpdB8ZHa3Wyb7o9";
NSString *sentryDSN = @"2RbeS9wfzQEOKB9MG3EWLDe+N8iXYNtWc8tovMcBmhuMIeyAHYKqo5eclSEYyM6lA73Y7FFHqUyTLbEmOR6MAU2PtWAitLdxOZlq3VnbXjI=";
NSString *countlyKey = @"uiasXoQNtkPQHvpvNqEE5N/tw/F1Hnzm+4ViSJ38EMeoWGvDQPJ+Kt9zPhb8Qans";
NSString *countlySalt = @"/raQUNxKQdxXRR5VFmCDJdyyJE8f6SPrTO5Y4z0kJH+wCrjaZ1VvCq+JSmOsBkz2";
#endif
NSString *decrypt(NSString *secret) { NSString *decrypt(NSString *secret) {

View File

@@ -18,6 +18,7 @@
#import "MPNavigationController.h" #import "MPNavigationController.h"
#import "MPWebViewController.h" #import "MPWebViewController.h"
#import "MPiOSAppDelegate.h"
@implementation MPNavigationController @implementation MPNavigationController
@@ -29,6 +30,16 @@
[self performSegueWithIdentifier:@"setup" sender:self]; [self performSegueWithIdentifier:@"setup" sender:self];
} }
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if ([identifier isEqualToString:@"web"] && [[(NSURL *)sender scheme] isEqualToString:@"masterpassword"]) {
[[MPiOSAppDelegate get] openURL:sender];
return;
}
[super performSegueWithIdentifier:identifier sender:sender];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"web"]) if ([segue.identifier isEqualToString:@"web"])

View File

@@ -33,9 +33,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
MPPasswordsBadNameTip = 1 << 0, MPPasswordsBadNameTip = 1 << 0,
}; };
@interface MPSitesViewController()<NSFetchedResultsControllerDelegate, SKStoreProductViewControllerDelegate> @interface MPSitesViewController()<NSFetchedResultsControllerDelegate>
@property(nonatomic, strong) SKStoreProductViewController *voltoViewController;
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController; @property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property(nonatomic, strong) NSArray *fuzzyGroups; @property(nonatomic, strong) NSArray *fuzzyGroups;
@property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet; @property(nonatomic, strong) NSCharacterSet *siteNameAcceptableCharactersSet;
@@ -435,13 +434,6 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
} completion:completion]; } completion:completion];
} }
#pragma mark - SKStoreProductViewControllerDelegate
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[viewController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Actions #pragma mark - Actions
- (IBAction)dismissPopdown:(id)sender { - (IBAction)dismissPopdown:(id)sender {
@@ -454,45 +446,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
- (IBAction)upgradeVolto:(UIButton *)sender { - (IBAction)upgradeVolto:(UIButton *)sender {
if ([UIApp canOpenURL:[[NSURL alloc] initWithString:@"volto:"]]) { [[MPiOSAppDelegate get] migrateFor:[MPiOSAppDelegate get].activeUserForMainThread];
[[MPiOSAppDelegate get] exportSitesRevealPasswords:NO askExportPassword:^NSString *(NSString *userName) {
return PearlAwait( ^(void (^setResult)(id)) {
PearlMainQueue( ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName )
message:@"Enter your master password to export the user."
preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.secureTextEntry = YES;
}];
[alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:
^(UIAlertAction *action) { setResult( alert.textFields.firstObject.text ); }]];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:
^(UIAlertAction *action) { setResult( nil ); }]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
} );
} );
} result:^(NSString *exportedUser, NSError *error) {
if (!exportedUser || error) {
MPError( error, @"Failed to export user." );
PearlMainQueue( ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error"
message:[error localizedDescription]
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
} );
return;
}
NSURLComponents *components = [NSURLComponents new];
components.scheme = @"volto";
components.path = @"import";
components.queryItems = @[ [[NSURLQueryItem alloc] initWithName:@"data" value:exportedUser] ];
[UIApp openURL:components.URL];
}];
}
else if (self.voltoViewController)
[self presentViewController:self.voltoViewController animated:YES completion:nil];
} }
#pragma mark - Private #pragma mark - Private
@@ -505,23 +459,8 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
self.voltoMigrateAlert.visible = YES; self.voltoMigrateAlert.visible = YES;
} }
else { else {
self.voltoInstallAlert.visible = NO; self.voltoInstallAlert.visible = [MPiOSAppDelegate get].voltoViewController != nil;
self.voltoMigrateAlert.visible = NO; self.voltoMigrateAlert.visible = NO;
self.voltoViewController = [SKStoreProductViewController new];
self.voltoViewController.delegate = self;
[self.voltoViewController loadProductWithParameters:@{
SKStoreProductParameterCampaignToken : @"app-masterpassword.ios", /* Campaign: From MasterPassword iOS */
SKStoreProductParameterProviderToken : @153897, /* Provider: Maarten Billemont */
SKStoreProductParameterITunesItemIdentifier: @510296984, /* Application: MasterPassword iOS */
//SKStoreProductParameterITunesItemIdentifier: @1500430196, /* Application: Volto iOS */
} completionBlock:^(BOOL result, NSError *error) {
if (error)
err( @"Failed loading Volto product information: %@", error );
[UIView animateWithDuration:0.3f animations:^{
self.voltoInstallAlert.visible = result;
}];
}];
} }
} }

View File

@@ -17,10 +17,12 @@
//============================================================================== //==============================================================================
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@interface MPWebViewController : UIViewController<UIWebViewDelegate> @interface MPWebViewController : UIViewController<WKNavigationDelegate>
@property(nonatomic) IBOutlet UIWebView *webView; @property(nonatomic) IBOutlet WKWebView *webView;
@property(nonatomic) IBOutlet UINavigationBar *webNavigationBar;
@property(nonatomic) IBOutlet UINavigationItem *webNavigationItem; @property(nonatomic) IBOutlet UINavigationItem *webNavigationItem;
@property(nonatomic) NSURL *initialURL; @property(nonatomic) NSURL *initialURL;

View File

@@ -17,6 +17,7 @@
//============================================================================== //==============================================================================
#import "MPWebViewController.h" #import "MPWebViewController.h"
#import "MPiOSAppDelegate.h"
@implementation MPWebViewController @implementation MPWebViewController
@@ -24,20 +25,30 @@
[super viewDidLoad]; [super viewDidLoad];
[self.webView.scrollView insetOcclusion]; if (!self.initialURL)
self.initialURL = [NSURL URLWithString:@"https://masterpassword.app"];
self.webNavigationItem.title = self.initialURL.host;
// WKWebView can't be on the storyboard for iOS pre 11 due to an NSCoding bug.
[self.view insertSubview:self.webView = [WKWebView new] atIndex:0];
[self.webView setNavigationDelegate:self];
[self.webView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.webView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
[self.webView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
[self.webView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
[self.webView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:self.initialURL]];
} }
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated]; [super viewWillAppear:animated];
}
if (!self.initialURL) - (void)viewDidLayoutSubviews {
self.initialURL = [NSURL URLWithString:@"https://masterpassword.app"]; [self.webView.scrollView insetOcclusion];
[super viewDidLayoutSubviews];
self.webNavigationItem.title = self.initialURL.host;
self.webView.visible = NO;
[self.webView loadRequest:[[NSURLRequest alloc] initWithURL:self.initialURL]];
} }
- (UIStatusBarStyle)preferredStatusBarStyle { - (UIStatusBarStyle)preferredStatusBarStyle {
@@ -45,26 +56,24 @@
return UIStatusBarStyleLightContent; return UIStatusBarStyleLightContent;
} }
#pragma mark - UIWebViewDelegate #pragma mark - WKNavigationDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
navigationType:(UIWebViewNavigationType)navigationType { decisionHandler:(void ( ^ )(WKNavigationActionPolicy))decisionHandler {
if ([[request.URL absoluteString] rangeOfString:@"thanks.lhunath.com"].location != NSNotFound) { if ([navigationAction.request.mainDocumentURL.scheme isEqualToString:@"masterpassword"]) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tipped.thanks"]; [[MPiOSAppDelegate get] openURL:navigationAction.request.mainDocumentURL];
if (![[NSUserDefaults standardUserDefaults] synchronize]) decisionHandler( WKNavigationActionPolicyCancel );
wrn( @"Couldn't synchronize thanks tip." ); return;
} }
if ([request.URL isEqual:request.mainDocumentURL]) { decisionHandler( WKNavigationActionPolicyAllow );
self.webNavigationItem.title = request.URL.host;
self.webNavigationItem.prompt = strl( @"Loading" );
}
return YES;
} }
- (void)webViewDidStartLoad:(UIWebView *)webView { - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
self.webNavigationItem.title = webView.URL.host;
self.webNavigationItem.prompt = strl( @"Loading" );
UIActivityIndicatorView *activityView = UIActivityIndicatorView *activityView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
@@ -72,19 +81,56 @@
[activityView startAnimating]; [activityView startAnimating];
} }
- (void)webViewDidFinishLoad:(UIWebView *)webView { - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[UIView animateWithDuration:0.3 animations:^{ if ([[webView.URL absoluteString] rangeOfString:@"thanks.lhunath.com"].location != NSNotFound) {
self.webView.visible = YES; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"tipped.thanks"];
if (![[NSUserDefaults standardUserDefaults] synchronize])
wrn( @"Couldn't synchronize thanks tip." );
}
[self.webNavigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector( action: )]];
[webView evaluateJavaScript:@"document.title" completionHandler:^(id o, NSError *error) {
self.webNavigationItem.prompt = [o description];
}]; }];
[self.webNavigationItem setLeftBarButtonItem:[webView canGoBack]? [[UIBarButtonItem alloc]
initWithTitle:@"⬅︎" style:UIBarButtonItemStylePlain target:webView action:@selector( goBack )]: nil];
self.webNavigationItem.prompt = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
} }
#pragma mark - Actions #pragma mark - Actions
- (IBAction)action:(id)sender {
UIAlertController *controller = [UIAlertController new];
controller.title = self.webView.URL.host;
controller.message = self.webView.URL.absoluteString;
[controller addAction:[UIAlertAction actionWithTitle:@"Safari" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[UIApp openURL:self.webView.URL];
}]];
if ([UIApp canOpenURL:[NSURL URLWithString:@"firefox:"]]) {
[controller addAction:[UIAlertAction actionWithTitle:@"Firefox" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[UIApp openURL:[NSURL URLWithString:strf( @"firefox://open-url?url=%@",
[self.webView.URL.absoluteString stringByAddingPercentEncodingWithAllowedCharacters:
[NSCharacterSet URLQueryAllowedCharacterSet]] )]];
}]];
}
if ([UIApp canOpenURL:[NSURL URLWithString:@"googlechrome:"]]) {
NSURL *url = [[NSURL alloc] initWithScheme:[self.webView.URL.scheme isEqualToString:@"http"]? @"googlechrome": @"googlechromes"
host:self.webView.URL.host path:self.webView.URL.path];
[controller addAction:[UIAlertAction actionWithTitle:@"Chrome" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[UIApp openURL:url];
}]];
}
if ([UIApp canOpenURL:[NSURL URLWithString:@"opera-http:"]]) {
NSURL *url = [[NSURL alloc] initWithScheme:[self.webView.URL.scheme isEqualToString:@"http"]? @"opera-http": @"opera-https"
host:self.webView.URL.host path:self.webView.URL.path];
[controller addAction:[UIAlertAction actionWithTitle:@"Opera" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[UIApp openURL:url];
}]];
}
[controller addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:controller animated:YES completion:nil];
}
- (IBAction)done:(id)sender { - (IBAction)done:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil]; [self dismissViewControllerAnimated:YES completion:nil];

View File

@@ -17,15 +17,22 @@
//============================================================================== //==============================================================================
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>
#import "MPAppDelegate_Shared.h" #import "MPAppDelegate_Shared.h"
@interface MPiOSAppDelegate : MPAppDelegate_Shared @interface MPiOSAppDelegate : MPAppDelegate_Shared <SKStoreProductViewControllerDelegate>
@property(nonatomic, strong) SKStoreProductViewController *voltoViewController;
- (void)openURL:(NSURL *)url;
- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController; - (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController; - (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
- (void)showExportForVC:(UIViewController *)viewController; - (void)showExportForVC:(UIViewController *)viewController;
- (void)migrateFor:(MPUserEntity *)user;
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset; - (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset;
@end @end

View File

@@ -26,6 +26,20 @@
#import <Sentry/Sentry.h> #import <Sentry/Sentry.h>
#import <Countly/Countly.h> #import <Countly/Countly.h>
@interface CountlyPushNotifications
@end
@interface CountlyPushNotifications(MPNotifications)
@end
@implementation CountlyPushNotifications(MPNotifications)
- (void)openURL:(NSString *)URLString {
[[MPiOSAppDelegate get].navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:URLString]];
}
@end
@interface MPiOSAppDelegate()<UIDocumentInteractionControllerDelegate> @interface MPiOSAppDelegate()<UIDocumentInteractionControllerDelegate>
@property(nonatomic, strong) UIDocumentInteractionController *interactionController; @property(nonatomic, strong) UIDocumentInteractionController *interactionController;
@@ -172,7 +186,26 @@
} }
} ); } );
SKStoreProductViewController *migrateVC = [SKStoreProductViewController new];
[migrateVC loadProductWithParameters:@{
SKStoreProductParameterCampaignToken : @"app-masterpassword.ios", /* Campaign: From MasterPassword iOS */
SKStoreProductParameterProviderToken : @153897, /* Provider: Maarten Billemont */
SKStoreProductParameterITunesItemIdentifier: @510296984, /* Application: MasterPassword iOS */
//SKStoreProductParameterITunesItemIdentifier: @1500430196, /* Application: Volto iOS */
} completionBlock:^(BOOL result, NSError *error) {
if (error)
err( @"Failed loading Volto product information: %@", error );
if (result) {
self.voltoViewController = migrateVC;
self.voltoViewController.delegate = self;
} else {
self.voltoViewController = nil;
}
}];
PearlMainQueueOperation( ^{ PearlMainQueueOperation( ^{
[self.navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:@"masterpassword://foo?bar=quux"]];
if ([[MPiOSConfig get].showSetup boolValue]) if ([[MPiOSConfig get].showSetup boolValue])
[self.navigationController performSegueWithIdentifier:@"setup" sender:self]; [self.navigationController performSegueWithIdentifier:@"setup" sender:self];
@@ -193,6 +226,12 @@
if (!url) if (!url)
return NO; return NO;
// masterpassword: URLs.
if ([url.scheme isEqualToString:@"masterpassword"]) {
[self openURL:url];
return YES;
}
// Arbitrary URL to mpsites data. // Arbitrary URL to mpsites data.
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler: [[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:
^(NSData *importedSitesData, NSURLResponse *response, NSError *error) { ^(NSData *importedSitesData, NSURLResponse *response, NSError *error) {
@@ -242,18 +281,17 @@
return NO; return NO;
PearlMainQueue( ^{ PearlMainQueue( ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Welcome to Master Password!" message: UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Diagnostics" message:
@"We want this experience to be top-notch.\n\n" @"We look for bugs, sudden crashes, runtime issues & statistics.\n\n"
@"We look for bugs, runtime issues, crashes & usage counters.\n" @"Diagnostics are scrubbed and personal details will never leave your device."
@"Needless to say, diagnostics are always scrubbed and personal details will never leave your device."
preferredStyle:UIAlertControllerStyleAlert]; preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Disable" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { [alert addAction:[UIAlertAction actionWithTitle:@"Disable" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
[MPiOSConfig get].sendInfo = @(NO); [MPiOSConfig get].sendInfo = @(NO);
[MPiOSConfig get].sendInfoDecided = @(YES); [MPiOSConfig get].sendInfoDecided = @(YES);
[self consentFeatures]; [self consentFeatures];
}]]; }]];
[alert addAction:[UIAlertAction actionWithTitle:@"Thanks" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { [alert addAction:[UIAlertAction actionWithTitle:@"Engage" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[MPiOSConfig get].sendInfo = @(YES); [MPiOSConfig get].sendInfo = @(YES);
[MPiOSConfig get].sendInfoDecided = @(YES); [MPiOSConfig get].sendInfoDecided = @(YES);
[self consentFeatures]; [self consentFeatures];
@@ -290,7 +328,7 @@
PearlMainQueue( ^{ PearlMainQueue( ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Coming Soon" message: UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Coming Soon" message:
@"Master Password is rolling out a new modern personal security platform and we're excited to bring you along.\n\n" @"Master Password is rolling out a brand new, updated version and we're excited to bring you along.\n\n"
@"When it's time, we'll send you a notification to help you make an effortless transition." @"When it's time, we'll send you a notification to help you make an effortless transition."
preferredStyle:UIAlertControllerStyleAlert]; preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Thanks" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { [alert addAction:[UIAlertAction actionWithTitle:@"Thanks" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
@@ -430,6 +468,42 @@
#pragma mark - Behavior #pragma mark - Behavior
- (void)openURL:(NSURL *)url {
if ([url.scheme isEqualToString:@"masterpassword"]) {
if ([url.host isEqualToString:@"open-url"]) {
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
if ([item.name isEqualToString:@"url"]) {
[UIApp openURL:[NSURL URLWithString:item.value]];
return;
}
}
else if ([url.host isEqualToString:@"show-url"]) {
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
if ([item.name isEqualToString:@"url"]) {
[[MPiOSAppDelegate get].navigationController performSegueWithIdentifier:@"web" sender:[NSURL URLWithString:item.value]];
return;
}
}
else if ([url.host isEqualToString:@"migrate"]) {
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
if ([item.name isEqualToString:@"fullName"]) {
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
NSFetchRequest
*fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", item.value];
NSArray *users = [context executeFetchRequest:fetchRequest error:nil];
[self migrateFor:users.firstObject];
}];
return;
}
[self migrateFor:nil];
return;
}
} else
[UIApp openURL:url];
}
- (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController { - (void)showFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController {
if (![PearlEMail canSendMail]) { if (![PearlEMail canSendMail]) {
@@ -550,89 +624,162 @@
return; return;
} }
[self exportSitesRevealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) { [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
return PearlAwait( ^(void (^setResult)(id)) { NSError *error = nil;
PearlMainQueue( ^{ NSString *exportedUser = [self exportSitesFor:[self activeUserInContext:context] revealPasswords:revealPasswords askExportPassword:^NSString *(NSString *userName) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName ) return PearlAwait( ^(void (^setResult)(id)) {
message:@"Enter your master password to export the user." PearlMainQueue( ^{
preferredStyle:UIAlertControllerStyleAlert]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName )
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { message:@"Enter your master password to export the user."
textField.secureTextEntry = YES; preferredStyle:UIAlertControllerStyleAlert];
}]; [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
[alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { textField.secureTextEntry = YES;
setResult( alert.textFields.firstObject.text ); }];
}]]; [alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { setResult( alert.textFields.firstObject.text );
setResult( nil ); }]];
}]]; [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
[self.navigationController presentViewController:alert animated:YES completion:nil]; setResult( nil );
}]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
} );
} ); } );
} ); } error:&error];
} result:^(NSString *exportedUser, NSError *error) {
if (!exportedUser || error) { PearlMainQueue( ^{
MPError( error, @"Failed to export mpsites." ); if (!exportedUser || error) {
PearlMainQueue( ^{ MPError( error, @"Failed to export mpsites." );
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error" message:[error localizedDescription] UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error" message:[error localizedDescription]
preferredStyle:UIAlertControllerStyleAlert]; preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]]; [alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil]; [self.navigationController presentViewController:alert animated:YES completion:nil];
} ); return;
}
NSDateFormatter *exportDateFormatter = [NSDateFormatter new];
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
NSString *exportFileName = strf( @"%@ (%@).mpsites",
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] );
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Destination" message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:@"Send As E-Mail" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSString *message;
if (revealPasswords)
message = strf( @"Export of Master Password sites with passwords included.\n\n"
@"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n"
@"--\n"
@"%@\n"
@"Master Password %@, build %@",
[self activeUserForMainThread].name,
[PearlInfoPlist get].CFBundleShortVersionString,
[PearlInfoPlist get].CFBundleVersion );
else
message = strf( @"Backup of Master Password sites.\n\n\n"
@"--\n"
@"%@\n"
@"Master Password %@, build %@",
[self activeUserForMainThread].name,
[PearlInfoPlist get].CFBundleShortVersionString,
[PearlInfoPlist get].CFBundleVersion );
[PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message
attachments:[[PearlEMailAttachment alloc] initWithContent:[exportedUser dataUsingEncoding:NSUTF8StringEncoding]
mimeType:@"text/plain"
fileName:exportFileName], nil];
return;
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Share / Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSURL *applicationSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *exportURL = [[applicationSupportURL
URLByAppendingPathComponent:[NSBundle mainBundle].bundleIdentifier isDirectory:YES]
URLByAppendingPathComponent:exportFileName isDirectory:NO];
NSError *writeError = nil;
if (![[exportedUser dataUsingEncoding:NSUTF8StringEncoding]
writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&writeError])
MPError( writeError, @"Failed to write export data to URL %@.", exportURL );
else {
self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:exportURL];
self.interactionController.UTI = @"com.lyndir.masterpassword.sites";
self.interactionController.delegate = self;
[self.interactionController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES];
}
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
} );
}];
}
- (void)migrateFor:(MPUserEntity *)user {
if ([UIApp canOpenURL:[[NSURL alloc] initWithString:@"volto:"]]) {
if (!user) {
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
NSArray *users = [context executeFetchRequest:fetchRequest error:nil];
if (![users count])
return;
UIAlertController *usersSheet = [UIAlertController alertControllerWithTitle:@"Migrate User"
message:@"Choose a user to migrate out to Volto."
preferredStyle:UIAlertControllerStyleActionSheet];
[usersSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
for (MPUserEntity *user_ in users)
[usersSheet addAction:[UIAlertAction actionWithTitle:user_.name style:UIAlertActionStyleDefault handler:
^(UIAlertAction *action) { [self migrateFor:user_]; }]];
PearlMainQueue( ^{
[self.navigationController presentViewController:usersSheet animated:YES completion:nil];
} );
}];
return; return;
} }
NSDateFormatter *exportDateFormatter = [NSDateFormatter new]; [MPAppDelegate_Shared managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
[exportDateFormatter setDateFormat:@"yyyy'-'MM'-'dd"]; NSError *error = nil;
NSString *exportFileName = strf( @"%@ (%@).mpsites", NSString *exportedUser = [[MPAppDelegate_Shared get] exportSitesFor:[MPUserEntity existingObjectWithID:user.objectID inContext:context]
[self activeUserForMainThread].name, [exportDateFormatter stringFromDate:[NSDate date]] ); revealPasswords:NO askExportPassword:^NSString *(NSString *userName) {
return PearlAwait( ^(void (^setResult)(id)) {
PearlMainQueue( ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:strf( @"Master Password For:\n%@", userName )
message:@"Enter your master password to export the user."
preferredStyle:UIAlertControllerStyleAlert];
[alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.secureTextEntry = YES;
}];
[alert addAction:[UIAlertAction actionWithTitle:@"Export" style:UIAlertActionStyleDefault handler:
^(UIAlertAction *action) { setResult( alert.textFields.firstObject.text ); }]];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:
^(UIAlertAction *action) { setResult( nil ); }]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
} );
} );
} error:&error];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Destination" message:nil PearlMainQueue( ^{
preferredStyle:UIAlertControllerStyleActionSheet]; if (!exportedUser || error) {
[alert addAction:[UIAlertAction actionWithTitle:@"Send As E-Mail" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { MPError( error, @"Failed to export user." );
NSString *message; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Export Error"
if (revealPasswords) message:[error localizedDescription]
message = strf( @"Export of Master Password sites with passwords included.\n\n" preferredStyle:UIAlertControllerStyleAlert];
@"REMINDER: Make sure nobody else sees this file! Passwords are visible!\n\n\n" [alert addAction:[UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleCancel handler:nil]];
@"--\n" [self.navigationController presentViewController:alert animated:YES completion:nil];
@"%@\n" return;
@"Master Password %@, build %@", }
[self activeUserForMainThread].name,
[PearlInfoPlist get].CFBundleShortVersionString,
[PearlInfoPlist get].CFBundleVersion );
else
message = strf( @"Backup of Master Password sites.\n\n\n"
@"--\n"
@"%@\n"
@"Master Password %@, build %@",
[self activeUserForMainThread].name,
[PearlInfoPlist get].CFBundleShortVersionString,
[PearlInfoPlist get].CFBundleVersion );
[PearlEMail sendEMailTo:nil fromVC:viewController subject:@"Master Password Export" body:message NSURLComponents *components = [NSURLComponents new];
attachments:[[PearlEMailAttachment alloc] initWithContent:[exportedUser dataUsingEncoding:NSUTF8StringEncoding] components.scheme = @"volto";
mimeType:@"text/plain" components.path = @"import";
fileName:exportFileName], nil]; components.queryItems = @[ [[NSURLQueryItem alloc] initWithName:@"data" value:exportedUser] ];
return; [UIApp openURL:components.URL];
}]]; } );
[alert addAction:[UIAlertAction actionWithTitle:@"Share / Export" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { }];
NSURL *applicationSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory }
inDomains:NSUserDomainMask] lastObject];
NSURL *exportURL = [[applicationSupportURL else if (self.voltoViewController)
URLByAppendingPathComponent:[NSBundle mainBundle].bundleIdentifier isDirectory:YES] [self.navigationController presentViewController:self.voltoViewController animated:YES completion:nil];
URLByAppendingPathComponent:exportFileName isDirectory:NO];
NSError *writeError = nil;
if (![[exportedUser dataUsingEncoding:NSUTF8StringEncoding]
writeToURL:exportURL options:NSDataWritingFileProtectionComplete error:&writeError])
MPError( writeError, @"Failed to write export data to URL %@.", exportURL );
else {
self.interactionController = [UIDocumentInteractionController interactionControllerWithURL:exportURL];
self.interactionController.UTI = @"com.lyndir.masterpassword.sites";
self.interactionController.delegate = self;
[self.interactionController presentOpenInMenuFromRect:CGRectZero inView:viewController.view animated:YES];
}
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleCancel handler:nil]];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}];
} }
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset { - (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void ( ^ )(void))didReset {
@@ -660,6 +807,13 @@
} ); } );
} }
#pragma mark - SKStoreProductViewControllerDelegate
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[viewController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - UIDocumentInteractionControllerDelegate #pragma mark - UIDocumentInteractionControllerDelegate
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application { - (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application {

View File

@@ -11,9 +11,9 @@
<dict> <dict>
<key>CFBundleTypeIconFiles</key> <key>CFBundleTypeIconFiles</key>
<array> <array>
<string>Icon-Small</string> <string>Icon-Small-40.png</string>
<string>Icon-64.png</string> <string>Icon-Small-40@2x.png</string>
<string>Icon-320.png</string> <string>Icon-Small-40@3x.png</string>
</array> </array>
<key>CFBundleTypeName</key> <key>CFBundleTypeName</key>
<string>Master Password sites</string> <string>Master Password sites</string>
@@ -21,6 +21,7 @@
<string>Alternate</string> <string>Alternate</string>
<key>LSItemContentTypes</key> <key>LSItemContentTypes</key>
<array> <array>
<string>com.lyndir.masterpassword.json</string>
<string>com.lyndir.masterpassword.sites</string> <string>com.lyndir.masterpassword.sites</string>
</array> </array>
</dict> </dict>
@@ -37,8 +38,30 @@
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>[auto]</string> <string>[auto]</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLIconFile</key>
<string>Icon-Small-40@3x</string>
<key>CFBundleURLName</key>
<string>com.lyndir.masterpassword</string>
<key>CFBundleURLSchemes</key>
<array>
<string>masterpassword</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>[auto]</string> <string>[auto]</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>firefox</string>
<string>googlechrome</string>
<string>opera-http</string>
<string>volto</string>
</array>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>LSSupportsOpeningDocumentsInPlace</key> <key>LSSupportsOpeningDocumentsInPlace</key>
@@ -103,6 +126,34 @@
</array> </array>
<key>UTExportedTypeDeclarations</key> <key>UTExportedTypeDeclarations</key>
<array> <array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Master Password JSON export</string>
<key>UTTypeIconFiles</key>
<array>
<string>Icon-Small-40.png</string>
<string>Icon-Small-40@2x.png</string>
<string>Icon-Small-40@3x.png</string>
</array>
<key>UTTypeIdentifier</key>
<string>com.lyndir.masterpassword.json</string>
<key>UTTypeReferenceURL</key>
<string>https://gitlab.com/MasterPassword/MasterPassword/-/wikis/File-Format</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>mpjson</string>
<string>mpsites.json</string>
</array>
<key>public.mime-type</key>
<string>text/plain</string>
</dict>
</dict>
<dict> <dict>
<key>UTTypeConformsTo</key> <key>UTTypeConformsTo</key>
<array> <array>
@@ -112,9 +163,9 @@
<string>Master Password sites</string> <string>Master Password sites</string>
<key>UTTypeIconFiles</key> <key>UTTypeIconFiles</key>
<array> <array>
<string>Icon-Small.png</string> <string>Icon-Small-40.png</string>
<string>Icon-64.png</string> <string>Icon-Small-40@2x.png</string>
<string>Icon-320.png</string> <string>Icon-Small-40@3x.png</string>
</array> </array>
<key>UTTypeIdentifier</key> <key>UTTypeIdentifier</key>
<string>com.lyndir.masterpassword.sites</string> <string>com.lyndir.masterpassword.sites</string>
@@ -123,6 +174,7 @@
<key>public.filename-extension</key> <key>public.filename-extension</key>
<array> <array>
<string>mpsites</string> <string>mpsites</string>
<string>mpsites.txt</string>
</array> </array>
</dict> </dict>
</dict> </dict>

View File

@@ -472,17 +472,11 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<webView contentMode="scaleToFill" scalesPageToFit="YES" suppressesIncrementalRendering="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3aB-Hk-Fgd">
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<outlet property="delegate" destination="Sd5-eW-Cx2" id="ePX-qz-XXR"/>
</connections>
</webView>
<navigationBar contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="03x-KT-JQN"> <navigationBar contentMode="scaleToFill" barStyle="black" translatesAutoresizingMaskIntoConstraints="NO" id="03x-KT-JQN">
<rect key="frame" x="0.0" y="0.0" width="414" height="90"/> <rect key="frame" x="0.0" y="0.0" width="414" height="90"/>
<items> <items>
<navigationItem title="masterpassword.app" prompt="Loading" id="Wpf-6b-UJb"> <navigationItem title="masterpassword.app" prompt="Loading" id="Wpf-6b-UJb">
<barButtonItem key="leftBarButtonItem" systemItem="action" id="d9P-Hd-rdw"/>
<barButtonItem key="rightBarButtonItem" systemItem="done" id="Tbg-c3-qOh"> <barButtonItem key="rightBarButtonItem" systemItem="done" id="Tbg-c3-qOh">
<connections> <connections>
<action selector="done:" destination="Sd5-eW-Cx2" id="cuN-bV-cwl"/> <action selector="done:" destination="Sd5-eW-Cx2" id="cuN-bV-cwl"/>
@@ -494,19 +488,14 @@
</subviews> </subviews>
<color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.12549020350000001" green="0.1411764771" blue="0.14901961389999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="3aB-Hk-Fgd" firstAttribute="top" secondItem="zXV-QC-CZm" secondAttribute="bottom" id="3Od-Xa-Ssc"/>
<constraint firstItem="03x-KT-JQN" firstAttribute="leading" secondItem="2Jz-8H-3nG" secondAttribute="leading" id="BAn-wU-k2A"/> <constraint firstItem="03x-KT-JQN" firstAttribute="leading" secondItem="2Jz-8H-3nG" secondAttribute="leading" id="BAn-wU-k2A"/>
<constraint firstItem="03x-KT-JQN" firstAttribute="top" secondItem="zXV-QC-CZm" secondAttribute="bottom" id="JU6-uj-GA3"/> <constraint firstItem="03x-KT-JQN" firstAttribute="top" secondItem="zXV-QC-CZm" secondAttribute="bottom" id="JU6-uj-GA3"/>
<constraint firstAttribute="bottom" secondItem="3aB-Hk-Fgd" secondAttribute="bottom" id="S01-AA-E0a"/>
<constraint firstAttribute="trailing" secondItem="03x-KT-JQN" secondAttribute="trailing" id="sQs-u3-M3r"/> <constraint firstAttribute="trailing" secondItem="03x-KT-JQN" secondAttribute="trailing" id="sQs-u3-M3r"/>
<constraint firstItem="3aB-Hk-Fgd" firstAttribute="leading" secondItem="2Jz-8H-3nG" secondAttribute="leading" id="w1l-x3-qCi"/>
<constraint firstAttribute="trailing" secondItem="3aB-Hk-Fgd" secondAttribute="trailing" id="xdJ-WF-yw0"/>
</constraints> </constraints>
</view> </view>
<navigationItem key="navigationItem" id="gmy-ym-z4I"/> <navigationItem key="navigationItem" id="gmy-ym-z4I"/>
<connections> <connections>
<outlet property="webNavigationItem" destination="Wpf-6b-UJb" id="8gM-LU-pHk"/> <outlet property="webNavigationItem" destination="Wpf-6b-UJb" id="8gM-LU-pHk"/>
<outlet property="webView" destination="3aB-Hk-Fgd" id="Mie-rI-l4h"/>
</connections> </connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="hNt-WS-DuE" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="hNt-WS-DuE" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -2324,7 +2313,7 @@ Suspendisse potenti. Etiam ut nisi id augue tempor ultrices et sit amet sapien.
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="OsH-Mq-gpM"> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="OsH-Mq-gpM">
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
</imageView> </imageView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ol8-3I-X99"> <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ol8-3I-X99">
@@ -2412,7 +2401,7 @@ However, it means that anyone who finds your device unlocked can do the same.</s
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="Hrg-vp-M2J"> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="Hrg-vp-M2J">
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
</imageView> </imageView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fJc-xU-1xA"> <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fJc-xU-1xA">
@@ -3036,7 +3025,7 @@ Invested: 3.7 work hours</string>
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<imageView userInteractionEnabled="NO" contentMode="center" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="rvb-7K-MHe"> <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="background.png" translatesAutoresizingMaskIntoConstraints="NO" id="rvb-7K-MHe">
<rect key="frame" x="0.0" y="0.0" width="414" height="842"/> <rect key="frame" x="0.0" y="0.0" width="414" height="842"/>
</imageView> </imageView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7A7-Yn-F6L"> <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7A7-Yn-F6L">
@@ -3268,8 +3257,8 @@ Ut in geometria, prima si dederis, danda sunt omnia. Nonne igitur tibi videntur,
</scene> </scene>
</scenes> </scenes>
<inferredMetricsTieBreakers> <inferredMetricsTieBreakers>
<segue reference="Ql4-wf-T8u"/> <segue reference="k2G-nL-x3l"/>
<segue reference="GZk-I4-JyH"/> <segue reference="gtb-zE-u9H"/>
</inferredMetricsTieBreakers> </inferredMetricsTieBreakers>
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<resources> <resources>

View File

@@ -1097,6 +1097,8 @@ MPMarshalledFile *mpw_marshal_read(
info->format = MPMarshalFormatJSON; info->format = MPMarshalFormatJSON;
#if MPW_JSON #if MPW_JSON
mpw_marshal_read_json( file, in ); mpw_marshal_read_json( file, in );
#else
mpw_marshal_error( file, MPMarshalErrorFormat, "JSON support is not enabled." );
#endif #endif
} }
} }