diff --git a/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj b/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj index cfb74216..0ba0f324 100644 --- a/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/Mac/MasterPassword-Mac.xcodeproj/project.pbxproj @@ -89,8 +89,6 @@ DACA22BC1705DE7D002C6C22 /* NSError+UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */; }; DACA22BD1705DE7D002C6C22 /* NSError+UbiquityStoreManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DACA22B91705DE7D002C6C22 /* NSError+UbiquityStoreManager.m */; }; DACA22BE1705DE7D002C6C22 /* UbiquityStoreManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */; }; - DACA26F91705DF81002C6C22 /* background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DACA24171705DF7D002C6C22 /* background@2x.png */; }; - DACA26FA1705DF81002C6C22 /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = DACA24181705DF7D002C6C22 /* background.png */; }; DACA26FE1705DF81002C6C22 /* logo-bare.png in Resources */ = {isa = PBXBuildFile; fileRef = DACA241C1705DF7D002C6C22 /* logo-bare.png */; }; DACA27121705DF81002C6C22 /* avatar-13@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DACA24321705DF7D002C6C22 /* avatar-13@2x.png */; }; DACA27131705DF81002C6C22 /* avatar-3@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DACA24331705DF7D002C6C22 /* avatar-3@2x.png */; }; @@ -751,8 +749,6 @@ DACA22B81705DE7D002C6C22 /* NSError+UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+UbiquityStoreManager.h"; sourceTree = ""; }; DACA22B91705DE7D002C6C22 /* NSError+UbiquityStoreManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+UbiquityStoreManager.m"; sourceTree = ""; }; DACA22BA1705DE7D002C6C22 /* UbiquityStoreManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UbiquityStoreManager.h; sourceTree = ""; }; - DACA24171705DF7D002C6C22 /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = ""; }; - DACA24181705DF7D002C6C22 /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = ""; }; DACA241C1705DF7D002C6C22 /* logo-bare.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "logo-bare.png"; sourceTree = ""; }; DACA24321705DF7D002C6C22 /* avatar-13@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-13@2x.png"; sourceTree = ""; }; DACA24331705DF7D002C6C22 /* avatar-3@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-3@2x.png"; sourceTree = ""; }; @@ -1550,7 +1546,6 @@ DA2509271951B86C00AC23F1 /* screen.png */, DA0933CF1747B91B00DE1CEF /* appstore.png */, DA0933CB1747AD2D00DE1CEF /* shot-laptop-leaning-iphone.png */, - DACA24161705DF7D002C6C22 /* Background */, DACA24311705DF7D002C6C22 /* Avatars */, DACA241C1705DF7D002C6C22 /* logo-bare.png */, DACA24581705DF7D002C6C22 /* menu-icon.png */, @@ -1559,15 +1554,6 @@ path = Media; sourceTree = ""; }; - DACA24161705DF7D002C6C22 /* Background */ = { - isa = PBXGroup; - children = ( - DACA24171705DF7D002C6C22 /* background@2x.png */, - DACA24181705DF7D002C6C22 /* background.png */, - ); - path = Background; - sourceTree = ""; - }; DACA24311705DF7D002C6C22 /* Avatars */ = { isa = PBXGroup; children = ( @@ -2006,8 +1992,6 @@ buildActionMask = 2147483647; files = ( DAFE4A5A1503982E003ABA7C /* Pearl.strings in Resources */, - DACA26F91705DF81002C6C22 /* background@2x.png in Resources */, - DACA26FA1705DF81002C6C22 /* background.png in Resources */, DACA26FE1705DF81002C6C22 /* logo-bare.png in Resources */, DACA27121705DF81002C6C22 /* avatar-13@2x.png in Resources */, DACA27131705DF81002C6C22 /* avatar-3@2x.png in Resources */, diff --git a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m index a2260c71..b918993e 100644 --- a/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m +++ b/MasterPassword/ObjC/iOS/MPiOSAppDelegate.m @@ -286,7 +286,8 @@ NSString *importHeader = @"# Master Password site export"; NSString *importedSitesString = [UIPasteboard generalPasteboard].string; - if ([[importedSitesString substringToIndex:[importHeader length]] isEqualToString:importHeader]) + if ([importedSitesString length] > [importHeader length] && + [[importedSitesString substringToIndex:[importHeader length]] isEqualToString:importHeader]) [PearlAlert showAlertWithTitle:@"Import Sites?" message: @"We've detected Master Password import sites on your pasteboard, would you like to import them?" viewStyle:UIAlertViewStyleDefault initAlert:nil diff --git a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj index 5b25c052..4349ff57 100644 --- a/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -136,6 +136,9 @@ DA32D05119D3D107004F3F0E /* icon_meter.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37BA1711E29600CF925C /* icon_meter.png */; }; DA32D05219D3D107004F3F0E /* icon_meter@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD37BB1711E29600CF925C /* icon_meter@2x.png */; }; DA32D05519D741DC004F3F0E /* MPSiteQuestionEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = DA32D05419D741DC004F3F0E /* MPSiteQuestionEntity.m */; }; + DA32D07A19D7D784004F3F0E /* background@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA32D07719D7D784004F3F0E /* background@3x.png */; }; + DA32D07B19D7D784004F3F0E /* background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA32D07819D7D784004F3F0E /* background@2x.png */; }; + DA32D07C19D7D784004F3F0E /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = DA32D07919D7D784004F3F0E /* background.png */; }; DA3509FE15F101A500C14A8E /* PearlQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = DA3509FC15F101A500C14A8E /* PearlQueue.h */; }; DA3509FF15F101A500C14A8E /* PearlQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3509FD15F101A500C14A8E /* PearlQueue.m */; }; DA38D6A318CCB5BF009AEB3E /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */; }; @@ -226,8 +229,6 @@ DABD395A1711E29700CF925C /* avatar-8@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD368F1711E29400CF925C /* avatar-8@2x.png */; }; DABD395B1711E29700CF925C /* avatar-9.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36901711E29400CF925C /* avatar-9.png */; }; DABD395C1711E29700CF925C /* avatar-9@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36911711E29400CF925C /* avatar-9@2x.png */; }; - DABD395D1711E29700CF925C /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36931711E29400CF925C /* background.png */; }; - DABD395E1711E29700CF925C /* background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36941711E29400CF925C /* background@2x.png */; }; DABD39871711E29700CF925C /* SourceCodePro-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = DABD36BF1711E29500CF925C /* SourceCodePro-Black.otf */; }; DABD39881711E29700CF925C /* SourceCodePro-ExtraLight.otf in Resources */ = {isa = PBXBuildFile; fileRef = DABD36C01711E29500CF925C /* SourceCodePro-ExtraLight.otf */; }; DABD39A01711E29700CF925C /* icon_action.png in Resources */ = {isa = PBXBuildFile; fileRef = DABD36DA1711E29500CF925C /* icon_action.png */; }; @@ -570,6 +571,9 @@ DA32D04D19D2F59B004F3F0E /* meter_fuel.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = meter_fuel.png; sourceTree = ""; }; DA32D05319D741DC004F3F0E /* MPSiteQuestionEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSiteQuestionEntity.h; sourceTree = ""; }; DA32D05419D741DC004F3F0E /* MPSiteQuestionEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSiteQuestionEntity.m; sourceTree = ""; }; + DA32D07719D7D784004F3F0E /* background@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "background@3x.png"; path = "ios/launch/background@3x.png"; sourceTree = ""; }; + DA32D07819D7D784004F3F0E /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "background@2x.png"; path = "ios/launch/background@2x.png"; sourceTree = ""; }; + DA32D07919D7D784004F3F0E /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = background.png; path = ios/launch/background.png; sourceTree = ""; }; DA3509FC15F101A500C14A8E /* PearlQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlQueue.h; sourceTree = ""; }; DA3509FD15F101A500C14A8E /* PearlQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlQueue.m; sourceTree = ""; }; DA38D6A218CCB5BF009AEB3E /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = ""; }; @@ -736,8 +740,6 @@ DABD368F1711E29400CF925C /* avatar-8@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-8@2x.png"; sourceTree = ""; }; DABD36901711E29400CF925C /* avatar-9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-9.png"; sourceTree = ""; }; DABD36911711E29400CF925C /* avatar-9@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "avatar-9@2x.png"; sourceTree = ""; }; - DABD36931711E29400CF925C /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = ""; }; - DABD36941711E29400CF925C /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = ""; }; DABD36BF1711E29500CF925C /* SourceCodePro-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-Black.otf"; sourceTree = ""; }; DABD36C01711E29500CF925C /* SourceCodePro-ExtraLight.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceCodePro-ExtraLight.otf"; sourceTree = ""; }; DABD36DA1711E29500CF925C /* icon_action.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_action.png; sourceTree = ""; }; @@ -1626,6 +1628,9 @@ DABD360D1711E29400CF925C /* Media */ = { isa = PBXGroup; children = ( + DA32D07719D7D784004F3F0E /* background@3x.png */, + DA32D07819D7D784004F3F0E /* background@2x.png */, + DA32D07919D7D784004F3F0E /* background.png */, DA32D04B19D2F59B004F3F0E /* meter_fuel@3x.png */, DA32D04C19D2F59B004F3F0E /* meter_fuel@2x.png */, DA32D04D19D2F59B004F3F0E /* meter_fuel.png */, @@ -1650,7 +1655,6 @@ DA5A09DE171A70E4005284AB /* play@2x.png */, DABD360E1711E29400CF925C /* Automaton */, DABD366B1711E29400CF925C /* Avatars */, - DABD36921711E29400CF925C /* Background */, DABD36BB1711E29500CF925C /* Fonts */, DABD36D91711E29500CF925C /* Insignia */, DABD38751711E29700CF925C /* Tooltips */, @@ -1817,15 +1821,6 @@ path = Avatars; sourceTree = ""; }; - DABD36921711E29400CF925C /* Background */ = { - isa = PBXGroup; - children = ( - DABD36931711E29400CF925C /* background.png */, - DABD36941711E29400CF925C /* background@2x.png */, - ); - path = Background; - sourceTree = ""; - }; DABD36BB1711E29500CF925C /* Fonts */ = { isa = PBXGroup; children = ( @@ -3141,6 +3136,7 @@ DABD393F1711E29700CF925C /* avatar-12@2x.png in Resources */, DA67461018DE7F0C00DFE240 /* Exo2.0-Bold.otf in Resources */, DABD39401711E29700CF925C /* avatar-13.png in Resources */, + DA32D07C19D7D784004F3F0E /* background.png in Resources */, DABD39411711E29700CF925C /* avatar-13@2x.png in Resources */, DABD39421711E29700CF925C /* avatar-14.png in Resources */, DABD39431711E29700CF925C /* avatar-14@2x.png in Resources */, @@ -3159,6 +3155,7 @@ DABD394A1711E29700CF925C /* avatar-18.png in Resources */, DABD394B1711E29700CF925C /* avatar-18@2x.png in Resources */, DABD394C1711E29700CF925C /* avatar-1@2x.png in Resources */, + DA32D07A19D7D784004F3F0E /* background@3x.png in Resources */, DA32D04319D27093004F3F0E /* thumb_generated_answers@2x.png in Resources */, DA29993319C9214600AF7DF1 /* icon_star-hollow.png in Resources */, DA29993019C86F5700AF7DF1 /* thumb_generated_login.png in Resources */, @@ -3187,6 +3184,7 @@ DABD39551711E29700CF925C /* avatar-6.png in Resources */, DA32D00919CF5C55004F3F0E /* icon_question.png in Resources */, DABD39561711E29700CF925C /* avatar-6@2x.png in Resources */, + DA32D07B19D7D784004F3F0E /* background@2x.png in Resources */, DABD39571711E29700CF925C /* avatar-7.png in Resources */, DABD39581711E29700CF925C /* avatar-7@2x.png in Resources */, DABD39591711E29700CF925C /* avatar-8.png in Resources */, @@ -3196,9 +3194,7 @@ DABD395A1711E29700CF925C /* avatar-8@2x.png in Resources */, DABD395B1711E29700CF925C /* avatar-9.png in Resources */, DABD395C1711E29700CF925C /* avatar-9@2x.png in Resources */, - DABD395D1711E29700CF925C /* background.png in Resources */, DA45224719062899008F650A /* icon_settings.png in Resources */, - DABD395E1711E29700CF925C /* background@2x.png in Resources */, DA945C8717E3F3FD0053236B /* Images.xcassets in Resources */, DA32D04E19D2F59B004F3F0E /* meter_fuel@3x.png in Resources */, DA250A101956484D00AC23F1 /* image-1.png in Resources */, diff --git a/MasterPassword/ObjC/iOS/Storyboard.storyboard b/MasterPassword/ObjC/iOS/Storyboard.storyboard index edf587b3..cdd2dffd 100644 --- a/MasterPassword/ObjC/iOS/Storyboard.storyboard +++ b/MasterPassword/ObjC/iOS/Storyboard.storyboard @@ -1,6 +1,7 @@ + @@ -223,11 +224,11 @@ - + - + @@ -296,7 +297,7 @@ - - diff --git a/MasterPassword/Resources/Media/Background/background.png b/MasterPassword/Resources/Media/Background/background.png deleted file mode 100644 index dad596a0..00000000 Binary files a/MasterPassword/Resources/Media/Background/background.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Background/background@2x.png b/MasterPassword/Resources/Media/Background/background@2x.png deleted file mode 100644 index 7bcaa643..00000000 Binary files a/MasterPassword/Resources/Media/Background/background@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Contents.json b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Contents.json index 9bf232b9..ab497008 100644 --- a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,130 +1 @@ -{ - "images" : [ - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-Small@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-40@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-60@2x.png", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-Small~ipad.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-Small~ipad@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-40~ipad.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-40~ipad@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-76~ipad@2x.png", - "scale" : "2x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "icon_16x16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "icon_16x16@2x.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "icon_32x32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "icon_32x32@2x.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "icon_128x128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "icon_128x128@2x.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "icon_256x256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "icon_256x256@2x.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "icon_512x512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "icon_512x512@2x.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - }, - "properties" : { - "pre-rendered" : true - } -} \ No newline at end of file +{"images":[{"size":"60x60","filename":"Icon-60@3x.png","scale":"3x","idiom":"iphone","minimum-system-version":"8.0"},{"size":"40x40","filename":"Icon-Small-40@3x.png","scale":"3x","idiom":"iphone","minimum-system-version":"8.0"},{"size":"60x60","filename":"Icon-60@2x.png","scale":"2x","idiom":"iphone","minimum-system-version":"7.0"},{"size":"40x40","filename":"Icon-Small-40@2x.png","scale":"2x","idiom":"iphone","minimum-system-version":"7.0"},{"size":"29x29","filename":"Icon-Small@3x.png","scale":"3x","idiom":"iphone"},{"size":"29x29","filename":"Icon-Small@2x.png","scale":"2x","idiom":"iphone"},{"size":"76x76","filename":"Icon-76.png","scale":"1x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"76x76","filename":"Icon-76@2x.png","scale":"2x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"40x40","filename":"Icon-Small-40.png","scale":"1x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"40x40","filename":"Icon-Small-40@2x.png","scale":"2x","idiom":"ipad","minimum-system-version":"7.0"},{"size":"29x29","filename":"Icon-Small.png","scale":"1x","idiom":"ipad"},{"size":"29x29","filename":"Icon-Small@2x.png","scale":"2x","idiom":"ipad"}],"info":{"version":1,"author":"genassets"},"properties":{"pre-rendered":true}} diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40.png deleted file mode 100644 index 1440a52c..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png deleted file mode 100644 index 49782f32..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40~ipad.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40~ipad.png deleted file mode 100644 index f15120d0..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40~ipad.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40~ipad@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40~ipad@2x.png deleted file mode 100644 index 49782f32..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-40~ipad@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60.png deleted file mode 100644 index 7abcac4b..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png index 14fda56b..7114a7c2 100644 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100644 index 00000000..55f9156b Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100644 index 00000000..bfbf3e21 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png new file mode 100644 index 00000000..c8461614 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76~ipad.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76~ipad.png deleted file mode 100644 index c61b5405..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76~ipad.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76~ipad@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76~ipad@2x.png deleted file mode 100644 index 02754d64..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-76~ipad@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png new file mode 100644 index 00000000..74fd5255 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png new file mode 100644 index 00000000..a3ecee29 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png new file mode 100644 index 00000000..71a9d426 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small.png index e2c69304..acdc47d8 100644 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small.png and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png index 891c2215..7eae5f31 100644 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png new file mode 100644 index 00000000..59f1cb15 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small~ipad.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small~ipad.png deleted file mode 100644 index 80f33ab4..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small~ipad.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small~ipad@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small~ipad@2x.png deleted file mode 100644 index 891c2215..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/Icon-Small~ipad@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_128x128.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_128x128.png deleted file mode 100644 index eb8e26ce..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_128x128.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_128x128@2x.png deleted file mode 100644 index ef7cfa27..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_128x128@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_16x16.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_16x16.png deleted file mode 100644 index 7b2702d3..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_16x16.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_16x16@2x.png deleted file mode 100644 index b2d66af9..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_16x16@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_256x256.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_256x256.png deleted file mode 100644 index ef7cfa27..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_256x256.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_256x256@2x.png deleted file mode 100644 index 9c44abf6..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_256x256@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_32x32.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_32x32.png deleted file mode 100644 index b2d66af9..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_32x32.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_32x32@2x.png deleted file mode 100644 index a493fd56..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_32x32@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_512x512.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_512x512.png deleted file mode 100644 index 9c44abf6..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_512x512.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_512x512@2x.png deleted file mode 100644 index 3d18b7d8..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/AppIcon.appiconset/icon_512x512@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Contents.json b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Contents.json index 36323a58..51321c40 100644 --- a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Contents.json +++ b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -1,47 +1 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "filename" : "Default@2x.png", - "scale" : "2x" - }, - { - "extent" : "full-screen", - "idiom" : "iphone", - "subtype" : "retina4", - "filename" : "Default-568h@2x.png", - "minimum-system-version" : "7.0", - "orientation" : "portrait", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "filename" : "Default.png", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "filename" : "Default@2x.png", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "filename" : "Default-568h@2x.png", - "subtype" : "retina4", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file +{"images":[{"extent":"full-screen","filename":"Default-8.0-736h@3x~iphone.png","orientation":"portrait","scale":"3x","idiom":"iphone","minimum-system-version":"8.0","subtype":"736h"},{"extent":"full-screen","filename":"Default-8.0-667h@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","minimum-system-version":"8.0","subtype":"667h"},{"extent":"full-screen","filename":"Default-7.0-retina4@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","minimum-system-version":"7.0","subtype":"retina4"},{"extent":"full-screen","filename":"Default-retina4@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","subtype":"retina4"},{"extent":"full-screen","filename":"Default-7.0@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone","minimum-system-version":"7.0"},{"extent":"full-screen","filename":"Default@2x~iphone.png","orientation":"portrait","scale":"2x","idiom":"iphone"},{"extent":"full-screen","filename":"Default~iphone.png","orientation":"portrait","scale":"1x","idiom":"iphone"}],"info":{"version":1,"author":"genassets"}} diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-568h.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-568h.png deleted file mode 100644 index 8ed0f0f1..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-568h.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png deleted file mode 100644 index 6f38547b..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-7.0-retina4@2x~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-7.0-retina4@2x~iphone.png new file mode 100644 index 00000000..9a562438 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-7.0-retina4@2x~iphone.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-7.0@2x~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-7.0@2x~iphone.png new file mode 100644 index 00000000..de9e0c2e Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-7.0@2x~iphone.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-8.0-667h@2x~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-8.0-667h@2x~iphone.png new file mode 100644 index 00000000..0773327e Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-8.0-667h@2x~iphone.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-8.0-736h@3x~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-8.0-736h@3x~iphone.png new file mode 100644 index 00000000..43494505 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-8.0-736h@3x~iphone.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-retina4@2x~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-retina4@2x~iphone.png new file mode 100644 index 00000000..9a562438 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default-retina4@2x~iphone.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default.png deleted file mode 100644 index f5eede50..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default@2x.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default@2x.png deleted file mode 100644 index 34007168..00000000 Binary files a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default@2x.png and /dev/null differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png new file mode 100644 index 00000000..de9e0c2e Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default@2x~iphone.png differ diff --git a/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default~iphone.png b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default~iphone.png new file mode 100644 index 00000000..9024b377 Binary files /dev/null and b/MasterPassword/Resources/Media/Images.xcassets/LaunchImage.launchimage/Default~iphone.png differ diff --git a/MasterPassword/Resources/Media/ios/icon.sketch/Data b/MasterPassword/Resources/Media/ios/icon.sketch/Data new file mode 100644 index 00000000..6f4326b9 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon.sketch/Data differ diff --git a/MasterPassword/Resources/Media/ios/icon.sketch/metadata b/MasterPassword/Resources/Media/ios/icon.sketch/metadata new file mode 100644 index 00000000..ea614509 --- /dev/null +++ b/MasterPassword/Resources/Media/ios/icon.sketch/metadata @@ -0,0 +1,22 @@ + + + + + app + com.bohemiancoding.sketch3 + build + 8053 + commit + 104f8b8798002207eebbbee810c02306c5ce85c9 + fonts + + SourceCodePro-Light + LucidaGrande + HelveticaNeue-Medium + + length + 353295 + version + 37 + + diff --git a/MasterPassword/Resources/Media/ios/icon.sketch/version b/MasterPassword/Resources/Media/ios/icon.sketch/version new file mode 100644 index 00000000..7c091989 --- /dev/null +++ b/MasterPassword/Resources/Media/ios/icon.sketch/version @@ -0,0 +1 @@ +37 \ No newline at end of file diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-60.png b/MasterPassword/Resources/Media/ios/icon/Icon-60.png new file mode 100644 index 00000000..4110269c Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-60.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-60@2x.png b/MasterPassword/Resources/Media/ios/icon/Icon-60@2x.png new file mode 100644 index 00000000..7114a7c2 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-60@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-60@3x.png b/MasterPassword/Resources/Media/ios/icon/Icon-60@3x.png new file mode 100644 index 00000000..55f9156b Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-60@3x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-76.png b/MasterPassword/Resources/Media/ios/icon/Icon-76.png new file mode 100644 index 00000000..bfbf3e21 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-76.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-76@2x.png b/MasterPassword/Resources/Media/ios/icon/Icon-76@2x.png new file mode 100644 index 00000000..c8461614 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-76@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-Small-40.png b/MasterPassword/Resources/Media/ios/icon/Icon-Small-40.png new file mode 100644 index 00000000..74fd5255 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-Small-40.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-Small-40@2x.png b/MasterPassword/Resources/Media/ios/icon/Icon-Small-40@2x.png new file mode 100644 index 00000000..a3ecee29 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-Small-40@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-Small-40@3x.png b/MasterPassword/Resources/Media/ios/icon/Icon-Small-40@3x.png new file mode 100644 index 00000000..71a9d426 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-Small-40@3x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-Small.png b/MasterPassword/Resources/Media/ios/icon/Icon-Small.png new file mode 100644 index 00000000..acdc47d8 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-Small.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-Small@2x.png b/MasterPassword/Resources/Media/ios/icon/Icon-Small@2x.png new file mode 100644 index 00000000..7eae5f31 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-Small@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/Icon-Small@3x.png b/MasterPassword/Resources/Media/ios/icon/Icon-Small@3x.png new file mode 100644 index 00000000..59f1cb15 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/Icon-Small@3x.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/iTunesArtwork.png b/MasterPassword/Resources/Media/ios/icon/iTunesArtwork.png new file mode 100644 index 00000000..16fea132 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/iTunesArtwork.png differ diff --git a/MasterPassword/Resources/Media/ios/icon/iTunesArtwork@2x.png b/MasterPassword/Resources/Media/ios/icon/iTunesArtwork@2x.png new file mode 100644 index 00000000..0fe2ab28 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/icon/iTunesArtwork@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/launch.sketch/Data b/MasterPassword/Resources/Media/ios/launch.sketch/Data new file mode 100644 index 00000000..9d2ff66a Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch.sketch/Data differ diff --git a/MasterPassword/Resources/Media/ios/launch.sketch/metadata b/MasterPassword/Resources/Media/ios/launch.sketch/metadata new file mode 100644 index 00000000..72b521b0 --- /dev/null +++ b/MasterPassword/Resources/Media/ios/launch.sketch/metadata @@ -0,0 +1,18 @@ + + + + + app + com.bohemiancoding.sketch3 + build + 8053 + commit + 104f8b8798002207eebbbee810c02306c5ce85c9 + fonts + + length + 297465 + version + 37 + + diff --git a/MasterPassword/Resources/Media/ios/launch.sketch/version b/MasterPassword/Resources/Media/ios/launch.sketch/version new file mode 100644 index 00000000..7c091989 --- /dev/null +++ b/MasterPassword/Resources/Media/ios/launch.sketch/version @@ -0,0 +1 @@ +37 \ No newline at end of file diff --git a/MasterPassword/Resources/Media/ios/launch/32.png b/MasterPassword/Resources/Media/ios/launch/32.png new file mode 100644 index 00000000..285bacd3 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/32.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/320-480.png b/MasterPassword/Resources/Media/ios/launch/320-480.png new file mode 100644 index 00000000..9024b377 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/320-480.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/320-480@2x.png b/MasterPassword/Resources/Media/ios/launch/320-480@2x.png new file mode 100644 index 00000000..de9e0c2e Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/320-480@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/320-568@2x.png b/MasterPassword/Resources/Media/ios/launch/320-568@2x.png new file mode 100644 index 00000000..9a562438 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/320-568@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/375-667@2x.png b/MasterPassword/Resources/Media/ios/launch/375-667@2x.png new file mode 100644 index 00000000..0773327e Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/375-667@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/414-736@3x.png b/MasterPassword/Resources/Media/ios/launch/414-736@3x.png new file mode 100644 index 00000000..43494505 Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/414-736@3x.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/background.png b/MasterPassword/Resources/Media/ios/launch/background.png new file mode 100644 index 00000000..457ec60c Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/background.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/background@2x.png b/MasterPassword/Resources/Media/ios/launch/background@2x.png new file mode 100644 index 00000000..39fd79cc Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/background@2x.png differ diff --git a/MasterPassword/Resources/Media/ios/launch/background@3x.png b/MasterPassword/Resources/Media/ios/launch/background@3x.png new file mode 100644 index 00000000..7c7f5c6e Binary files /dev/null and b/MasterPassword/Resources/Media/ios/launch/background@3x.png differ diff --git a/Scripts/bashlib b/Scripts/bashlib index 0e1686b1..0a798aa0 100644 --- a/Scripts/bashlib +++ b/Scripts/bashlib @@ -18,28 +18,160 @@ # ___________________________________________________________________________ # # # # # -# Copyright 2007-2010, lhunath # +# Copyright 2007-2013, lhunath # # * http://www.lhunath.com # # * Maarten Billemont # # # +# ______________________________________________________________________ +# | | +# | .:: TABLE OF CONTENTS ::. | +# |______________________________________________________________________| +# +# chr decimal +# Outputs the character that has the given decimal ASCII value. +# +# ord character +# Outputs the decimal ASCII value of the given character. +# +# hex character +# Outputs the hexadecimal ASCII value of the given character. +# +# unhex character +# Outputs the character that has the given decimal ASCII value. +# +# max numbers... +# Outputs the highest of the given numbers. +# +# min numbers... +# Outputs the lowest of the given numbers. +# +# totime "YYYY-MM-DD HH:MM:SS.mmm"... +# Outputs the number of milliseconds in the given date string(s). +# +# exists application +# Succeeds if the application is in PATH and is executable. +# +# eol message +# Return termination punctuation for a message, if necessary. +# +# hr pattern [length] +# Outputs a horizontal ruler of the given length in characters or the terminal column length otherwise. +# +# cloc +# Outputs the current cursor location as two space-separated numbers: row column. +# +# readwhile command [args] +# Outputs the characters typed by the user into the terminal's input buffer while running the given command. +# +# pushqueue element ... +# Pushes the given arguments as elements onto the queue. +# +# popqueue +# Pops one element off the queue. +# +# log [format] [arguments...] +# Log an event at a certain importance level. +# The event is expressed as a printf(1) format argument. +# +# ask [-c optionchars|-d default] [-s|-S maskchar] message... +# Ask a question and read the user's reply to it. Then output the result on stdout. +# +# trim lines ... +# Trim the whitespace off of the beginning and end of the given lines. +# +# reverse [-0|-d delimitor] [elements ...] [<<< elements] +# Reverse the order of the given elements. +# +# order [-0|-d char] [-[cC] isAscending|-n] [-t number] [elements ...] [<<< elements] +# Orders the elements in ascending order. +# +# mutex file +# Open a mutual exclusion lock on the file, unless another process already owns one. +# +# pushjob [poolsize] command +# Start an asynchronous command within a pool, waiting for space in the pool if it is full. +# +# fsleep time +# Wait for the given (fractional) amount of seconds. +# +# showHelp name description author [option description]... +# Generate a prettily formatted usage description of the application. +# +# shquote [-e] [argument...] +# Shell-quote the arguments to make them safe for injection into bash code. +# +# requote [string] +# Escape the argument string to make it safe for injection into a regex. +# +# shorten [-p pwd] path [suffix]... +# Shorten an absolute path for pretty printing. +# +# up .../path|num +# Walk the current working directory up towards root num times or until path is found. +# +# buildarray name terms... -- elements... +# Create an array by adding all the terms to it for each element, replacing {} terms by the element. +# +# inArray element array +# Checks whether a certain element is in the given array. +# +# xpathNodes query [files...] +# Outputs every xpath node that matches the query on a separate line. +# +# hideDebug [on|off] +# Toggle Bash's debugging mode off temporarily. +# +# stackTrace +# Output the current script's function execution stack. +# +_tocHash=71e13f42e1ea82c1c7019b27a3bc71f3 + + # ______________________________________________________________________ # | | # | .:: GLOBAL CONFIGURATION ::. | # |______________________________________________________________________| +# Unset all exported functions. Exported functions are evil. +while read _ _ func; do + command unset -f "$func" +done < <(command declare -Fx) + { shopt -s extglob shopt -s globstar } 2>/dev/null ||: -# Unset all exported functions. Exported functions are evil. -while read _ _ func; do - unset -f "$func" -done < <(declare -Fx) +# Generate Table Of Contents +genToc() { + local line= comments=() usage= whatis= lineno=0 out= outhash= outline= + while read -r line; do + (( ++lineno )) + [[ $line = '#'* ]] && comments+=("$line") && continue + [[ $line = +([[:alnum:]])'() {' ]] && IFS='()' read func _ <<< "$line" && [[ $func != $FUNCNAME ]] && { + usage=${comments[3]##'#'+( )} + whatis=${comments[5]##'#'+( )} + [[ $usage = $func* && $whatis = *. ]] || err "Malformed docs for %s (line %d)." "$func" "$lineno" + + printf -v outline '# %s\n# %s\n#\n' "$usage" "$whatis" + out+=$outline + } + comments=() + done < ~/.bin/bashlib + + outhash=$(openssl md5 <<< "$out") + if [[ $_tocHash = "$outhash" ]]; then + inf 'Table of contents up-to-date.' + else + printf '%s' "$out" + printf '_tocHash=%q' "$outhash" + wrn 'Table of contents outdated.' + fi +} @@ -48,25 +180,34 @@ done < <(declare -Fx) # | .:: GLOBAL DECLARATIONS ::. | # |______________________________________________________________________| -# Variables for global internal operation. +# Variables for convenience sequences. bobber=( '.' 'o' 'O' 'o' ) spinner=( '-' \\ '|' '/' ) crosser=( '+' 'x' '+' 'x' ) runner=( '> >' \ '>> ' \ - '>>>' \ ' >>' ) # Variables for terminal requests. -[[ -t 1 ]] && { - hide=$( tput civis || tput vi ) - show=$( tput cvvis || tput vs ) - save=$( tput sc ) - load=$( tput rc ) - bold=$( tput bold || tput md ) - reset=$( tput sgr0 || tput me ) - #blink=$( tput blink || tput mb ) - italic=$( tput sitm || tput ZH ) +[[ -t 2 && $TERM != dumb ]] && { + COLUMNS=$( tput cols || tput co ) # Columns in a line + LINES=$( tput lines || tput li ) # Lines on screen + alt=$( tput smcup || tput ti ) # Start alt display + ealt=$( tput rmcup || tput te ) # End alt display + hide=$( tput civis || tput vi ) # Hide cursor + show=$( tput cnorm || tput ve ) # Show cursor + save=$( tput sc ) # Save cursor + load=$( tput rc ) # Load cursor + dim=$( tput dim || tput mh ) # Start dim + bold=$( tput bold || tput md ) # Start bold + stout=$( tput smso || tput so ) # Start stand-out + estout=$( tput rmso || tput se ) # End stand-out + under=$( tput smul || tput us ) # Start underline + eunder=$( tput rmul || tput ue ) # End underline + reset=$( tput sgr0 || tput me ) # Reset cursor + blink=$( tput blink || tput mb ) # Start blinking + italic=$( tput sitm || tput ZH ) # Start italic + eitalic=$( tput ritm || tput ZR ) # End italic [[ $TERM != *-m ]] && { red=$( tput setaf 1|| tput AF 1 ) green=$( tput setaf 2|| tput AF 2 ) @@ -75,6 +216,7 @@ runner=( '> >' \ magenta=$( tput setaf 5|| tput AF 5 ) cyan=$( tput setaf 6|| tput AF 6 ) } + black=$( tput setaf 0|| tput AF 0 ) white=$( tput setaf 7|| tput AF 7 ) default=$( tput op ) eed=$( tput ed || tput cd ) # Erase to end of display @@ -109,7 +251,7 @@ runner=( '> >' \ # Outputs the character that has the given decimal ASCII value. # chr() { - printf \\"$(printf '%03o' "$1")" + printf "\\$(printf '%03o' "$1")" } # _____________________________________________________________________ @@ -122,7 +264,7 @@ chr() { # Outputs the decimal ASCII value of the given character. # ord() { - printf %d "'$1" + printf '%d' "'$1" } # _____________________________________________________________________ @@ -135,7 +277,7 @@ ord() { # Outputs the hexadecimal ASCII value of the given character. # hex() { - printf '%x' "'$1" + printf '%x' "'$1" } # _____________________________________________________________________ @@ -145,10 +287,71 @@ hex() { # # unhex character # -# Outputs the character that has the given decimal ASCII value. +# Outputs the character that has the given hexadecimal ASCII value. # unhex() { - printf \\x"$1" + printf "\\x$1" +} # _____________________________________________________________________ + + + +# ______________________________________________________________________ +# |__ max _______________________________________________________________| +# +# max numbers... +# +# Outputs the highest of the given numbers. +# +max() { + local max=$1 n + for n; do + (( n > max )) && max=$n + done + printf %d "$max" +} # _____________________________________________________________________ + + + +# ______________________________________________________________________ +# |__ min _______________________________________________________________| +# +# min numbers... +# +# Outputs the lowest of the given numbers. +# +min() { + local min=$1 n + for n; do + (( n < min )) && min=$n + done + printf '%d' "$min" +} # _____________________________________________________________________ + + + +# ______________________________________________________________________ +# |__ totime ____________________________________________________________| +# +# totime "YYYY-MM-DD HH:MM:SS.mmm"... +# +# Outputs the number of milliseconds in the given date string(s). +# +# When multiple date string arguments are given, multiple time strings are output, one per line. +# +# The fields should be in the above defined order. The delimitor between the fields may be any one of [ -:.]. +# If a date string does not follow the defined format, the result is undefined. +# +# Note that this function uses a very simplistic conversion formula which does not take any special calendar +# convenions into account. It assumes there are 12 months in evert year, 31 days in every month, 24 hours +# in every day, 60 minutes in every hour, 60 seconds in every minute and 1000 milliseconds in every second. +# +totime() { + local arg time year month day hour minute second milli + for arg; do + IFS=' -:.' read year month day hour minute second milli <<< "$arg" && + (( time = (((((((((((10#$year * 12) + 10#$month) * 31) + 10#$day) * 24) + 10#$hour) * 60) + 10#$minute) * 60) + 10#$second) * 1000) + 10#$milli )) && + printf '%d\n' "$time" + done } # _____________________________________________________________________ @@ -158,8 +361,7 @@ unhex() { # # exists application # -# Returns successfully if the application is in PATH and is executable -# by the current user. +# Succeeds if the application is in PATH and is executable. # exists() { [[ -x $(type -P "$1" 2>/dev/null) ]] @@ -167,6 +369,22 @@ exists() { +# ______________________________________________________________________ +# |__ FirstExists ____________________________________________________________| +# +# firstExists file... +# +# Outputs the first of the arguments that is a file which exists. +# +firstExists() { + local file; + for file; do + [[ -e "$file" ]] && printf %s "$file" && exit + done +} # _____________________________________________________________________ + + + # ______________________________________________________________________ # |__ Eol _______________________________________________________________| # @@ -180,27 +398,107 @@ eol() { +# ______________________________________________________________________ +# |__ Hr _______________________________________________________________| +# +# hr pattern [length] +# +# Outputs a horizontal ruler of the given length in characters or the terminal column length otherwise. +# The ruler is a repetition of the given pattern string. +# +hr() { + local pattern=${1:--} length=${2:-$COLUMNS} ruler= + + while (( ${#ruler} < length )); do + ruler+=${pattern:0:length-${#ruler}} + done + + printf %s "$ruler" +} # _____________________________________________________________________ + + + # ______________________________________________________________________ # |__ CLoc ______________________________________________________________| # # cloc # -# Outputs the current cursor location as two space-separated numbers: row column +# Outputs the current cursor location as two space-separated numbers: row column. # cloc() { local old=$(stty -g) + trap 'stty "$old"' RETURN stty raw # If the tty has input waiting then we can't read back its response. We'd only break and pollute the tty input buffer. - read -t 0 < /dev/tty 2>/dev/null && { - stty "$old" - return 1 - } + read -t 0 < /dev/tty 2>/dev/null && return 1 printf '\e[6n' > /dev/tty IFS='[;' read -dR _ row col < /dev/tty printf '%d %d' "$row" "$col" - stty "$old" +} # _____________________________________________________________________ + + + +# ______________________________________________________________________ +# |__ readwhile ______________________________________________________________| +# +# readwhile command [args] +# +# Outputs the characters typed by the user into the terminal's input buffer while running the given command. +# +readwhile() { + local old=$(stty -g) in result REPLY + trap 'stty "$old"' RETURN + stty raw + + "$@" + result=$? + + while read -t 0; do + IFS= read -rd '' -n1 && in+=$REPLY + done + printf %s "$in" + + return $result +} # _____________________________________________________________________ + + + +# ___________________________________________________________________________ +# |__ pushqueue ______________________________________________________________| +# +# pushqueue element ... +# +# Pushes the given arguments as elements onto the queue. +# +pushqueue() { + [[ $_queue ]] || { + coproc _queue { + while IFS= read -r -d ''; do + printf '%s\0' "$REPLY" + done + } + } + + printf '%s\0' "$@" >&"${_queue[1]}" +} # _____________________________________________________________________ + + + +# __________________________________________________________________________ +# |__ popqueue ______________________________________________________________| +# +# popqueue +# +# Pops one element off the queue. +# If no elements are available on the queue, this command fails with exit code 1. +# +popqueue() { + local REPLY + [[ $_queue ]] && read -t0 <&"${_queue[0]}" || return + IFS= read -r -d '' <&"${_queue[0]}" + printf %s "$REPLY" } # _____________________________________________________________________ @@ -219,437 +517,325 @@ latest() ( [[ $file -nt $latest ]] && latest=$file done printf '%s\n' "$latest" -) +) # _____________________________________________________________________ + +# _______________________________________________________________________ +# |__ Iterate ____________________________________________________________| +# +# iterate [command] +# +# All arguments to iterate make up a single command that will be executed. +# +# Any of the arguments may be of the format {x..y[..z]} which causes the command +# to be executed in a loop, each iteration substituting the argument for the +# current step the loop has reached from x to y. We step from x to y by +# walking from x's position in the ASCII character table to y's with a step of z +# or 1 if z is not specified. +# +iterate() ( + local command=( "$@" ) iterationCommand=() loop= a= arg= current=() step=() target=() + for a in "${!command[@]}"; do + arg=${command[a]} + if [[ $arg = '{'*'}' ]]; then + loop=${arg#'{'} loop=${loop%'}'} + step[a]=${loop#*..*..} current[a]=${loop%%..*} target[a]=${loop#*..} target[a]=${target[a]%.."${step[a]}"} + [[ ! ${step[a]} || ${step[a]} = $loop ]] && step[a]=1 + fi + done + if (( ${#current[@]} )); then + for loop in "${!current[@]}"; do + while true; do + iterationCommand=() + + for a in "${!command[@]}"; do + (( a == loop )) \ + && iterationCommand+=( "${current[a]}" ) \ + || iterationCommand+=( "${command[a]}" ) + done + + iterate "${iterationCommand[@]}" + + [[ ${current[loop]} = ${target[loop]} ]] && break + current[loop]="$(chr "$(( $(ord "${current[loop]}") + ${step[loop]} ))")" + done + done + else + "${command[@]}" + fi +) # _____________________________________________________________________ + # ______________________________________________________________________ -# |__ Emit ______________________________________________________________| +# |__ Logging ___________________________________________________________| # -# emit [options] message... [-- [command args...]] +# log format [arguments...] # -# Display a message with contextual coloring. +# Log an event at a certain importance level. The event is expressed as a printf(1) format argument. +# The current exit code remains unaffected by the execution of this function. # -# When a command is provided, a spinner will be activated in front of the -# message for as long as the command runs. When the command ends, its -# exit status will result in a message 'done' or 'failed' to be displayed. +# Instead of 'log', you can use a level as command name, to log at that level. Using log, messages are +# logged at level inf. The supported levels are: trc, dbg, inf, wrn, err, ftl. # -# It is possible to only specify -- as final argument. This will prepare -# a spinner for you with the given message but leave it up to you to -# notify the spinner that it needs to stop. See the documentation for -# 'spinner' to learn how to do this. +# If you prefix the command name with a p, the log message is shown as a spinner and waits for the next +# closing statement. Eg. +# +# pinf 'Converting image' +# convert image.png image.jpg +# fnip # -# -n Do not end the line with a newline. -# -b Activate bright (bold) mode. -# -d Activate half-bright (dim) mode. -# -g Display in green. -# -y Display in yellow. -# -r Display in red. -# -w Display in the default color. +# The closing statement (here fnip) is the reverse of the opening statement and exits with the exit code +# of the last command. If the last command failed, it shows the exit code in the spinner before it is stopped. +# The closing statement also takes a format and arguments, which are displayed in the spinner. # -# -[code] A proxy-call to 'spinner -[code]'. -# -# Non-captialized versions of these options affect the * or the spinner -# in front of the message. Capitalized options affect the message text -# displayed. -# -emit() { +log() { + local exitcode=$? level=${level:-inf} supported=0 end=$'\n' type=msg conMsg= logMsg= format= colorFormat= date= info= arg= args=() colorArgs=() ruler= - # Proxy call to spinner. - [[ $# -eq 1 && $1 = -+([0-9]) ]] \ - && { spinner $1; return; } - - # Initialize the vars. - local arg - local style= - local color= - local textstyle= - local textcolor= - local noeol=0 - local cmd=0 - - # Parse the options. - spinArgs=() - for arg in $(getArgs odbwgyrDBWGYRn "$@"); do - case ${arg%% } in - d) style=$dim ;; - b) style=$bold ;; - w) color=$white ;; - g) color=$green ;; - y) color=$yellow ;; - r) color=$red ;; - D) textstyle=$dim ;; - B) textstyle=$bold ;; - W) textcolor=$white ;; - G) textcolor=$green ;; - Y) textcolor=$yellow ;; - R) textcolor=$red ;; - n) noeol=1 - spinArgs+=(-n) ;; - o) spinArgs+=("-$arg") ;; + # Handle options. + local OPTIND=1 + while getopts :tpuPrR:d:n arg; do + case $arg in + p) + end='.. ' + type=startProgress ;; + u) + end='.. ' + type=updateProgress ;; + P) + type=stopProgress ;; + r) + ruler='____' ;; + R) + ruler=$OPTARG ;; + d) + end=$OPTARG ;; + n) + end= ;; + t) + date=$(date +"${_logDate:-%H:%M}") ;; esac done - shift $(getArgs -c odbwgyrDBWGYRn "$@") - while [[ $1 = +* ]]; do - spinArgs+=("-${1#+}") - shift - done + shift "$((OPTIND-1))" + format=$1 args=( "${@:2}" ) + (( ! ${#args[@]} )) && [[ $format ]] && { args=("$format") format=%s; local bold=; } - # Defaults. - color=${color:-$textcolor} - color=${color:-$green} - [[ $color = $textcolor && -z $style ]] && style=$bold + # Level-specific settings. + local logLevelColor + case $level in + TRC) (( supported = _logVerbosity >= 4 )) + logLevelColor=$_logTrcColor ;; + DBG) (( supported = _logVerbosity >= 3 )) + logLevelColor=$_logDbgColor ;; + INF) (( supported = _logVerbosity >= 2 )) + logLevelColor=$_logInfColor ;; + WRN) (( supported = _logVerbosity >= 1 )) + logLevelColor=$_logWrnColor ;; + ERR) (( supported = _logVerbosity >= 0 )) + logLevelColor=$_logErrColor ;; + FTL) (( supported = 1 )) + logLevelColor=$_logFtlColor ;; + *) + log FTL 'Log level %s does not exist' "$level" + exit 1 ;; + esac + (( ! supported )) && return "$exitcode" + local logColor=${_logColor:+$logLevelColor} - # Get the text message. - local text= origtext= - for arg; do [[ $arg = -- ]] && break; origtext+="$arg "; done - origtext=${origtext%% } - (( noeol )) && text=$origtext || text=$origtext$reset$(eol "$origtext")$'\n' + # Generate the log message. + case $type in + msg|startProgress) + printf -v logMsg "[${date:+%s }%-3s] $format$end" ${date:+"$date"} "$level" "${args[@]}" + if (( _logColor )); then + colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$bold$logColor&$reset$logColor/g" <<< "$format") + colorArgs=("${args[@]//$reset/$reset$bold$logColor}") + printf -v conMsg "$reset[${date:+%s }$logColor$bold%-3s$reset] $logColor$colorFormat$reset$black\$$reset$end$save" ${date:+"$date"} "$level" "${colorArgs[@]}" + else + conMsg=$logMsg + fi + ;; - - # Trim off everything up to -- - while [[ $# -gt 1 && $1 != -- ]]; do shift; done - [[ $1 = -- ]] && { shift; cmd=1; } + updateProgress) + printf -v logMsg printf " [$format]" "${args[@]}" + if (( _logColor )); then + colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$bold$logColor&$reset$logColor/g" <<< "$format") + colorArgs=("${args[@]//$reset/$reset$bold$logColor}") + printf -v conMsg "$load$eel$blue$bold[$reset$logColor$colorFormat$reset$blue$bold]$reset$end" "${colorArgs[@]}" + else + conMsg=$logMsg + fi + ;; - # Figure out what FD to use for our messages. - [[ -t 1 ]]; local fd=$(( $? + 1 )) + stopProgress) + case $exitcode in + 0) printf -v logMsg "done${format:+ ($format)}.\n" "${args[@]}" + if (( _logColor )); then + colorFormat=$(sed ${reset:+-e "s/$(requote "$reset")/$reset$logColor/g"} -e "s/%[^a-z]*[a-z]/$reset$bold$logColor&$reset$logColor/g" <<< "$format") + colorArgs=("${args[@]//$reset/$reset$bold$logColor}") + printf -v conMsg "$load$eel$green${bold}done${colorFormat:+ ($reset$logColor$colorFormat$reset$green$bold)}$reset.\n" "${colorArgs[@]}" + else + conMsg=$logMsg + fi + ;; - # Display the message or spinner. - if (( cmd )); then - # Don't let this Bash handle SIGINT. - #trap : INT - - # Create the spinner in the background. - spinPipe=${TMPDIR:-/tmp}/bashlib.$$ - { touch "$spinPipe" && rm -f "$spinPipe" && mkfifo "$spinPipe"; } 2>/dev/null \ - || unset spinPipe - { spinner "${spinArgs[@]}" "$origtext" -- "$style" "$color" "$textstyle" "$textcolor" < "${spinPipe:-/dev/null}" & } 2>/dev/null - [[ $spinPipe ]] && echo > "$spinPipe" - spinPid=$! - - # Execute the command for the spinner if one is given. - #sleep 1 # Let the spinner initialize itself properly first. # Can probably remove this now that we echo > spinPipe? - if (( $# == 1 )); then command=$1 - elif (( $# > 1 )); then command=$(printf '%q ' "$@") - else return 0; fi - - eval "$command" >/dev/null \ - && spinner -0 \ - || spinner -1 - else - # Make reset codes restore the initial font. - local font=$reset$textstyle$textcolor - text=$font${text//$reset/$font} - - printf "\r$reset $style$color* %s$reset" "$text" >&$fd - fi -} # _____________________________________________________________________ - - - -# ______________________________________________________________________ -# |__ Spinner ___________________________________________________________| -# -# spinner message... [-- style color textstyle textcolor] -# or -# spinner -[code] -# -# Displays a spinner on the screen that waits until a certain time. -# Best used through its interface provided by 'emit'. -# -# style A terminal control string that defines the style of the spinner. -# color A terminal control string that defines the color of the spinner. -# textstyle A terminal control string that defines the style of the message. -# textcolor A terminal control string that defines the color of the message. -# -# -[code] Shut down a previously activated spinner with the given exit -# code. If the exit code is 0, a green message 'done' will be -# displayed. Otherwise a red message 'failed' will appear. -# The function will return with this exit code as result. -# -# You can manually specify a previously started spinner by putting its PID in -# the 'spinPid' variable. If this variable is not defined, the PID of the most -# recently backgrounded process is used. The 'spinPid' variable is unset upon -# each call to 'spinner' and reset to the PID of the spinner if one is created. -# -spinner() { - - # Check usage. - (( ! $# )) || getArgs -q :h "$@" && { - emit -y 'Please specify a message as argument or a status option.' - return 1 - } - - # Initialize spinner vars. - # Make sure monitor mode is off or we won't be able to trap INT properly. - local monitor=0; [[ $- = *m* ]] && monitor=1 - local done= - - # Place the trap for interrupt signals. - trap 'done="${red}failed"' USR2 - trap 'done="${green}done"' USR1 - - # Initialize the vars. - local pid=${spinPid:-$!} - local graphics=( "${bobber[@]}" ) - local style=$bold - local color=$green - local textstyle= - local textcolor= - local output= - local noeol= - unset spinPid - - # Any remaining options are the exit status of an existing spinner or spinner type. - while [[ $1 = -* ]]; do - arg=${1#-} - shift - - # Stop parsing when arg is -- - [[ $arg = - ]] && break - - # Process arg: Either a spinner type or result code. - if [[ $arg = *[^0-9]* ]]; then - case $arg in - b) graphics=( "${bobber[@]}" ) ;; - c) graphics=( "${crosser[@]}" ) ;; - r) graphics=( "${runner[@]}" ) ;; - s) graphics=( "${spinner[@]}" ) ;; - o) output=1 ;; - n) noeol=1 ;; + *) info=${format:+$(printf ": $format" "${args[@]}")} + printf -v logMsg "error(%d%s).\n" "$exitcode" "$info" + if (( _logColor )); then + printf -v conMsg "${eel}${red}error${reset}(${bold}${red}%d${reset}%s).\n" "$exitcode" "$info" + else + conMsg=$logMsg + fi + ;; esac - elif [[ $pid ]]; then - [[ $arg = 0 ]] \ - && kill -USR1 $pid 2>/dev/null \ - || kill -USR2 $pid 2>/dev/null - - trap - INT - wait $pid 2>/dev/null + ;; + esac - return $arg - fi - done - - # Read arguments. - local text= origtext= - for arg; do [[ $arg = -- ]] && break; origtext+="$arg "; done - origtext=${origtext% } - local styles=$*; [[ $styles = *' -- '* ]] || styles= - read -a styles <<< "${styles##* -- }" - [[ ${styles[0]} ]] && style=${styles[0]} - [[ ${styles[1]} ]] && color=${styles[1]} - [[ ${styles[2]} ]] && textstyle=${styles[2]} - [[ ${styles[3]} ]] && textcolor=${styles[3]} - - # Figure out what FD to use for our messages. - [[ -t 1 ]]; local fd=$(( $? + 1 )) - - # Make reset codes restore the initial font. - local font=$reset$textstyle$textcolor - origtext=$font${origtext//$reset/$font} - (( noeol )) && text=$origtext || text=$origtext$reset$(eol "$origtext") - - # Spinner initial status. - printf "\r$save$eel$reset $style$color* %s$reset" "$text" >&$fd - (( output )) && printf "\n" >&$fd - - # Render the spinner. - set +m - local i=0 - while [[ ! $done ]]; do - IFS= read -r -d '' newtext || true - newtext=${newtext%%$'\n'}; newtext=${newtext##*$'\n'} - if [[ $newtext = +* ]]; then - newtext="$origtext [${newtext#+}]" - fi - if [[ $newtext ]]; then - newtext="$font${newtext//$reset/$font}" - (( noeol )) && text=$newtext || text=$newtext$reset$(eol "$newtext") - fi - - if (( output )) - then printf "\r" >&$fd - else printf "$load$eel" >&$fd - fi - - if (( output )) - then printf "$reset $style$color$blue%s %s$reset" \ - "${graphics[i++ % 4]}" "$text" >&$fd - else printf "$reset $style$color%s %s$reset" \ - "${graphics[i++ % 4]}" "$text" >&$fd - fi - - sleep .25 # Four iterations make one second. - - # Cancel when calling script disappears. - kill -0 $$ >/dev/null || done="${red}aborted" - done - - # Get rid of the spinner traps. - trap - USR1 USR2; (( monitor )) && set -m - - # Spinner final status. - if (( output )) - then text=; printf "\r" >&$fd - else printf "$load" >&$fd + # Create the log file. + if [[ $_logFile && ! -e $_logFile ]]; then + [[ $_logFile = */* ]] || $_logFile=./$logFile + mkdir -p "${_logFile%/*}" && touch "$_logFile" fi - printf "$eel$reset $style$color* %s${text:+ }$bold%s$font.$reset\n" \ - "$text" "$done" >&$fd -} # _____________________________________________________________________ - - - -# ______________________________________________________________________ -# |__ report ___________________________________________________________| -# -# report [-code] [-e] failure-message [success-message] -# -# This is a convenience function for replacement of spinner -code. -# -# It checks either the exit code of the previously completed command or -# the code provided as option to determine whether to display the success -# or failure message. It calls spinner -code to complete an actively -# emitted message if there is one. The success message is optional. -# -# -[code] The exit code to use. -# -e Exit the script on failure. -# -report() { - - # Exit Status of previous command. - local code=$? - - # Parse the options. - while [[ $1 = -* && $2 ]]; do - arg=${1#-} - shift - - # Stop parsing when arg is -- - [[ $arg = - ]] && break - - # Process arg: Either a spinner type or result code. - if [[ $arg = *[^0-9]* ]]; then - case $arg in - esac - else code=$arg - fi - done - - # Initialize the vars. - local failure=$1 - local success=$2 - - # Check usage. - (( ! $# )) || getArgs -q :h "$@" && { - emit -y 'Please specify at least a failure message as argument.' - return 1 - } - - # Proxy call to spinner. - (( spinPid )) \ - && { spinner -$code; } - - # Success or failure message. - if (( ! code )) - then [[ $success ]] && emit " $success" - else [[ $failure ]] && emit -R " $failure" + # Stop the spinner. + if [[ $type = stopProgress && $_logSpinner ]]; then + kill "$_logSpinner" + wait "$_logSpinner" 2>/dev/null + unset _logSpinner fi - # Pass on exit code. - return $code -} # _____________________________________________________________________ + # Output the ruler. + if [[ $ruler ]]; then + printf >&2 '%s\n' "$(hr "$ruler")" + [[ -w $_logFile ]] \ + && printf >> "$_logFile" '%s' "$ruler" + fi + + # Output the log message. + printf >&2 '%s' "$conMsg" + [[ -w $_logFile ]] \ + && printf >> "$_logFile" '%s' "$logMsg" + + # Start the spinner. + if [[ $type = startProgress && ! $_logSpinner ]]; then + { + set +m + trap 'printf %s "$show"' EXIT + printf %s "$hide" + while printf "$eel$blue$bold[$reset%s$reset$blue$bold]$reset\b\b\b" "${spinner[s++ % ${#spinner[@]}]}" && sleep .1 + do :; done + } & _logSpinner=$! + fi 2>/dev/null + + return $exitcode +} +trc() { level=TRC log "$@"; } +dbg() { level=DBG log "$@"; } +inf() { level=INF log "$@"; } +wrn() { level=WRN log "$@"; } +err() { level=ERR log "$@"; } +ftl() { level=FTL log "$@"; } +plog() { log -p "$@"; } +ulog() { log -u "$@"; } +golp() { log -P "$@"; } +ptrc() { level=TRC plog "$@"; } +pdbg() { level=DBG plog "$@"; } +pinf() { level=INF plog "$@"; } +pwrn() { level=WRN plog "$@"; } +perr() { level=ERR plog "$@"; } +pftl() { level=FTL plog "$@"; } +utrc() { level=TRC ulog "$@"; } +udbg() { level=DBG ulog "$@"; } +uinf() { level=INF ulog "$@"; } +uwrn() { level=WRN ulog "$@"; } +uerr() { level=ERR ulog "$@"; } +uftl() { level=FTL ulog "$@"; } +gtrc() { level=trc golp "$@"; } +gbdp() { level=DBG golp "$@"; } +fnip() { level=INF golp "$@"; } +nrwp() { level=WRN golp "$@"; } +rrep() { level=ERR golp "$@"; } +ltfp() { level=FTL golp "$@"; } +_logColor=${_logColor:-$([[ -t 2 ]] && echo 1)} _logVerbosity=2 +_logTrcColor=$grey _logDbgColor=$blue _logInfColor=$white _logWrnColor=$yellow _logErrColor=$red _logFtlColor=$bold$red +# _______________________________________________________________________ # ______________________________________________________________________ # |__ Ask _______________________________________________________________| # -# ask [-optionchars|+default] message... +# ask [-c optionchars|-d default] [-s|-S maskchar] format [arguments...] # -# Ask a question and read the user's reply to it. +# Ask a question and read the user's reply to it. Then output the result on stdout. # -# By default, a reply is terminated by a newline. -# -# You may use the options to switch into key mode. In key mode, only a -# single character is read. The valid characters are specified in the -# optionchars. A capital option character makes that option the default. -# -# If the reply character in key mode was not amoungst the provided options -# the default is assumed instead. If no default was given, an exit code -# of 2 is returned. +# When in normal mode, a single line is read. If the line is empty and +# -d was specified, the default argument is output instead of an empty line. +# The exit code is always 0. # +# When in option mode (-c), the user is shown the option characters with +# which he can reply and a single character is read. +# If the reply is empty (user hits enter) and any of the optionchars are +# upper-case, the upper-case option (= the default option) character will +# be output instead of an empty line. +# If the reply character is not amoungst the provided options the default +# option is again output instead if present. If no default was given, an +# exit code of 2 is returned. # You may mark an optionchar as 'valid' by appending a '!' to it. As a # result, an exit code of 0 will only be returned if this valid option # is replied. If not, an exit code of 1 will be returned. # -# If no option is marked as valid, the given reply is echoed and an exit -# code of 0 is returned. -# -# You can specify the -# option to make ask hide the user's input. -# -# If you prefix the first argument with a + instead of a -, the remaining -# argument is taken as the default string value and returned when no input -# was received. In this case, the exit code is 0 either way. -# ask() { - # Check usage. - (( ! $# )) || getArgs -q :h "$@" && { - emit -y 'Please specify a question as argument.' - return 1 - } - # Initialize the vars. - local arg + local opt arg local option= local options= local default= local silent= local valid= local muteChar= + local format= # Parse the options. - if [[ $1 = +* ]]; then - option=${1#+} - default=$option + local OPTIND=1 + while getopts :sS:c:d: opt; do + case $opt in + s) silent=1 ;; + S) silent=1 muteChar=$OPTARG ;; + c) while read -n1 arg; do + case $arg in + [[:upper:]]) default=$arg ;; + !) valid=${options: -1}; continue ;; + esac - shift - else - for arg in $(getArgs "$(printf "%s" {a..z} {A..Z})!#%" "$@"); do - [[ $arg = [[:upper:]] ]] \ - && default=$arg - [[ $arg = ! ]] \ - && { valid=${options: -1}; continue; } - [[ $arg = '#' ]] \ - && { silent=1 arg=; } - [[ $arg = '%' ]] \ - && { silent=1 muteChar='*' arg=; } - - options+=$arg - done - fi + options+=$arg + done <<< "$OPTARG" ;; + d) default=$OPTARG option=$default ;; + esac + done # Trim off the options. - while [[ $1 = -* ]]; do shift; done + shift $((OPTIND-1)) # Figure out what FD to use for our messages. - [[ -t 1 ]]; local fd=$(( $? + 1 )) + [[ -t 1 ]] && local fd=1 || local fd=2 # Ask the question. - emit -yn "$*${option:+ [$option]}${options:+ [$options]} " + format=$1; shift + level=${level:-WRN} log -n "$format${option:+ [%s]}${options:+ [%s]}" "$@" ${option:+"$option"} ${options:+"$options"} # Read the reply. + exec 8<&0; [[ -t 8 ]] || exec 8&$fd + printf '%s' "$muteChar" >&$fd done REPLY=$reply else - read ${options:+-n1} ${silent:+-s} + read -u8 -e ${options:+-n1} ${silent:+-s} fi - [[ $options && $REPLY ]] || (( silent )) && printf "\n" >&$fd + [[ $options && $REPLY ]] || (( silent )) && printf '\n' >&$fd # Evaluate the reply. while true; do @@ -682,25 +868,8 @@ ask() { # When no arguments are given, lines will be read from standard input. # trim() { - - # Initialize the vars. - local lines - local line - local oIFS - - # Get the lines. - lines=( "$@" ) - if (( ! ${#lines[@]} )); then - oIFS=$IFS; IFS=$'\n' - lines=( $(cat) ) - IFS=$oIFS - fi - - # Trim the lines - for line in "${lines[@]}"; do - line=${line##*([[:space:]])}; line=${line%%*([[:space:]])} - printf "%s" "$line" - done + { (( $# )) && printf '%s\n' "$@" || cat; } | \ + sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' } # _____________________________________________________________________ @@ -708,32 +877,37 @@ trim() { # ______________________________________________________________________ # |__ Reverse ___________________________________________________________| # -# reverse [-0] [elements ...] [<<< elements] +# reverse [-0|-d delimitor] [elements ...] [<<< elements] # -# Reverse the order of the given elements. Elements are read from command -# arguments or standard input if no element arguments are given. +# Reverse the order of the given elements. +# Elements are read from command arguments or standard input if no element +# arguments are given. # They are reversed and output on standard output. # # If the -0 option is given, input and output are delimited by NUL bytes. +# If the -d option is given, input and output are delimited by the +# character argument. # Otherwise, they are delimited by newlines. # reverse() { # Initialize the vars. - local elements delimitor=$'\n' + local elements=() delimitor=$'\n' i # Parse the options. - while [[ $1 = -* ]]; do - case $1 in - -0) delimitor=$'\0' ;; - --) shift; break ;; + local OPTIND=1 + while getopts :0d: opt; do + case $opt in + 0) delimitor=$'\0' ;; + d) delimitor=$OPTARG ;; esac - shift done + shift "$((OPTIND-1))" # Get the elements. - elements=( "$@" ) - if (( ! ${#elements[@]} )); then + if (( $# )); then + elements=( "$@" ) + else while IFS= read -r -d "$delimitor"; do elements+=("$REPLY") done @@ -741,119 +915,276 @@ reverse() { # Iterate in reverse order. for (( i=${#elements[@]} - 1; i >=0; --i )); do - printf '%s%s' "${elements[i]}" "$delimitor" + printf "%s${delimitor:-'\0'}" "${elements[i]}" done } # _____________________________________________________________________ # ______________________________________________________________________ -# |__ SWait _____________________________________________________________| +# |__ Order _____________________________________________________________| # -# swait pid... +# order [-0|-d char] [-[fF] isDesired] [-[cC] isAscending|-n|-r|-t] [-T number] [-a array|elements ...] [<<< elements] # -# Wait for the given PID(s). The PID does not need to be a child of the -# running shell. Note that relying on PIDs always introduces race conditions -# which may be potentially harmful and sometimes even a security issue. +# Orders the elements in ascending order. +# Elements are read from command arguments or standard input if no element +# arguments are given. +# The result is output on standard output. # -# This implementation requires the necessary permissions to send signals -# to the PID(s) provided. +# By default, the elements will be ordered using lexicographic comparison. +# If the -n option is given, the elements will be ordered numerically. +# If the -r option is given, the elements will be ordered randomly. +# If the -f option is given, the command name following it will be used +# as a filter. +# If the -c option is given, the command name following it will be used +# as a comparator. +# If the -C option is given, the bash code following it will be used +# as a comparator. +# If the -t option is given, only the first number results are returned. +# If the -a option is given, the elements in array are ordered instead and +# array is mutated to contain the result. +# If number is 0, all results are returned. # -swait() { - - # Check usage. - (( ! $# )) || getArgs -q :h "$@" && { - emit -y 'Please provide one or more PIDs to wait for as argument.' - return 1 - } - - # Time to wait. - local pid - for pid; do - while kill -0 $pid 2>/dev/null - do sleep .1; done - done -} # _____________________________________________________________________ - - - -# ______________________________________________________________________ -# |__ GetArgs ___________________________________________________________| +# isDesired is a command name which will get one parameter. The parameter +# is an element which will only be included if the command exits successfully. +# isAscending is a command name which will be executed for each element +# comparison and will be passed two element arguments. The command should +# succeed if the first argument is less than the second argument for the +# purpose of this sort. # -# getArgs [options] optstring [args...] +# If the -0 option is given, input and output are delimited by NUL bytes. +# If the -d option is given, input and output are delimited by the +# character argument. +# Otherwise, they are delimited by newlines. # -# Retrieve all options present in the given arguments. +# The ordering is implemented by an insertion sort algorithm. # -# This is a wrapper for getopts(P) which will safely work inside functions. -# It manages OPTIND for you and returns a list of options found in the -# provided arguments. -# -# optstring This is a string of characters in which each character -# represents an option to look for in the arguments. -# See getopts(P) for a description of the optstring syntax. -# -# args This is a list of arguments in which to look for options. -# Most commonly, you will use "$@" to supply these arguments. -# -# -c Instead of output the arguments, output OPTARGS. -# -q Be quiet. No arguments are displayed. Only the exit code is set. -# -n Use newlines as a separator between the options that were found. -# -0 Use NULL-bytes as a separator between the options that were found. -# -# If any given arguments are found, an exit code of 0 is returned. If none -# are found, an exit code of 1 is returned. -# -# After the operation, OPTARGS is set the the index of the last argument -# that has been parsed by getArgs. Ready for you to use shift $OPTARGS. -# -getArgs() { - - # Check usage. - (( ! $# )) && { - emit -y 'Please provide the arguments to search for in' \ - 'getopts(P) format followed by the positional parameters.' - return 1 - } - - # Initialize the defaults. - local arg - local found=0 - local quiet=0 - local count=0 - local delimitor=' ' +order() { + + # Initialize the vars. + local delimitor=$'\n' i isDesired=true isAscending=string_ascends top=0 arrayName= array= # Parse the options. - while [[ $1 = -* ]]; do - case $1 in - -q) quiet=1 ;; - -c) count=1 ;; - -n) delimitor=$'\n' ;; - -0) delimitor=$'\0' ;; + local OPTIND=1 + while getopts :0nrd:f:F:c:C:tT:a: opt; do + case $opt in + 0) delimitor=$'\0' ;; + d) delimitor=$OPTARG ;; + n) isAscending=number_ascends ;; + r) isAscending=random_ascends ;; + t) isAscending=mtime_ascends ;; + f) isDesired=$OPTARG ;; + F) isDesired=bash_desired bash_desired_code=$OPTARG ;; + c) isAscending=$OPTARG ;; + C) isAscending=bash_ascends bash_ascends_code=$OPTARG ;; + T) top=$OPTARG ;; + a) arrayName=$OPTARG array=$arrayName[@] ;; esac - shift + done + shift "$((OPTIND-1))" + + # Get the elements. + local elements=() element + if [[ $arrayName ]]; then + for element in "${!array}"; do + "$isDesired" "$element" && elements+=("$element") + done + elif (( $# )); then + for element; do + "$isDesired" "$element" && elements+=("$element") + done + else + while IFS= read -r -d "$delimitor" element; do + "$isDesired" "$element" && elements+=("$element") + done + fi + + # Iterate in reverse order. + for (( i = 1; i < ${#elements[@]}; ++i )); do + for (( j = i; j > 0; --j )); do + element=${elements[j]} + if "$isAscending" "$element" "${elements[j-1]}"; then + elements[j]=${elements[j-1]} + elements[j-1]=$element + fi + done done - # Get the optstring. - local optstring=$1; shift - local oOPTIND=$OPTIND OPTIND=1 + (( top )) || top=${#elements[@]} + if [[ $array ]]; then + declare -ga "$array=($(printf '%q ' "${elements[@]:0:top}"))" + else + printf "%s${delimitor:-\0}" "${elements[@]:0:top}" + fi +} # _____________________________________________________________________ +string_ascends() { [[ $1 < $2 ]]; } +number_ascends() { (( $1 < $2 )); } +random_ascends() { (( RANDOM % 2 )); } +mtime_ascends() { [[ $1 -ot $2 ]]; } +exists_desired() { [[ -e $1 ]]; } +line_desired() { [[ $1 ]]; } +code_desired() { line_desired "$1" && ! comment_desired "$1"; } +comment_desired() { line_desired "$1" && [[ $1 = @(#|//|/\*)* ]]; } +bash_desired() { bash -c "$bash_desired_code" -- "$@"; } +bash_ascends() { bash -c "$bash_ascends_code" -- "$@"; } - # Enumerate the arguments. - while getopts "$optstring" arg; do - [[ $arg != '?' ]] && found=1 - (( quiet + count )) || \ - printf "%s${OPTARG:+ }%s%s" "$arg" "$OPTARG" "$delimitor" +# ______________________________________________________________________ +# |__ Mutex _____________________________________________________________| +# +# mutex file +# +# Open a mutual exclusion lock on the file, unless another process already owns one. +# +# If the file is already locked by another process, the operation fails. +# This function defines a lock on a file as having a file descriptor open to the file. +# This function uses FD 9 to open a lock on the file. To release the lock, close FD 9: +# exec 9>&- +# +mutex() { + local lockfile=${1:-${BASH_SOURCE[-1]}} pid pids + [[ -e $lockfile ]] || err "No such file: $lockfile" || return + + exec 9>> "$lockfile" && [[ $({ fuser -f "$lockfile"; } 2>&- 9>&-) == $$ ]] +} + + +# ______________________________________________________________________ +# |__ PushJob ___________________________________________________________| +# +# pushjob [poolsize] command +# +# Start an asynchronous command within a pool, waiting for space in the pool if it is full. +# +# The pool is pruned automatically as running jobs complete. This function +# allows you to easily run asynchronous commands within a pool of N, +# automatically starting the next command as soon as there's space. +# +pushjob() { + local size=$1; shift 1 + + # Wait for space in the pool. + until (( ${#jobpool[@]} < size )); do + sleep 1 & pushjobsleep=$! + wait "$pushjobsleep" + done 2>/dev/null + + # Register prunejobs and start the pushed job. + trap _prunejobs SIGCHLD + set -m + "$@" & jobpool[$!]= +} +_prunejobs() { + # Prune all pool jobs that are no longer running. + for pid in "${!jobpool[@]}"; do + kill -0 "$pid" 2>/dev/null || unset "jobpool[$pid]" done - OPTARGS=$(( OPTIND - 1 )) - OPTIND=$oOPTIND - # Any arguments found? - (( count )) && printf "%s" "$OPTARGS" - return $(( ! found )) + # Unregister SIGCHLD if our pool is empty. + (( ${#jobpool[@]} )) || trap - SIGCHLD + + # Wake up pushjob. + kill "$pushjobsleep" 2>/dev/null +} + + + + +# ______________________________________________________________________ +# |__ FSleep _____________________________________________________________| +# +# fsleep time +# +# Wait for the given (fractional) amount of seconds. +# +# This implementation solves the problem portably, assuming that either +# bash 4.x or a fractional sleep(1) is available. +# +fsleep() { + + local fifo=${TMPDIR:-/tmp}/.fsleep.$$ + trap 'rm -f "$fifo"' RETURN + mkfifo "$fifo" && { read -t "$1" <> "$fifo" 2>/dev/null || sleep "$1"; } } # _____________________________________________________________________ +# ______________________________________________________________________ +# |__ options ___________________________________________________________| +# +# options [option description]... +# +# Specify and handle options in arguments. +# +# The 'setopt' function will be called for each option expected option +# passed to the script, with $1 set to the option character and $2 +# its description. Check OPTARG if the option takes an argument. +# 'setopt' will be called with '?' if an invalid option is passed. +# +# Unless specified, the -h option will show a usage description, +# explaining the options. +# +# Proposed usage: +# setopt() { +# case "$1" in +# a) echo "got option a" ;; +# b) echo "got option b with argument $OPTARG" ;; +# esac +# } +# options \ +# a 'option a' \ +# b: 'option b with argument' +# +options() { + + # Parse the expected options and their description. + declare -A options=() + while (( $# )); do + local optchar=$1 optdesc=$2 + shift 2 || ftl 'Missing arguments, expected option (%s), description (%s).' "$optchar" "$optdesc" || exit + options[$optchar]=$optdesc + done + + # Find the script's options. + local argc=${BASH_ARGC[@]: -1} argv=("${BASH_ARGV[@]: -argc}") arg + local optstring=$(printf %s "${!options[@]}")h + set -- # Sigh. BASH_ARGV is all backwards. + for arg in "${argv[@]}"; do + set -- "$arg" "$@" + done + + # Handle the script's options. + while getopts "$optstring" arg; do + if [[ $arg = h && ! ${options[h]} ]]; then + # Show usage message. + [[ -t 1 ]]; local fd=$(( $? + 1 )) optarg + + # Print out the app usage. + printf " Usage: $reset$bold%s$reset" "${BASH_SOURCE[1]##*/}" >&$fd + for optchar in "${!options[@]}"; do + [[ $optchar = *: ]] && optarg=" arg" || optarg= + printf " [$bold$green-%s$reset%s]" "${optchar%:}" "$optarg" >&$fd + done + printf "\n\n" >&$fd + + # Print out the option descriptions. + for optchar in "${!options[@]}"; do + local optdesc=${options[$optchar]} + [[ $optchar = *: ]] && optarg=" arg" || optarg= + printf " $bold$green-%s$reset%s\t" "${optchar%:}" "$optarg" + fmt -w "$COLUMNS" <<< "${optdesc//+( )/ }" | sed $'1!s/^/ \t/' + printf "\n" + done | column -t -s $'\t' >&$fd + else + optchar=$arg; [[ ! ${options[$arg]} && ${options[$arg:]} ]] && optchar=$arg: + setopt "$arg" "${options[$arg]}" + fi + done +} # _____________________________________________________________________ + + + +# ______________________________________________________________________ # |__ ShowHelp __________________________________________________________| # # showHelp name description author [option description]... @@ -871,13 +1202,6 @@ getArgs() { # showHelp() { - # Check usage. - (( $# < 3 )) || getArgs -q :h "$@" && { - emit -y 'Please provide the name, description, author and options' \ - 'of the application.' - return 1 - } - # Parse the options. local appName=$1; shift local appDesc=${1//+([[:space:]])/ }; shift @@ -913,26 +1237,29 @@ showHelp() { # ______________________________________________________________________ # |__ Quote _____________________________________________________________| # -# quote [-e] [argument...] +# shquote [-e] [argument...] # -# Output a single string where all arguments are quoted -# such that the string is safe to be passed as shell -# command arguments as though given arguments had been -# passed. -# -# When no arguments are passed; no output is generated. +# Shell-quote the arguments to make them safe for injection into bash code. +# +# The result is bash code that represents a series of words, where each +# word is a literal string argument. By default, quoting happens using +# single-quotes. # # -e Use backslashes rather than single quotes. +# -d Use double-quotes rather than single quotes (does NOT disable expansions!). +# -a Normally, shquote doesn't quote arguments that don't need it. This forces all arguments to be quoted. # -quote() { +shquote() { # Initialize the defaults. - local arg escape=0 quotedArgs=() + local arg escape=0 sq="'\\''" dq='\"' quotedArgs=() type=single always=0 # Parse the options. while [[ $1 = -* ]]; do case $1 in - -e) escape=1 ;; + -e) type=escape ;; + -d) type=double ;; + -a) always=1 ;; --) shift; break ;; esac shift @@ -940,11 +1267,18 @@ quote() { # Print out each argument, quoting it properly. for arg; do - if (( escape )); then - quotedArgs+=("$(printf "%q" "$arg")") - else - quotedArgs+=("$(printf "'%s'" "${arg//"'"/"\\'"}")") - fi + (( ! always )) && [[ $arg = "$(printf %q "$arg")" ]] && quotedArgs+=("$arg") && continue + + case "$type" in + escape) + quotedArgs+=("$(printf "%q" "$arg")") ;; + single) + arg=${arg//"'"/$sq} + quotedArgs+=("$(printf "'%s'" "$arg")") ;; + double) + arg=${arg//'"'/$dq} + quotedArgs+=("$(printf '"%s"' "$arg")") ;; + esac done printf '%s\n' "$(IFS=' '; echo "${quotedArgs[*]}")" @@ -952,13 +1286,36 @@ quote() { +# ______________________________________________________________________ +# |__ ReQuote __________________________________________________________| +# +# requote [string] +# +# Escape the argument string to make it safe for injection into a regex. +# +# The result is a regular expression that matches the literal argument +# string. +# +requote() { + + # Initialize the defaults. + local char + + printf '%s' "$1" | while IFS= read -r -d '' -n1 char; do + printf '[%s]' "$char" + done +} # _____________________________________________________________________ + + + # ______________________________________________________________________ # |__ Shorten ___________________________________________________________| # # shorten [-p pwd] path [suffix]... # -# Shorten an absolute path for pretty printing by cutting -# off PWD and replacing HOME by ~. +# Shorten an absolute path for pretty printing. +# Paths are shortened by replacing the homedir by ~, making it relative and +# cutting off given suffixes from the end. # # -p Use the given pathname as the base for relative filenames instead of PWD. # path The path string to shorten. @@ -967,12 +1324,6 @@ quote() { # shorten() { - # Check usage. - (( $# < 1 )) || getArgs -q :h "$@" && { - emit -y 'Please provide the path to shorten.' - return 1 - } - # Parse the options. local suffix path pwd=$PWD [[ $1 = -p ]] && { pwd=$2; shift 2; } @@ -1001,8 +1352,8 @@ shorten() { fi # Replace special paths. - path=${path#$pwd/} path=${path/#$HOME/'~'} + path=${path#$pwd/} # Cut off suffix. for suffix; do @@ -1017,6 +1368,63 @@ shorten() { +# ______________________________________________________________________ +# |__ Up ________________________________________________________________| +# +# up .../path|num +# +# Walk the current working directory up towards root num times or until path is found. +# +# Returns 0 if the destination was reached or 1 if we hit root. +# +# Prints PWD on stdout on success. +# +up() { + local up=0 + until [[ $PWD = / ]]; do + cd ../ + + if [[ $1 = .../* ]]; then + [[ -e ${1#.../} ]] && pwd && return + elif (( ++up == $1 )); then + pwd && return + fi + done +} # _____________________________________________________________________ + + + +# ______________________________________________________________________ +# |__ BuildArray ________________________________________________________| +# +# buildarray name terms... -- elements... +# +# Create an array by adding all the terms to it for each element, replacing {} terms by the element. +# +# name The name of the array to put the result into. +# terms The values to add to the array for each of the elements. A {} term is replaced by the current element. +# elements The elements to iterate the terms for. +# +buildarray() { + local target=$1 term terms=() element value + shift + + while [[ $1 != -- ]]; do + terms+=("$1") + shift + done + shift + + for element; do + for term in "${terms[@]}"; do + [[ $term = {} ]] && value="$element" || value="$term" + declare -ag "$target+=($(printf '%q' "$value"))" + done + done +} # _____________________________________________________________________ + + + # ______________________________________________________________________ # |__ InArray ___________________________________________________________| # @@ -1029,13 +1437,6 @@ shorten() { # inArray() { - # Check usage. - (( $# < 1 )) || getArgs -q :h "$@" && { - emit -y 'Please provide the element to search for and the array' \ - 'to search through.' - return 1 - } - # Parse the options. local element local search=$1; shift @@ -1048,45 +1449,17 @@ inArray() { -# ______________________________________________________________________ -# |__ xpathNodes ________________________________________________________| -# -# xpathNodes query [filename] -# -# Outputs every xpath node that matches the query on a separate line. -# Leading and trailing whitespace is always stripped. -# -# filename The path to the file that contains the document to run the query on. -# query The XPath query to run on the document. -# -xpathNodes() { - local query=$1 filename=$2 - [[ $filename ]] || filename=<(cat) - - { - if xpath -e / <(echo '') >/dev/null 2>&1; then - xpath -e "$query" "$filename" 2>&1 - else - xpath "$filename" "$query" 2>&1 - fi - } | { - read - sed -ne $'s/-- NODE --/\\\n/g' -e 's/^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$/\1/p' - } - - return "${PIPESTATUS[0]}" -} - - - # ______________________________________________________________________ # |__ HideDebug _________________________________________________________| # -# hideDebug [ on | off ] +# hideDebug [on|off] # -# Toggle Bash's debugging mode off temporarily. To hide Bash's debugging -# output for a function, you should have a hideDebug on as its first line -# and hideDebug off as its last. +# Toggle Bash's debugging mode off temporarily. +# To hide Bash's debugging output for a function, you should have +# hideDebug on +# as its first line, and +# hideDebug off +# as its last. # hideDebug() { @@ -1101,49 +1474,110 @@ hideDebug() { fi } + + +# ______________________________________________________________________ +# |__ anfunc ____________________________________________________________| +# +# anfunc [on|off] +# +# Turn on or off support for annonymous functions. +# +# WARNING: This is a hack. It turns on extdebug and causes any argument +# that matches (){code} to be replaced by a function name that if invoked +# runs code. +# +# eg. +# confirm '(){ rm "$1" }' *.txt +# # In this example, confirm() could be a function that asks confirmation +# # for each argument past the first and runs the anfunc in the first +# # argument on each confirmed argument. +# +# Don't use this. It is an academic experiment and has bugs. +# +# Bugs: +# - commands lose their exit code. +# To inhibit the real command from running, we use extdebug and +# a DEBUG trap that returns non-0. As a result, the actual return +# code is lost. +# +anfunc() { + case "$1" in + on) + shopt -s extdebug + trap _anfunc_trap DEBUG + ;; + off) + trap - DEBUG + shopt -u extdebug + ;; + esac +} +_anfunc_trap() { + local f w + + # Perform the command parsing and handling up to its word splitting. + # This includes command substitution, quote handling, pathname expansion, etc. + declare -a words="($BASH_COMMAND)" + + # Iterate the words to run in the final stage, and handle anfunc matches. + for ((w=0; w<${#words[@]}; ++w)); do + [[ ${words[w]} = '(){'*'}' ]] && + # Declare a new function for this anfunc. + eval "_f$((++f))${words[w]}" && + # Replace the word by the new function's name. + words[w]="_f$f" + done + + # Run the command. + eval "$(printf '%q ' "${words[@]}")" + + # Clean up the anfuncs. + for ((; f>0; --f)); do + unset -f "_f$f" + done + + # Inhibit the real command's execution. + return 1 +} + + + # ______________________________________________________________________ # |__ StackTrace ________________________________________________________| # # stackTrace # -# Retrieve a mapping of a key from the given map or modify the given map by -# assigning a new value for the given key if stdin is not the terminal. +# Output the current script's function execution stack. # stackTrace() { - # Some general debug information. - printf "\t$bold%s$reset v$bold%s$reset" "$BASH" "$BASH_VERSION\n" - printf " Was running: $bold%s %s$reset" "$BASH_COMMAND" "$*\n" - printf "\n" - printf " [Shell : $bold%15s$reset] [Subshells : $bold%5s$reset]\n" "$SHLVL" "$BASH_SUBSHELL" - printf " [Locale : $bold%15s$reset] [Runtime : $bold%5s$reset]\n" "$LC_ALL" "${SECONDS}s" - printf "\n" + wrn " [PID : %15s] [PPID : %8s] [Main PID : %8s]" "$BASHPID" "$PPID" "$$" + wrn " [Level : %15s] [Subshells : %8s] [Runtime : %7ss]" "$SHLVL" "$BASH_SUBSHELL" "$SECONDS" + wrn " [Locale : %15s] [IFS : %8s]" "${LC_ALL:-${LC_COLLATE:-${LANG:-C}}}" "$(printf %q "$IFS")" + wrn " Dir Stack : %s" "${DIRSTACK[*]}" + wrn " Shell : %s v%s" "$BASH" "$BASH_VERSION" + wrn " Shell Opts : %s" "${SHELLOPTS//:/, }" + wrn " Bash Opts : %s" "${BASHOPTS//:/, }" + wrn " Functions :" + # Search through the map. - local arg=0 - for i in ${!FUNCNAME[@]}; do - #if (( i )); then + local arg=0 + for stack in "${!FUNCNAME[@]}"; do + (( stack+1 >= ${#BASH_SOURCE[@]} )) && break - # Print this execution stack's location. - printf "$reset $bold-$reset $green" - [[ ${BASH_SOURCE[i+1]} ]] \ - && printf "%s$reset:$green$bold%s" "${BASH_SOURCE[i+1]}" "${BASH_LINENO[i]}" \ - || printf "${bold}Prompt" - - # Print this execution stack's function and positional parameters. - printf "$reset :\t$bold%s(" "${FUNCNAME[i]}" - [[ ${BASH_ARGC[i]} ]] && \ - for (( j = 0; j < ${BASH_ARGC[i]}; j++ )); do - (( j )) && printf ', ' - printf "%s" "${BASH_ARGV[arg]}" - let arg++ - done - - # Print the end of this execution stack's line. - printf ")$reset\n" - #fi + func=${FUNCNAME[stack]} + line=${BASH_LINENO[stack]} + file=${BASH_SOURCE[stack+1]} + args=() + for (( arg=0, s=0; s <= stack; ++s )); do + for (( sarg=0; sarg < ${BASH_ARGC[s]:-0}; ++sarg, ++arg )); do + (( s == stack )) && args[${BASH_ARGC[s]} - sarg]=${BASH_ARGV[arg]} + done + done + wrn '%40s:%-3d | %s %s' "$file" "$line" "$func" "$(printf '%s ' "$(shquote "${args[@]}")")" done - printf "\n" } # _____________________________________________________________________ @@ -1157,9 +1591,19 @@ stackTrace() { # |______________________________________________________________________| # Make sure this file is sourced and not executed. -(( ! BASH_LINENO )) && { - emit -R "You should source this file, not execute it." - exit 1 +( return 2>/dev/null ) || { + help=$(sed -n '1,/_tocHash=/{ /^#/p; }' "$BASH_SOURCE") + if [[ $1 ]]; then + while [[ $1 ]]; do + awk "p && !/^# *[^ ]/ {exit} + p || /^# $1/ {print; p=1}" <<< "$help" + shift + done + else + echo "$help" + echo + echo "To use bashlib, copy it into your PATH and put ''source bashlib'' at the top of your script." + fi } : diff --git a/Scripts/genassets b/Scripts/genassets new file mode 100755 index 00000000..78e05037 --- /dev/null +++ b/Scripts/genassets @@ -0,0 +1,151 @@ +#!/usr/bin/env bash +# See https://developer.apple.com/library/ios/qa/qa1686/_index.html +source bashlib + +# icons format: [pixel size]@[scale]@[idiom]@[os]:[filename] -- if os is "anything lower", omit it +icons=( + 180@3@iphone@8.0:Icon-60@3x.png + 120@3@iphone@8.0:Icon-Small-40@3x.png + 120@2@iphone@7.0:Icon-60@2x.png + 80@2@iphone@7.0:Icon-Small-40@2x.png +# 114@2@iphone@:Icon@2x.png + 87@3@iphone@:Icon-Small@3x.png + 58@2@iphone@:Icon-Small@2x.png +# 57@1@iphone@:Icon.png +# 29@1@iphone@:Icon-Small.png +# + 76@1@ipad@7.0:Icon-76.png + 152@2@ipad@7.0:Icon-76@2x.png + 40@1@ipad@7.0:Icon-Small-40.png + 80@2@ipad@7.0:Icon-Small-40@2x.png + 29@1@ipad@:Icon-Small.png + 58@2@ipad@:Icon-Small@2x.png +# 72@1@ipad@:Icon-72.png +# 144@2@ipad@:Icon-72@2x.png +# 50@1@ipad@:Icon-Small-50.png +# 100@2@ipad@:Icon-Small-50@2x.png +) +# splashes format: [size name]@[scale]@[idiom]@[os] -- if scale is 1, omit it. if os is "anything lower", omit it +splashes=( + 414-736@3@iphone@8.0 + 375-667@2@iphone@8.0 + 320-568@2@iphone@7.0 + 320-568@2@iphone@ + 320-480@2@iphone@7.0 + 320-480@2@iphone@ + 320-480@@iphone@ +) + +copyImage() { + local src=$1 dst=$2 + + if [[ $src = *.9.png || $src = *.9@*.png ]]; then + pinf '%s -> %s (ninepatch)' "${src##*/}" "${dst##*/}" + niftyNinePatch=$(java -Dapple.awt.UIElement=true -jar Scripts/NiftyNinePatchHelper.jar "$src" "$dst") || return + while IFS='=' read var value; do + [[ $var = imageMode ]] && value=${value#'"resize:'} value=${value%'"'} && IFS=, read capLeft capWidth capRight capTop _ _ _ capHeight _ _ _ capBottom <<< "$value" + [[ $var = padding ]] && IFS=, read paddingTop paddingRight paddingBottom paddingLeft <<< "${value//[px\"]}" + uinf 'caps: [%d, %d, %d, %d], padding: [%d, %d, %d, %d]' "$capTop" "$capRight" "$capBottom" "$capLeft" "$paddingTop" "$paddingRight" "$paddingBottom" "$paddingLeft" + printf ',"resizing":{"capInsets":{"bottom":%d,"left":%d,"right":%d,"top":%d},"center":{"height":%d,"mode":"fill","width":%d},"mode":"9-part"}' \ + "$capBottom" "$capLeft" "$capRight" "$capTop" "$capHeight" "$capWidth" + done <<< "$niftyNinePatch" + fnip + else + pinf '%s -> %s' "${src##*/}" "${dst##*/}" + cp "$src" "$dst" + fnip + fi +} + +xcassets=MasterPassword/Resources/Media/Images.xcassets +appiconset="$xcassets/AppIcon.appiconset" +launchimage="$xcassets/LaunchImage.launchimage" +ios_icon=MasterPassword/Resources/Media/ios/icon +ios_launch=MasterPassword/Resources/Media/ios/launch + +[[ "$(latest "$ios_icon"/*)" -nt "$appiconset/Contents.json" ]] && { + rm -rf "$appiconset"; mkdir -p "$appiconset" + { + comma= + printf '{"images":[' + for icon in "${icons[@]}"; do + IFS=: read icon filename <<< "$icon" + IFS=@ read px scale idiom os <<< "$icon" + pt=$(( px / scale )) + + if imageProps=$(copyImage "$ios_icon/$filename" "$appiconset/$filename"); then + printf '%s{"size":"%dx%d","filename":"%s","scale":"%sx"' \ + "$comma" "$pt" "$pt" "$filename" "$scale" + [[ $idiom ]] && printf ',"idiom":"%s"' "$idiom" + [[ $os ]] && printf ',"minimum-system-version":"%s"' "$os" + [[ $imageProps ]] && printf '%s' "$imageProps" + printf '}' + + comma=, + fi + + done + printf '],"info":{"version":1,"author":"genassets"},"properties":{"pre-rendered":true}}\n' + } > "$appiconset/Contents.json" +} + +[[ "$(latest "$ios_launch"/*)" -nt "$launchimage/Contents.json" ]] && { + rm -rf "$launchimage"; mkdir -p "$launchimage" + { + comma= + printf '{"images":[' + for splash in "${splashes[@]}"; do + IFS=@ read name scale idiom os <<< "$splash" + case "$name" in + *-568) subtype=retina4 ;; + *-667) subtype=667h ;; + *-736) subtype=736h ;; + *) subtype= ;; + esac + filename="Default${os:+-$os}${subtype:+-$subtype}${scale:+@${scale}x}${idiom:+~$idiom}.png" + + if imageProps=$(copyImage "$ios_launch/$name${scale:+@${scale}x}.png" "$launchimage/$filename"); then + printf '%s{"extent":"full-screen","filename":"%s","orientation":"portrait","scale":"%sx"' \ + "$comma" "$filename" "${scale:-1}" + [[ $idiom ]] && printf ',"idiom":"%s"' "$idiom" + [[ $os ]] && printf ',"minimum-system-version":"%s"' "$os" + [[ $subtype ]] && printf ',"subtype":"%s"' "$subtype" + [[ $imageProps ]] && printf '%s' "$imageProps" + printf '}' + + comma=, + fi + done + printf '],"info":{"version":1,"author":"genassets"}}\n' + } > "$launchimage/Contents.json" +} + +#for file in resources/images/mdpi/*.png; do +# name=${file##*/} name=${name%.*} name=${name/.9/} +# mdpiFile=$file +# xhdpiFile=${file%/*/*.*}/xhdpi/${file##*/} +# mdpiFilename=$name.png +# xhdpiFilename=$name@2x.png +# +# [[ -e "$xcassets/$name.imageset/$mdpiFilename" && $mdpiFile -ot "$xcassets/$name.imageset/$mdpiFilename" && +# -e "$xcassets/$name.imageset/$xhdpiFilename" && $xhdpiFile -ot "$xcassets/$name.imageset/$xhdpiFilename" ]] && continue +# rm -rf "$xcassets/$name.imageset"; mkdir -p "$xcassets/$name.imageset" +# +# { +# comma= +# printf '{"images":[' +# if imageProps=$(copyImage "$mdpiFile" "$xcassets/$name.imageset/$mdpiFilename"); then +# printf '%s{"idiom":"universal","scale":"1x","filename":"%s"' "$comma" "$mdpiFilename" +# [[ $imageProps ]] && printf '%s' "$imageProps" +# printf '}' +# comma=, +# fi +# if imageProps=$(copyImage "$xhdpiFile" "$xcassets/$name.imageset/$xhdpiFilename"); then +# printf '%s{"idiom":"universal","scale":"2x","filename":"%s"' "$comma" "$xhdpiFilename" +# [[ $imageProps ]] && printf '%s' "$imageProps" +# printf '}' +# comma=, +# fi +# printf '],"info":{"version":1,"author":"genassets"}}\n' +# } > "$xcassets/$name.imageset/Contents.json" +#done