Compare commits
187 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be96d4d506 | ||
|
|
f782b2ef62 | ||
|
|
188353d39b | ||
|
|
acdb96cb6f | ||
|
|
2c3a706ac4 | ||
|
|
0e3160b8bb | ||
|
|
6d8c5e7f94 | ||
|
|
9e6bb48105 | ||
|
|
e8d9796ba0 | ||
|
|
490e0fbd7e | ||
|
|
174859ad8d | ||
|
|
60506e69ef | ||
|
|
d42c2a17fa | ||
|
|
207d6eadd1 | ||
|
|
b3674e5324 | ||
|
|
2aa7d33f7a | ||
|
|
7c0628ddc9 | ||
|
|
dabc402d45 | ||
|
|
537e7d86f9 | ||
|
|
cdaf8f99d5 | ||
|
|
b932f132ef | ||
|
|
7f68d4b98f | ||
|
|
8316e5331d | ||
|
|
1bcbb3c90e | ||
|
|
12adde818b | ||
|
|
7cd66f5170 | ||
|
|
8a43a0d580 | ||
|
|
a831a9b3ee | ||
|
|
4013ca3578 | ||
|
|
39097d4458 | ||
|
|
7608173cca | ||
|
|
877207e547 | ||
|
|
21e3b9396f | ||
|
|
c662065bc3 | ||
|
|
db7f9d8af8 | ||
|
|
8f1d897660 | ||
|
|
6961236534 | ||
|
|
be0893c738 | ||
|
|
ee922c947f | ||
|
|
78afbbb128 | ||
|
|
8dbc521773 | ||
|
|
ff12aa6d7f | ||
|
|
6afdb38f98 | ||
|
|
87960a2d60 | ||
|
|
7f5bb9e114 | ||
|
|
4c4aaac08b | ||
|
|
5320e079ce | ||
|
|
636c337c78 | ||
|
|
c2b08678df | ||
|
|
7117d82aa4 | ||
|
|
4fa6436de2 | ||
|
|
3e30087856 | ||
|
|
6bd2d70270 | ||
|
|
cf11b01ed6 | ||
|
|
7e11f01331 | ||
|
|
aeca5e18fe | ||
|
|
615e7c98a8 | ||
|
|
e713776123 | ||
|
|
7d5b7e53d4 | ||
|
|
950c68437a | ||
|
|
300a04f5c7 | ||
|
|
8faf6b48dd | ||
|
|
5f0367ad29 | ||
|
|
e126a55912 | ||
|
|
d05c5eedd8 | ||
|
|
6819a2ace5 | ||
|
|
645b6c5f54 | ||
|
|
d3c09fd979 | ||
|
|
a41ae1814a | ||
|
|
70f7fa1345 | ||
|
|
ea9d8cc275 | ||
|
|
20d1811b5c | ||
|
|
634ef062f3 | ||
|
|
a424531a8a | ||
|
|
9cffe53993 | ||
|
|
fd35fea8cf | ||
|
|
01c21e95bb | ||
|
|
5af3ffa178 | ||
|
|
651d07f982 | ||
|
|
a383d0eee7 | ||
|
|
ca8f14fd3e | ||
|
|
fd855bb025 | ||
|
|
af340806af | ||
|
|
cdeee2576d | ||
|
|
779d2776a0 | ||
|
|
563aab9a81 | ||
|
|
73de98c5e2 | ||
|
|
c330728ac3 | ||
|
|
2db601475f | ||
|
|
d898646097 | ||
|
|
afaa17948f | ||
|
|
8514a58e64 | ||
|
|
f80bbff46e | ||
|
|
f7d595b0e7 | ||
|
|
422066ad4a | ||
|
|
73372f507a | ||
|
|
feddd038e3 | ||
|
|
3f6773f3a9 | ||
|
|
12b1610dc7 | ||
|
|
e20b33a051 | ||
|
|
b84ae532f2 | ||
|
|
145008406d | ||
|
|
a6ab9b9194 | ||
|
|
78c593fc08 | ||
|
|
5b08149ca6 | ||
|
|
58afc19c26 | ||
|
|
b3109187e9 | ||
|
|
a6e7a749bf | ||
|
|
ca5d83d40c | ||
|
|
285813324f | ||
|
|
d4b772b467 | ||
|
|
f392ad4053 | ||
|
|
35990f3bdd | ||
|
|
3932857c21 | ||
|
|
6f771a972b | ||
|
|
806a07135a | ||
|
|
f6b2287778 | ||
|
|
f4e90bb839 | ||
|
|
21630e919b | ||
|
|
ae74ab6906 | ||
|
|
caf361cd10 | ||
|
|
aeedc1946e | ||
|
|
93ae31f679 | ||
|
|
d5ff215da2 | ||
|
|
b34f7377da | ||
|
|
0c2e182039 | ||
|
|
438daf27ee | ||
|
|
aa6634970a | ||
|
|
9052416786 | ||
|
|
9d19eaf667 | ||
|
|
7ae9afa63a | ||
|
|
3d856b3773 | ||
|
|
7617b2382a | ||
|
|
a03dcf6859 | ||
|
|
57769ba199 | ||
|
|
6304b3a619 | ||
|
|
d1649f3c33 | ||
|
|
80f507b4cc | ||
|
|
f8a665db65 | ||
|
|
b15f2a8a26 | ||
|
|
e9094097a2 | ||
|
|
bea6ac5e68 | ||
|
|
778533ac7f | ||
|
|
83fcde5bd0 | ||
|
|
c9ec5874d3 | ||
|
|
4ce5fd25bc | ||
|
|
1ed28ebc9b | ||
|
|
c03199f7e5 | ||
|
|
9f10bcdec4 | ||
|
|
82c96ddfe3 | ||
|
|
c0fea076b9 | ||
|
|
b779ff5d1c | ||
|
|
73c10906e3 | ||
|
|
0ccd545dd4 | ||
|
|
49da0b47c7 | ||
|
|
672b28a5b7 | ||
|
|
2dbada3c7c | ||
|
|
3dbc105fbd | ||
|
|
43d55211b0 | ||
|
|
f170e9df69 | ||
|
|
1fbb6b0754 | ||
|
|
4c526d6f08 | ||
|
|
a62ae8c757 | ||
|
|
f2eb53569b | ||
|
|
c2a6a3d035 | ||
|
|
97dcc65eac | ||
|
|
1bd76dbb61 | ||
|
|
0fdf894bf0 | ||
|
|
19202e07d4 | ||
|
|
84b624aea2 | ||
|
|
c7ac5087b3 | ||
|
|
4ff8cd6d90 | ||
|
|
3f4558da2b | ||
|
|
b976e79b0f | ||
|
|
3d064fa68d | ||
|
|
1a1e024178 | ||
|
|
4876d62b56 | ||
|
|
8006b7096f | ||
|
|
a82ce7310d | ||
|
|
ae08cb62c5 | ||
|
|
c48fba6c01 | ||
|
|
3db25e7e3b | ||
|
|
1f7a49378b | ||
|
|
37ec21f5be | ||
|
|
2b8498f569 | ||
|
|
5c4fc61a12 | ||
|
|
c0ec65bbae |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
# OS-Specific junk.
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# IntelliJ
|
||||
/MasterPassword/Java/.idea
|
||||
@@ -28,14 +29,14 @@ Press/MasterPassword_PressKit/MasterPassword_pressrelease_*.pdf
|
||||
/sendipa/*
|
||||
!/sendipa/sendipa.conf
|
||||
|
||||
# Java
|
||||
MasterPassword/Java/**/target
|
||||
|
||||
# C
|
||||
MasterPassword/C/VERSION
|
||||
MasterPassword/C/*.o
|
||||
MasterPassword/C/mpw-*.tar.gz
|
||||
MasterPassword/C/mpw
|
||||
MasterPassword/C/mpw-bench
|
||||
MasterPassword/C/lib/*/*
|
||||
!MasterPassword/C/lib/*/.source
|
||||
MasterPassword/C/mpw-tests
|
||||
MasterPassword/C/lib/*/.unpacked
|
||||
MasterPassword/C/lib/*/.patched
|
||||
MasterPassword/C/lib/*/src
|
||||
MasterPassword/C/lib/include
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -18,4 +18,4 @@
|
||||
url = git://github.com/jonmarimba/jrswizzle.git
|
||||
[submodule "Site/mpw-js/js/mpw-js"]
|
||||
path = Site/mpw-js/js/mpw-js
|
||||
url = https://github.com/Lyndir/mpw-js.git
|
||||
url = https://github.com/tmthrgd/mpw-js.git
|
||||
|
||||
12
.idea/encodings.xml
generated
Normal file → Executable file
12
.idea/encodings.xml
generated
Normal file → Executable file
@@ -1,5 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
|
||||
<file url="file://$PROJECT_DIR$/MasterPassword/Java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-algorithm" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-cli" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-gui" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/MasterPassword/Java/masterpassword-model" charset="UTF-8" />
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/inspectionProfiles/Project_Default.xml
generated
2
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -2,6 +2,7 @@
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="Convert to string" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="FunctionImplicitDeclarationInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ImplicitIntegerAndEnumConversion" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="LossyEncoding" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
@@ -9,6 +10,7 @@
|
||||
<inspection_tool class="OCNotLocalizedStringInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="OCUnusedMacroInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="OCUnusedMethodInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="Replace with subshell" enabled="true" level="INFO" enabled_by_default="true" />
|
||||
<inspection_tool class="SignednessMismatch" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="UnavailableInDeploymentTarget" enabled="true" level="INFO" enabled_by_default="true" />
|
||||
<inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
language: objective-c
|
||||
xcode_project: MasterPassword/ObjC/iOS/MasterPassword-iOS.xcodeproj
|
||||
xcode_scheme: MasterPassword iOS (Development)
|
||||
osx_image: xcode7
|
||||
xcode_scheme: MasterPassword iOS (App Store)
|
||||
xcode_workspace: MasterPassword.xcworkspace
|
||||
xcode_sdk: iphonesimulator
|
||||
env: TERM=dumb
|
||||
git:
|
||||
|
||||
BIN
External/Mac/Crashlytics.framework/Versions/A/Crashlytics
vendored
Normal file → Executable file
BIN
External/Mac/Crashlytics.framework/Versions/A/Crashlytics
vendored
Normal file → Executable file
Binary file not shown.
31
External/Mac/Crashlytics.framework/Versions/A/Headers/ANSCompatibility.h
vendored
Normal file
31
External/Mac/Crashlytics.framework/Versions/A/Headers/ANSCompatibility.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// ANSCompatibility.h
|
||||
// AnswersKit
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !__has_feature(nullability)
|
||||
#define nonnull
|
||||
#define nullable
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_END
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
#if __has_feature(objc_generics)
|
||||
#define ANS_GENERIC_NSARRAY(type) NSArray<type>
|
||||
#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary<key_type, object_key>
|
||||
#else
|
||||
#define ANS_GENERIC_NSARRAY(type) NSArray
|
||||
#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
|
||||
#endif
|
||||
206
External/Mac/Crashlytics.framework/Versions/A/Headers/Answers.h
vendored
Normal file
206
External/Mac/Crashlytics.framework/Versions/A/Headers/Answers.h
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
//
|
||||
// Answers.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ANSCompatibility.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Answers : NSObject
|
||||
|
||||
/**
|
||||
* Log a Sign Up event to see users signing up for your app in real-time, understand how
|
||||
* many users are signing up with different methods and their success rate signing up.
|
||||
*
|
||||
* @param signUpMethodOrNil The method by which a user logged in, e.g. Twitter or Digits.
|
||||
* @param signUpSucceededOrNil The ultimate success or failure of the login
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logSignUpWithMethod:(nullable NSString *)signUpMethodOrNil
|
||||
success:(nullable NSNumber *)signUpSucceededOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log an Log In event to see users logging into your app in real-time, understand how many
|
||||
* users are logging in with different methods and their success rate logging into your app.
|
||||
*
|
||||
* @param loginMethodOrNil The method by which a user logged in, e.g. email, Twitter or Digits.
|
||||
* @param loginSucceededOrNil The ultimate success or failure of the login
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logLoginWithMethod:(nullable NSString *)loginMethodOrNil
|
||||
success:(nullable NSNumber *)loginSucceededOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Share event to see users sharing from your app in real-time, letting you
|
||||
* understand what content they're sharing from the type or genre down to the specific id.
|
||||
*
|
||||
* @param shareMethodOrNil The method by which a user shared, e.g. email, Twitter, SMS.
|
||||
* @param contentNameOrNil The human readable name for this piece of content.
|
||||
* @param contentTypeOrNil The type of content shared.
|
||||
* @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logShareWithMethod:(nullable NSString *)shareMethodOrNil
|
||||
contentName:(nullable NSString *)contentNameOrNil
|
||||
contentType:(nullable NSString *)contentTypeOrNil
|
||||
contentId:(nullable NSString *)contentIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log an Invite Event to track how users are inviting other users into
|
||||
* your application.
|
||||
*
|
||||
* @param inviteMethodOrNil The method of invitation, e.g. GameCenter, Twitter, email.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logInviteWithMethod:(nullable NSString *)inviteMethodOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Purchase event to see your revenue in real-time, understand how many users are making purchases, see which
|
||||
* items are most popular, and track plenty of other important purchase-related metrics.
|
||||
*
|
||||
* @param itemPriceOrNil The purchased item's price.
|
||||
* @param currencyOrNil The ISO4217 currency code. Example: USD
|
||||
* @param purchaseSucceededOrNil Was the purchase succesful or unsuccesful
|
||||
* @param itemNameOrNil The human-readable form of the item's name. Example:
|
||||
* @param itemIdOrNil The machine-readable, unique item identifier Example: SKU
|
||||
* @param itemTypeOrNil The type, or genre of the item. Example: Song
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logPurchaseWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
|
||||
currency:(nullable NSString *)currencyOrNil
|
||||
success:(nullable NSNumber *)purchaseSucceededOrNil
|
||||
itemName:(nullable NSString *)itemNameOrNil
|
||||
itemType:(nullable NSString *)itemTypeOrNil
|
||||
itemId:(nullable NSString *)itemIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Level Start Event to track where users are in your game.
|
||||
*
|
||||
* @param levelNameOrNil The level name
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this level start event.
|
||||
*/
|
||||
+ (void)logLevelStart:(nullable NSString *)levelNameOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Level End event to track how users are completing levels in your game.
|
||||
*
|
||||
* @param levelNameOrNil The name of the level completed, E.G. "1" or "Training"
|
||||
* @param scoreOrNil The score the user completed the level with.
|
||||
* @param levelCompletedSuccesfullyOrNil A boolean representing whether or not the level was completed succesfully.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logLevelEnd:(nullable NSString *)levelNameOrNil
|
||||
score:(nullable NSNumber *)scoreOrNil
|
||||
success:(nullable NSNumber *)levelCompletedSuccesfullyOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log an Add to Cart event to see users adding items to a shopping cart in real-time, understand how
|
||||
* many users start the purchase flow, see which items are most popular, and track plenty of other important
|
||||
* purchase-related metrics.
|
||||
*
|
||||
* @param itemPriceOrNil The purchased item's price.
|
||||
* @param currencyOrNil The ISO4217 currency code. Example: USD
|
||||
* @param itemNameOrNil The human-readable form of the item's name. Example:
|
||||
* @param itemTypeOrNil The type, or genre of the item. Example: Song
|
||||
* @param itemIdOrNil The machine-readable, unique item identifier Example: SKU
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logAddToCartWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
|
||||
currency:(nullable NSString *)currencyOrNil
|
||||
itemName:(nullable NSString *)itemNameOrNil
|
||||
itemType:(nullable NSString *)itemTypeOrNil
|
||||
itemId:(nullable NSString *)itemIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Start Checkout event to see users moving through the purchase funnel in real-time, understand how many
|
||||
* users are doing this and how much they're spending per checkout, and see how it related to other important
|
||||
* purchase-related metrics.
|
||||
*
|
||||
* @param totalPriceOrNil The total price of the cart.
|
||||
* @param currencyOrNil The ISO4217 currency code. Example: USD
|
||||
* @param itemCountOrNil The number of items in the cart.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logStartCheckoutWithPrice:(nullable NSDecimalNumber *)totalPriceOrNil
|
||||
currency:(nullable NSString *)currencyOrNil
|
||||
itemCount:(nullable NSNumber *)itemCountOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Rating event to see users rating content within your app in real-time and understand what
|
||||
* content is most engaging, from the type or genre down to the specific id.
|
||||
*
|
||||
* @param ratingOrNil The integer rating given by the user.
|
||||
* @param contentNameOrNil The human readable name for this piece of content.
|
||||
* @param contentTypeOrNil The type of content shared.
|
||||
* @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logRating:(nullable NSNumber *)ratingOrNil
|
||||
contentName:(nullable NSString *)contentNameOrNil
|
||||
contentType:(nullable NSString *)contentTypeOrNil
|
||||
contentId:(nullable NSString *)contentIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Content View event to see users viewing content within your app in real-time and
|
||||
* understand what content is most engaging, from the type or genre down to the specific id.
|
||||
*
|
||||
* @param contentNameOrNil The human readable name for this piece of content.
|
||||
* @param contentTypeOrNil The type of content shared.
|
||||
* @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logContentViewWithName:(nullable NSString *)contentNameOrNil
|
||||
contentType:(nullable NSString *)contentTypeOrNil
|
||||
contentId:(nullable NSString *)contentIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Search event allows you to see users searching within your app in real-time and understand
|
||||
* exactly what they're searching for.
|
||||
*
|
||||
* @param queryOrNil The user's query.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logSearchWithQuery:(nullable NSString *)queryOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Custom Event to see user actions that are uniquely important for your app in real-time, to see how often
|
||||
* they're performing these actions with breakdowns by different categories you add. Use a human-readable name for
|
||||
* the name of the event, since this is how the event will appear in Answers.
|
||||
*
|
||||
* @param eventName The human-readable name for the event.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase. Attribute keys
|
||||
* must be <code>NSString</code> and and values must be <code>NSNumber</code> or <code>NSString</code>.
|
||||
* @discussion How we treat <code>NSNumbers</code>:
|
||||
* We will provide information about the distribution of values over time.
|
||||
*
|
||||
* How we treat <code>NSStrings</code>:
|
||||
* NSStrings are used as categorical data, allowing comparison across different category values.
|
||||
* Strings are limited to a maximum length of 100 characters, attributes over this length will be
|
||||
* truncated.
|
||||
*
|
||||
* When tracking the Tweet views to better understand user engagement, sending the tweet's length
|
||||
* and the type of media present in the tweet allows you to track how tweet length and the type of media influence
|
||||
* engagement.
|
||||
*/
|
||||
+ (void)logCustomEventWithName:(NSString *)eventName
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
33
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSAttributes.h
vendored
Normal file
33
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSAttributes.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// CLSAttributes.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CLS_DEPRECATED(x) __attribute__ ((deprecated(x)))
|
||||
|
||||
#if !__has_feature(nullability)
|
||||
#define nonnull
|
||||
#define nullable
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_END
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
#if __has_feature(objc_generics)
|
||||
#define CLS_GENERIC_NSARRAY(type) NSArray<type>
|
||||
#define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary<key_type, object_key>
|
||||
#else
|
||||
#define CLS_GENERIC_NSARRAY(type) NSArray
|
||||
#define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
|
||||
#endif
|
||||
64
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSLogging.h
vendored
Normal file
64
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSLogging.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// CLSLogging.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
#ifdef __OBJC__
|
||||
#import "CLSAttributes.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The CLS_LOG macro provides as easy way to gather more information in your log messages that are
|
||||
* sent with your crash data. CLS_LOG prepends your custom log message with the function name and
|
||||
* line number where the macro was used. If your app was built with the DEBUG preprocessor macro
|
||||
* defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog.
|
||||
* If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only.
|
||||
*
|
||||
* Example output:
|
||||
* -[AppDelegate login:] line 134 $ login start
|
||||
*
|
||||
* If you would like to change this macro, create a new header file, unset our define and then define
|
||||
* your own version. Make sure this new header file is imported after the Crashlytics header file.
|
||||
*
|
||||
* #undef CLS_LOG
|
||||
* #define CLS_LOG(__FORMAT__, ...) CLSNSLog...
|
||||
*
|
||||
**/
|
||||
#ifdef __OBJC__
|
||||
#ifdef DEBUG
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will not show up in the system.log
|
||||
* and will only be visible in your Crashlytics dashboard.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifdef __OBJC__
|
||||
OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will show up in the system.log
|
||||
* and your Crashlytics dashboard. It is not recommended for Release builds.
|
||||
*
|
||||
**/
|
||||
OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSNSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
103
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSReport.h
vendored
Normal file
103
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSReport.h
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// CLSReport.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "CLSAttributes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate changes for details.
|
||||
**/
|
||||
@protocol CLSCrashReport <NSObject>
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *identifier;
|
||||
@property (nonatomic, copy, readonly) NSDictionary *customKeys;
|
||||
@property (nonatomic, copy, readonly) NSString *bundleVersion;
|
||||
@property (nonatomic, copy, readonly) NSString *bundleShortVersionString;
|
||||
@property (nonatomic, copy, readonly) NSDate *crashedOnDate;
|
||||
@property (nonatomic, copy, readonly) NSString *OSVersion;
|
||||
@property (nonatomic, copy, readonly) NSString *OSBuildVersion;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can
|
||||
* use this class to get information about the event, and can also set some values after the
|
||||
* event has occured.
|
||||
**/
|
||||
@interface CLSReport : NSObject <CLSCrashReport>
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Returns the session identifier for the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *identifier;
|
||||
|
||||
/**
|
||||
* Returns the custom key value data for the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSDictionary *customKeys;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleVersion of the application that generated the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *bundleVersion;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleShortVersionString of the application that generated the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *bundleShortVersionString;
|
||||
|
||||
/**
|
||||
* Returns the date that the report was created.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSDate *dateCreated;
|
||||
|
||||
/**
|
||||
* Returns the os version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *OSVersion;
|
||||
|
||||
/**
|
||||
* Returns the os build version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *OSBuildVersion;
|
||||
|
||||
/**
|
||||
* Returns YES if the report contains any crash information, otherwise returns NO.
|
||||
**/
|
||||
@property (nonatomic, assign, readonly) BOOL isCrash;
|
||||
|
||||
/**
|
||||
* You can use this method to set, after the event, additional custom keys. The rules
|
||||
* and semantics for this method are the same as those documented in Crashlytics.h. Be aware
|
||||
* that the maximum size and count of custom keys is still enforced, and you can overwrite keys
|
||||
* and/or cause excess keys to be deleted by using this method.
|
||||
**/
|
||||
- (void)setObjectValue:(nullable id)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Record an application-specific user identifier. See Crashlytics.h for details.
|
||||
**/
|
||||
@property (nonatomic, copy, nullable) NSString * userIdentifier;
|
||||
|
||||
/**
|
||||
* Record a user name. See Crashlytics.h for details.
|
||||
**/
|
||||
@property (nonatomic, copy, nullable) NSString * userName;
|
||||
|
||||
/**
|
||||
* Record a user email. See Crashlytics.h for details.
|
||||
**/
|
||||
@property (nonatomic, copy, nullable) NSString * userEmail;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
37
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSStackFrame.h
vendored
Normal file
37
External/Mac/Crashlytics.framework/Versions/A/Headers/CLSStackFrame.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// CLSStackFrame.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "CLSAttributes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
*
|
||||
* This class is used in conjunction with -[Crashlytics recordCustomExceptionName:reason:frameArray:] to
|
||||
* record information about non-ObjC/C++ exceptions. All information included here will be displayed
|
||||
* in the Crashlytics UI, and can influence crash grouping. Be particularly careful with the use of the
|
||||
* address property. If set, Crashlytics will attempt symbolication and could overwrite other properities
|
||||
* in the process.
|
||||
*
|
||||
**/
|
||||
@interface CLSStackFrame : NSObject
|
||||
|
||||
+ (instancetype)stackFrame;
|
||||
+ (instancetype)stackFrameWithAddress:(NSUInteger)address;
|
||||
+ (instancetype)stackFrameWithSymbol:(NSString *)symbol;
|
||||
|
||||
@property (nonatomic, copy, nullable) NSString *symbol;
|
||||
@property (nonatomic, copy, nullable) NSString *library;
|
||||
@property (nonatomic, copy, nullable) NSString *fileName;
|
||||
@property (nonatomic, assign) uint32_t lineNumber;
|
||||
@property (nonatomic, assign) uint64_t offset;
|
||||
@property (nonatomic, assign) uint64_t address;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -2,186 +2,189 @@
|
||||
// Crashlytics.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright 2013 Crashlytics, Inc. All rights reserved.
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* The CLS_LOG macro provides as easy way to gather more information in your log messages that are
|
||||
* sent with your crash data. CLS_LOG prepends your custom log message with the function name and
|
||||
* line number where the macro was used. If your app was built with the DEBUG preprocessor macro
|
||||
* defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog.
|
||||
* If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only.
|
||||
*
|
||||
* Example output:
|
||||
* -[AppDelegate login:] line 134 $ login start
|
||||
*
|
||||
* If you would like to change this macro, create a new header file, unset our define and then define
|
||||
* your own version. Make sure this new header file is imported after the Crashlytics header file.
|
||||
*
|
||||
* #undef CLS_LOG
|
||||
* #define CLS_LOG(__FORMAT__, ...) CLSNSLog...
|
||||
*
|
||||
**/
|
||||
#ifdef DEBUG
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will not show up in the system.log
|
||||
* and will only be visible in your Crashlytics dashboard.
|
||||
*
|
||||
**/
|
||||
OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will show up in the system.log
|
||||
* and your Crashlytics dashboard. It is not recommended for Release builds.
|
||||
*
|
||||
**/
|
||||
OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSNSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0);
|
||||
#import "CLSAttributes.h"
|
||||
#import "CLSLogging.h"
|
||||
#import "CLSReport.h"
|
||||
#import "CLSStackFrame.h"
|
||||
#import "Answers.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol CrashlyticsDelegate;
|
||||
|
||||
/**
|
||||
* Crashlytics. Handles configuration and initialization of Crashlytics.
|
||||
*/
|
||||
@interface Crashlytics : NSObject
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *apiKey;
|
||||
@property (nonatomic, readonly, copy) NSString *APIKey;
|
||||
@property (nonatomic, readonly, copy) NSString *version;
|
||||
@property (nonatomic, assign) BOOL debugMode;
|
||||
|
||||
@property (nonatomic, assign) NSObject <CrashlyticsDelegate> *delegate;
|
||||
|
||||
/**
|
||||
*
|
||||
* The recommended way to install Crashlytics into your application is to place a call
|
||||
* to +startWithAPIKey: in your -application:didFinishLaunchingWithOptions: method.
|
||||
* The delegate can be used to influence decisions on reporting and behavior, as well as reacting
|
||||
* to previous crashes.
|
||||
*
|
||||
* This delay defaults to 1 second in order to generally give the application time to
|
||||
* fully finish launching.
|
||||
* Make certain that the delegate is setup before starting Crashlytics with startWithAPIKey:... or
|
||||
* via +[Fabric with:...]. Failure to do will result in missing any delegate callbacks that occur
|
||||
* synchronously during start.
|
||||
*
|
||||
**/
|
||||
@property (nonatomic, assign, nullable) id <CrashlyticsDelegate> delegate;
|
||||
|
||||
/**
|
||||
* The recommended way to install Crashlytics into your application is to place a call to +startWithAPIKey:
|
||||
* in your -application:didFinishLaunchingWithOptions: or -applicationDidFinishLaunching:
|
||||
* method.
|
||||
*
|
||||
* Note: Starting with 3.0, the submission process has been significantly improved. The delay parameter
|
||||
* is no longer required to throttle submissions on launch, performance will be great without it.
|
||||
*
|
||||
* @param apiKey The Crashlytics API Key for this app
|
||||
*
|
||||
* @return The singleton Crashlytics instance
|
||||
*/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey: instead.");
|
||||
|
||||
/**
|
||||
* If you need the functionality provided by the CrashlyticsDelegate protocol, you can use
|
||||
* these convenience methods to activate the framework and set the delegate in one call.
|
||||
*
|
||||
* @param apiKey The Crashlytics API Key for this app
|
||||
* @param delegate A delegate object which conforms to CrashlyticsDelegate.
|
||||
*
|
||||
* If you need the functionality provided by the CrashlyticsDelegate protocol, you can use
|
||||
* these convenience methods to activate the framework and set the delegate in one call.
|
||||
*
|
||||
**/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject <CrashlyticsDelegate> *)delegate;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject <CrashlyticsDelegate> *)delegate afterDelay:(NSTimeInterval)delay;
|
||||
* @return The singleton Crashlytics instance
|
||||
*/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id<CrashlyticsDelegate>)delegate;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id<CrashlyticsDelegate>)delegate afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey:delegate: instead.");
|
||||
|
||||
/**
|
||||
* Access the singleton Crashlytics instance.
|
||||
*
|
||||
* Access the singleton Crashlytics instance.
|
||||
*
|
||||
**/
|
||||
* @return The singleton Crashlytics instance
|
||||
*/
|
||||
+ (Crashlytics *)sharedInstance;
|
||||
|
||||
/**
|
||||
*
|
||||
* The easiest way to cause a crash - great for testing!
|
||||
*
|
||||
**/
|
||||
* The easiest way to cause a crash - great for testing!
|
||||
*/
|
||||
- (void)crash;
|
||||
|
||||
/**
|
||||
*
|
||||
* Many of our customers have requested the ability to tie crashes to specific end-users of their
|
||||
* application in order to facilitate responses to support requests or permit the ability to reach
|
||||
* out for more information. We allow you to specify up to three separate values for display within
|
||||
* the Crashlytics UI - but please be mindful of your end-user's privacy.
|
||||
*
|
||||
* We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record
|
||||
* in your system. This could be a database id, hash, or other value that is meaningless to a
|
||||
* third-party observer but can be indexed and queried by you.
|
||||
*
|
||||
* Optionally, you may also specify the end-user's name or username, as well as email address if you
|
||||
* do not have a system that works well with obscured identifiers.
|
||||
*
|
||||
* Pursuant to our EULA, this data is transferred securely throughout our system and we will not
|
||||
* disseminate end-user data unless required to by law. That said, if you choose to provide end-user
|
||||
* contact information, we strongly recommend that you disclose this in your application's privacy
|
||||
* policy. Data privacy is of our utmost concern.
|
||||
*
|
||||
**/
|
||||
- (void)setUserIdentifier:(NSString *)identifier;
|
||||
- (void)setUserName:(NSString *)name;
|
||||
- (void)setUserEmail:(NSString *)email;
|
||||
|
||||
+ (void)setUserIdentifier:(NSString *)identifier;
|
||||
+ (void)setUserName:(NSString *)name;
|
||||
+ (void)setUserEmail:(NSString *)email;
|
||||
* The easiest way to cause a crash with an exception - great for testing.
|
||||
*/
|
||||
- (void)throwException;
|
||||
|
||||
/**
|
||||
* Specify a user identifier which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* Set a value for a key to be associated with your crash data.
|
||||
* Many of our customers have requested the ability to tie crashes to specific end-users of their
|
||||
* application in order to facilitate responses to support requests or permit the ability to reach
|
||||
* out for more information. We allow you to specify up to three separate values for display within
|
||||
* the Crashlytics UI - but please be mindful of your end-user's privacy.
|
||||
*
|
||||
**/
|
||||
- (void)setObjectValue:(id)value forKey:(NSString *)key;
|
||||
* We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record
|
||||
* in your system. This could be a database id, hash, or other value that is meaningless to a
|
||||
* third-party observer but can be indexed and queried by you.
|
||||
*
|
||||
* Optionally, you may also specify the end-user's name or username, as well as email address if you
|
||||
* do not have a system that works well with obscured identifiers.
|
||||
*
|
||||
* Pursuant to our EULA, this data is transferred securely throughout our system and we will not
|
||||
* disseminate end-user data unless required to by law. That said, if you choose to provide end-user
|
||||
* contact information, we strongly recommend that you disclose this in your application's privacy
|
||||
* policy. Data privacy is of our utmost concern.
|
||||
*
|
||||
* @param identifier An arbitrary user identifier string which ties an end-user to a record in your system.
|
||||
*/
|
||||
- (void)setUserIdentifier:(nullable NSString *)identifier;
|
||||
|
||||
/**
|
||||
* Specify a user name which will be visible in the Crashlytics UI.
|
||||
* Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs.
|
||||
* @see setUserIdentifier:
|
||||
*
|
||||
* @param name An end user's name.
|
||||
*/
|
||||
- (void)setUserName:(nullable NSString *)name;
|
||||
|
||||
/**
|
||||
* Specify a user email which will be visible in the Crashlytics UI.
|
||||
* Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs.
|
||||
*
|
||||
* @see setUserIdentifier:
|
||||
*
|
||||
* @param email An end user's email address.
|
||||
*/
|
||||
- (void)setUserEmail:(nullable NSString *)email;
|
||||
|
||||
+ (void)setUserIdentifier:(nullable NSString *)identifier CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setUserName:(nullable NSString *)name CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setUserEmail:(nullable NSString *)email CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
|
||||
/**
|
||||
* Set a value for a for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
* When setting an object value, the object is converted to a string. This is typically done by calling
|
||||
* -[NSObject description].
|
||||
*
|
||||
* @param value The object to be associated with the key
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setObjectValue:(nullable id)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Set an int value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* @param value The integer value to be set
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setIntValue:(int)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Set an BOOL value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* @param value The BOOL value to be set
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Set an float value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* @param value The float value to be set
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setFloatValue:(float)value forKey:(NSString *)key;
|
||||
|
||||
+ (void)setObjectValue:(id)value forKey:(NSString *)key;
|
||||
+ (void)setIntValue:(int)value forKey:(NSString *)key;
|
||||
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
|
||||
+ (void)setFloatValue:(float)value forKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
+ (void)setObjectValue:(nullable id)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setIntValue:(int)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setFloatValue:(float)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
|
||||
/**
|
||||
* The CLSCrashReport protocol exposes methods that you can call on crash report objects passed
|
||||
* to delegate methods. If you want these values or the entire object to stay in memory retain
|
||||
* them or copy them.
|
||||
**/
|
||||
@protocol CLSCrashReport <NSObject>
|
||||
@required
|
||||
* This method can be used to record a single exception structure in a report. This is particularly useful
|
||||
* when your code interacts with non-native languages like Lua, C#, or Javascript. This call can be
|
||||
* expensive and should only be used shortly before process termination. This API is not intended be to used
|
||||
* to log NSException objects. All safely-reportable NSExceptions are automatically captured by
|
||||
* Crashlytics.
|
||||
*
|
||||
* @param name The name of the custom exception
|
||||
* @param reason The reason this exception occured
|
||||
* @param frameArray An array of CLSStackFrame objects
|
||||
*/
|
||||
- (void)recordCustomExceptionName:(NSString *)name reason:(nullable NSString *)reason frameArray:(CLS_GENERIC_NSARRAY(CLSStackFrame *) *)frameArray;
|
||||
|
||||
/**
|
||||
* Returns the session identifier for the crash report.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *identifier;
|
||||
|
||||
/**
|
||||
* Returns the custom key value data for the crash report.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSDictionary *customKeys;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleVersion of the application that crashed.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *bundleVersion;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleShortVersionString of the application that crashed.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *bundleShortVersionString;
|
||||
|
||||
/**
|
||||
* Returns the date that the application crashed at.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSDate *crashedOnDate;
|
||||
|
||||
/**
|
||||
* Returns the os version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *OSVersion;
|
||||
|
||||
/**
|
||||
* Returns the os build version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *OSBuildVersion;
|
||||
- (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
- (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
+ (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
+ (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
|
||||
@end
|
||||
|
||||
@@ -190,31 +193,56 @@ OBJC_EXTERN void CLSNSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,
|
||||
* The CrashlyticsDelegate protocol provides a mechanism for your application to take
|
||||
* action on events that occur in the Crashlytics crash reporting system. You can make
|
||||
* use of these calls by assigning an object to the Crashlytics' delegate property directly,
|
||||
* or through the convenience startWithAPIKey:delegate:... methods.
|
||||
* or through the convenience +startWithAPIKey:delegate: method.
|
||||
*
|
||||
**/
|
||||
*/
|
||||
@protocol CrashlyticsDelegate <NSObject>
|
||||
@optional
|
||||
|
||||
/**
|
||||
*
|
||||
* Called once a Crashlytics instance has determined that the last execution of the
|
||||
* application ended in a crash. This is called some time after the crash reporting
|
||||
* process has begun. If you have specified a delay in one of the
|
||||
* startWithAPIKey:... calls, this will take at least that long to be invoked.
|
||||
*
|
||||
**/
|
||||
- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics;
|
||||
|
||||
- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:");
|
||||
- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:");
|
||||
|
||||
/**
|
||||
*
|
||||
* Just like crashlyticsDidDetectCrashDuringPreviousExecution this delegate method is
|
||||
* called once a Crashlytics instance has determined that the last execution of the
|
||||
* application ended in a crash. A CLSCrashReport is passed back that contains data about
|
||||
* the last crash report that was generated. See the CLSCrashReport protocol for method details.
|
||||
* This method is called after crashlyticsDidDetectCrashDuringPreviousExecution.
|
||||
* Called when a Crashlytics instance has determined that the last execution of the
|
||||
* application ended in a crash. This is called synchronously on Crashlytics
|
||||
* initialization. Your delegate must invoke the completionHandler, but does not need to do so
|
||||
* synchronously, or even on the main thread. Invoking completionHandler with NO will cause the
|
||||
* detected report to be deleted and not submitted to Crashlytics. This is useful for
|
||||
* implementing permission prompts, or other more-complex forms of logic around submitting crashes.
|
||||
*
|
||||
**/
|
||||
- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash;
|
||||
* @warning Failure to invoke the completionHandler will prevent submissions from being reported. Watch out.
|
||||
*
|
||||
* @warning Just implementing this delegate method will disable all forms of synchronous report submission. This can
|
||||
* impact the reliability of reporting crashes very early in application launch.
|
||||
*
|
||||
* @param report The CLSReport object representing the last detected crash
|
||||
* @param completionHandler The completion handler to call when your logic has completed.
|
||||
*
|
||||
*/
|
||||
- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report completionHandler:(void (^)(BOOL submit))completionHandler;
|
||||
|
||||
/**
|
||||
* If your app is running on an OS that supports it (OS X 10.9+, iOS 7.0+), Crashlytics will submit
|
||||
* most reports using out-of-process background networking operations. This results in a significant
|
||||
* improvement in reliability of reporting, as well as power and performance wins for your users.
|
||||
* If you don't want this functionality, you can disable by returning NO from this method.
|
||||
*
|
||||
* @warning Background submission is not supported for extensions on iOS or OS X.
|
||||
*
|
||||
* @param crashlytics The Crashlytics singleton instance
|
||||
*
|
||||
* @return Return NO if you don't want out-of-process background network operations.
|
||||
*
|
||||
*/
|
||||
- (BOOL)crashlyticsCanUseBackgroundSessions:(Crashlytics *)crashlytics;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* `CrashlyticsKit` can be used as a parameter to `[Fabric with:@[CrashlyticsKit]];` in Objective-C. In Swift, use Crashlytics.sharedInstance()
|
||||
*/
|
||||
#define CrashlyticsKit [Crashlytics sharedInstance]
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
framework module Crashlytics {
|
||||
umbrella header "Crashlytics.h"
|
||||
header "Crashlytics.h"
|
||||
header "Answers.h"
|
||||
header "ANSCompatibility.h"
|
||||
header "CLSLogging.h"
|
||||
header "CLSReport.h"
|
||||
header "CLSStackFrame.h"
|
||||
header "CLSAttributes.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
export *
|
||||
|
||||
link "z"
|
||||
link "c++"
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>14E46</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Crashlytics</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.crashlytics.sdk.mac</string>
|
||||
<string>com.twitter.crashlytics.mac</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@@ -15,16 +17,31 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.2.5</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>macosx</string>
|
||||
</array>
|
||||
<string>3.3.4</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>39</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>10.6</string>
|
||||
<string>82</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>6E35b</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>14D125</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.10</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0640</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>6E35b</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2015 Crashlytics, Inc. All rights reserved.</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
BIN
External/Mac/Crashlytics.framework/run
vendored
BIN
External/Mac/Crashlytics.framework/run
vendored
Binary file not shown.
BIN
External/Mac/Crashlytics.framework/submit
vendored
Executable file
BIN
External/Mac/Crashlytics.framework/submit
vendored
Executable file
Binary file not shown.
BIN
External/Mac/Crashlytics.framework/uploadDSYM
vendored
Executable file
BIN
External/Mac/Crashlytics.framework/uploadDSYM
vendored
Executable file
Binary file not shown.
1
External/Mac/Fabric.framework/Fabric
vendored
Symbolic link
1
External/Mac/Fabric.framework/Fabric
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
Versions/Current/Fabric
|
||||
1
External/Mac/Fabric.framework/Modules
vendored
Symbolic link
1
External/Mac/Fabric.framework/Modules
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
Versions/Current/Modules
|
||||
BIN
External/Mac/Fabric.framework/Versions/A/Fabric
vendored
Executable file
BIN
External/Mac/Fabric.framework/Versions/A/Fabric
vendored
Executable file
Binary file not shown.
48
External/Mac/Fabric.framework/Versions/A/Headers/FABAttributes.h
vendored
Normal file
48
External/Mac/Fabric.framework/Versions/A/Headers/FABAttributes.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// FABAttributes.h
|
||||
// Fabric
|
||||
//
|
||||
// Copyright (c) 2015 Twitter. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define FAB_UNAVAILABLE(x) __attribute__((unavailable(x)))
|
||||
|
||||
#if __has_feature(nullability)
|
||||
#define fab_nullable nullable
|
||||
#define fab_nonnull nonnull
|
||||
#define fab_null_unspecified null_unspecified
|
||||
#define fab_null_resettable null_resettable
|
||||
#define __fab_nullable __nullable
|
||||
#define __fab_nonnull __nonnull
|
||||
#define __fab_null_unspecified __null_unspecified
|
||||
#else
|
||||
#define fab_nullable
|
||||
#define fab_nonnull
|
||||
#define fab_null_unspecified
|
||||
#define fab_null_resettable
|
||||
#define __fab_nullable
|
||||
#define __fab_nonnull
|
||||
#define __fab_null_unspecified
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_END
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* The following macros are defined here to provide
|
||||
* backwards compatability. If you are still using
|
||||
* them you should migrate to the new versions that
|
||||
* are defined above.
|
||||
*/
|
||||
#define FAB_NONNULL __fab_nonnull
|
||||
#define FAB_NULLABLE __fab_nullable
|
||||
#define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN
|
||||
#define FAB_END_NONNULL NS_ASSUME_NONNULL_END
|
||||
64
External/Mac/Fabric.framework/Versions/A/Headers/Fabric.h
vendored
Normal file
64
External/Mac/Fabric.framework/Versions/A/Headers/Fabric.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Fabric.h
|
||||
//
|
||||
// Copyright (c) 2015 Twitter. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FABAttributes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
|
||||
#error "Fabric's minimum iOS version is 6.0"
|
||||
#endif
|
||||
#else
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
|
||||
#error "Fabric's minimum OS X version is 10.7"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Fabric Base. Coordinates configuration and starts all provided kits.
|
||||
*/
|
||||
@interface Fabric : NSObject
|
||||
|
||||
/**
|
||||
* Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use.
|
||||
*
|
||||
* For example, in Objective-C:
|
||||
*
|
||||
* `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];`
|
||||
*
|
||||
* Swift:
|
||||
*
|
||||
* `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])`
|
||||
*
|
||||
* Only the first call to this method is honored. Subsequent calls are no-ops.
|
||||
*
|
||||
* @param kitClasses An array of kit Class objects
|
||||
*
|
||||
* @return Returns the shared Fabric instance. In most cases this can be ignored.
|
||||
*/
|
||||
+ (instancetype)with:(NSArray *)kitClasses;
|
||||
|
||||
/**
|
||||
* Returns the Fabric singleton object.
|
||||
*/
|
||||
+ (instancetype)sharedSDK;
|
||||
|
||||
/**
|
||||
* This BOOL enables or disables debug logging, such as kit version information. The default value is NO.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL debug;
|
||||
|
||||
/**
|
||||
* Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance.
|
||||
*/
|
||||
- (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance.");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
6
External/Mac/Fabric.framework/Versions/A/Modules/module.modulemap
vendored
Normal file
6
External/Mac/Fabric.framework/Versions/A/Modules/module.modulemap
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
framework module Fabric {
|
||||
umbrella header "Fabric.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
51
External/Mac/Fabric.framework/Versions/A/Resources/Info.plist
vendored
Normal file
51
External/Mac/Fabric.framework/Versions/A/Resources/Info.plist
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>14E46</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Fabric</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.fabric.sdk.mac</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Fabric</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.5.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>30</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>7A220</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>15A278</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.11</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0700</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>7A220</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2015 Twitter. All rights reserved.</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
28
External/Mac/Fabric.framework/run
vendored
Executable file
28
External/Mac/Fabric.framework/run
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
# run
|
||||
#
|
||||
# Copyright (c) 2015 Crashlytics. All rights reserved.
|
||||
|
||||
# Figure out where we're being called from
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
# Quote path in case of spaces or special chars
|
||||
DIR="\"${DIR}"
|
||||
|
||||
PATH_SEP="/"
|
||||
VALIDATE_COMMAND="uploadDSYM\" $@ validate"
|
||||
UPLOAD_COMMAND="uploadDSYM\" $@"
|
||||
|
||||
# Ensure params are as expected, run in sync mode to validate
|
||||
eval $DIR$PATH_SEP$VALIDATE_COMMAND
|
||||
return_code=$?
|
||||
|
||||
if [[ $return_code != 0 ]]; then
|
||||
exit $return_code
|
||||
fi
|
||||
|
||||
# Verification passed, upload dSYM in background to prevent Xcode from waiting
|
||||
# Note: Validation is performed again before upload.
|
||||
# Output can still be found in Console.app
|
||||
eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 &
|
||||
BIN
External/Mac/Fabric.framework/uploadDSYM
vendored
Executable file
BIN
External/Mac/Fabric.framework/uploadDSYM
vendored
Executable file
Binary file not shown.
2
External/Pearl
vendored
2
External/Pearl
vendored
Submodule External/Pearl updated: 2237aaf429...adcbc1f10a
@@ -1 +0,0 @@
|
||||
Versions/Current/Crashlytics
|
||||
BIN
External/iOS/Crashlytics.framework/Crashlytics
vendored
Executable file
BIN
External/iOS/Crashlytics.framework/Crashlytics
vendored
Executable file
Binary file not shown.
31
External/iOS/Crashlytics.framework/Headers/ANSCompatibility.h
vendored
Normal file
31
External/iOS/Crashlytics.framework/Headers/ANSCompatibility.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// ANSCompatibility.h
|
||||
// AnswersKit
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !__has_feature(nullability)
|
||||
#define nonnull
|
||||
#define nullable
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_END
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
#if __has_feature(objc_generics)
|
||||
#define ANS_GENERIC_NSARRAY(type) NSArray<type>
|
||||
#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary<key_type, object_key>
|
||||
#else
|
||||
#define ANS_GENERIC_NSARRAY(type) NSArray
|
||||
#define ANS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
|
||||
#endif
|
||||
210
External/iOS/Crashlytics.framework/Headers/Answers.h
vendored
Normal file
210
External/iOS/Crashlytics.framework/Headers/Answers.h
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
//
|
||||
// Answers.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ANSCompatibility.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* This class exposes the Answers Events API, allowing you to track key
|
||||
* user user actions and metrics in your app.
|
||||
*/
|
||||
@interface Answers : NSObject
|
||||
|
||||
/**
|
||||
* Log a Sign Up event to see users signing up for your app in real-time, understand how
|
||||
* many users are signing up with different methods and their success rate signing up.
|
||||
*
|
||||
* @param signUpMethodOrNil The method by which a user logged in, e.g. Twitter or Digits.
|
||||
* @param signUpSucceededOrNil The ultimate success or failure of the login
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logSignUpWithMethod:(nullable NSString *)signUpMethodOrNil
|
||||
success:(nullable NSNumber *)signUpSucceededOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log an Log In event to see users logging into your app in real-time, understand how many
|
||||
* users are logging in with different methods and their success rate logging into your app.
|
||||
*
|
||||
* @param loginMethodOrNil The method by which a user logged in, e.g. email, Twitter or Digits.
|
||||
* @param loginSucceededOrNil The ultimate success or failure of the login
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logLoginWithMethod:(nullable NSString *)loginMethodOrNil
|
||||
success:(nullable NSNumber *)loginSucceededOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Share event to see users sharing from your app in real-time, letting you
|
||||
* understand what content they're sharing from the type or genre down to the specific id.
|
||||
*
|
||||
* @param shareMethodOrNil The method by which a user shared, e.g. email, Twitter, SMS.
|
||||
* @param contentNameOrNil The human readable name for this piece of content.
|
||||
* @param contentTypeOrNil The type of content shared.
|
||||
* @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logShareWithMethod:(nullable NSString *)shareMethodOrNil
|
||||
contentName:(nullable NSString *)contentNameOrNil
|
||||
contentType:(nullable NSString *)contentTypeOrNil
|
||||
contentId:(nullable NSString *)contentIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log an Invite Event to track how users are inviting other users into
|
||||
* your application.
|
||||
*
|
||||
* @param inviteMethodOrNil The method of invitation, e.g. GameCenter, Twitter, email.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logInviteWithMethod:(nullable NSString *)inviteMethodOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Purchase event to see your revenue in real-time, understand how many users are making purchases, see which
|
||||
* items are most popular, and track plenty of other important purchase-related metrics.
|
||||
*
|
||||
* @param itemPriceOrNil The purchased item's price.
|
||||
* @param currencyOrNil The ISO4217 currency code. Example: USD
|
||||
* @param purchaseSucceededOrNil Was the purchase succesful or unsuccesful
|
||||
* @param itemNameOrNil The human-readable form of the item's name. Example:
|
||||
* @param itemIdOrNil The machine-readable, unique item identifier Example: SKU
|
||||
* @param itemTypeOrNil The type, or genre of the item. Example: Song
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logPurchaseWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
|
||||
currency:(nullable NSString *)currencyOrNil
|
||||
success:(nullable NSNumber *)purchaseSucceededOrNil
|
||||
itemName:(nullable NSString *)itemNameOrNil
|
||||
itemType:(nullable NSString *)itemTypeOrNil
|
||||
itemId:(nullable NSString *)itemIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Level Start Event to track where users are in your game.
|
||||
*
|
||||
* @param levelNameOrNil The level name
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this level start event.
|
||||
*/
|
||||
+ (void)logLevelStart:(nullable NSString *)levelNameOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Level End event to track how users are completing levels in your game.
|
||||
*
|
||||
* @param levelNameOrNil The name of the level completed, E.G. "1" or "Training"
|
||||
* @param scoreOrNil The score the user completed the level with.
|
||||
* @param levelCompletedSuccesfullyOrNil A boolean representing whether or not the level was completed succesfully.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logLevelEnd:(nullable NSString *)levelNameOrNil
|
||||
score:(nullable NSNumber *)scoreOrNil
|
||||
success:(nullable NSNumber *)levelCompletedSuccesfullyOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log an Add to Cart event to see users adding items to a shopping cart in real-time, understand how
|
||||
* many users start the purchase flow, see which items are most popular, and track plenty of other important
|
||||
* purchase-related metrics.
|
||||
*
|
||||
* @param itemPriceOrNil The purchased item's price.
|
||||
* @param currencyOrNil The ISO4217 currency code. Example: USD
|
||||
* @param itemNameOrNil The human-readable form of the item's name. Example:
|
||||
* @param itemTypeOrNil The type, or genre of the item. Example: Song
|
||||
* @param itemIdOrNil The machine-readable, unique item identifier Example: SKU
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logAddToCartWithPrice:(nullable NSDecimalNumber *)itemPriceOrNil
|
||||
currency:(nullable NSString *)currencyOrNil
|
||||
itemName:(nullable NSString *)itemNameOrNil
|
||||
itemType:(nullable NSString *)itemTypeOrNil
|
||||
itemId:(nullable NSString *)itemIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Start Checkout event to see users moving through the purchase funnel in real-time, understand how many
|
||||
* users are doing this and how much they're spending per checkout, and see how it related to other important
|
||||
* purchase-related metrics.
|
||||
*
|
||||
* @param totalPriceOrNil The total price of the cart.
|
||||
* @param currencyOrNil The ISO4217 currency code. Example: USD
|
||||
* @param itemCountOrNil The number of items in the cart.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase.
|
||||
*/
|
||||
+ (void)logStartCheckoutWithPrice:(nullable NSDecimalNumber *)totalPriceOrNil
|
||||
currency:(nullable NSString *)currencyOrNil
|
||||
itemCount:(nullable NSNumber *)itemCountOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Rating event to see users rating content within your app in real-time and understand what
|
||||
* content is most engaging, from the type or genre down to the specific id.
|
||||
*
|
||||
* @param ratingOrNil The integer rating given by the user.
|
||||
* @param contentNameOrNil The human readable name for this piece of content.
|
||||
* @param contentTypeOrNil The type of content shared.
|
||||
* @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logRating:(nullable NSNumber *)ratingOrNil
|
||||
contentName:(nullable NSString *)contentNameOrNil
|
||||
contentType:(nullable NSString *)contentTypeOrNil
|
||||
contentId:(nullable NSString *)contentIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Content View event to see users viewing content within your app in real-time and
|
||||
* understand what content is most engaging, from the type or genre down to the specific id.
|
||||
*
|
||||
* @param contentNameOrNil The human readable name for this piece of content.
|
||||
* @param contentTypeOrNil The type of content shared.
|
||||
* @param contentIdOrNil The unique identifier for this piece of content. Useful for finding the top shared item.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logContentViewWithName:(nullable NSString *)contentNameOrNil
|
||||
contentType:(nullable NSString *)contentTypeOrNil
|
||||
contentId:(nullable NSString *)contentIdOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Search event allows you to see users searching within your app in real-time and understand
|
||||
* exactly what they're searching for.
|
||||
*
|
||||
* @param queryOrNil The user's query.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this event.
|
||||
*/
|
||||
+ (void)logSearchWithQuery:(nullable NSString *)queryOrNil
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
/**
|
||||
* Log a Custom Event to see user actions that are uniquely important for your app in real-time, to see how often
|
||||
* they're performing these actions with breakdowns by different categories you add. Use a human-readable name for
|
||||
* the name of the event, since this is how the event will appear in Answers.
|
||||
*
|
||||
* @param eventName The human-readable name for the event.
|
||||
* @param customAttributesOrNil A dictionary of custom attributes to associate with this purchase. Attribute keys
|
||||
* must be <code>NSString</code> and and values must be <code>NSNumber</code> or <code>NSString</code>.
|
||||
* @discussion How we treat <code>NSNumbers</code>:
|
||||
* We will provide information about the distribution of values over time.
|
||||
*
|
||||
* How we treat <code>NSStrings</code>:
|
||||
* NSStrings are used as categorical data, allowing comparison across different category values.
|
||||
* Strings are limited to a maximum length of 100 characters, attributes over this length will be
|
||||
* truncated.
|
||||
*
|
||||
* When tracking the Tweet views to better understand user engagement, sending the tweet's length
|
||||
* and the type of media present in the tweet allows you to track how tweet length and the type of media influence
|
||||
* engagement.
|
||||
*/
|
||||
+ (void)logCustomEventWithName:(NSString *)eventName
|
||||
customAttributes:(nullable ANS_GENERIC_NSDICTIONARY(NSString *, id) *)customAttributesOrNil;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
33
External/iOS/Crashlytics.framework/Headers/CLSAttributes.h
vendored
Normal file
33
External/iOS/Crashlytics.framework/Headers/CLSAttributes.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// CLSAttributes.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CLS_DEPRECATED(x) __attribute__ ((deprecated(x)))
|
||||
|
||||
#if !__has_feature(nullability)
|
||||
#define nonnull
|
||||
#define nullable
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_END
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
#if __has_feature(objc_generics)
|
||||
#define CLS_GENERIC_NSARRAY(type) NSArray<type>
|
||||
#define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary<key_type, object_key>
|
||||
#else
|
||||
#define CLS_GENERIC_NSARRAY(type) NSArray
|
||||
#define CLS_GENERIC_NSDICTIONARY(key_type,object_key) NSDictionary
|
||||
#endif
|
||||
64
External/iOS/Crashlytics.framework/Headers/CLSLogging.h
vendored
Normal file
64
External/iOS/Crashlytics.framework/Headers/CLSLogging.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// CLSLogging.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
#ifdef __OBJC__
|
||||
#import "CLSAttributes.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The CLS_LOG macro provides as easy way to gather more information in your log messages that are
|
||||
* sent with your crash data. CLS_LOG prepends your custom log message with the function name and
|
||||
* line number where the macro was used. If your app was built with the DEBUG preprocessor macro
|
||||
* defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog.
|
||||
* If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only.
|
||||
*
|
||||
* Example output:
|
||||
* -[AppDelegate login:] line 134 $ login start
|
||||
*
|
||||
* If you would like to change this macro, create a new header file, unset our define and then define
|
||||
* your own version. Make sure this new header file is imported after the Crashlytics header file.
|
||||
*
|
||||
* #undef CLS_LOG
|
||||
* #define CLS_LOG(__FORMAT__, ...) CLSNSLog...
|
||||
*
|
||||
**/
|
||||
#ifdef __OBJC__
|
||||
#ifdef DEBUG
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will not show up in the system.log
|
||||
* and will only be visible in your Crashlytics dashboard.
|
||||
*
|
||||
**/
|
||||
|
||||
#ifdef __OBJC__
|
||||
OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will show up in the system.log
|
||||
* and your Crashlytics dashboard. It is not recommended for Release builds.
|
||||
*
|
||||
**/
|
||||
OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSNSLogv(NSString *format, va_list ap) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
103
External/iOS/Crashlytics.framework/Headers/CLSReport.h
vendored
Normal file
103
External/iOS/Crashlytics.framework/Headers/CLSReport.h
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// CLSReport.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "CLSAttributes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
* The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate changes for details.
|
||||
**/
|
||||
@protocol CLSCrashReport <NSObject>
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *identifier;
|
||||
@property (nonatomic, copy, readonly) NSDictionary *customKeys;
|
||||
@property (nonatomic, copy, readonly) NSString *bundleVersion;
|
||||
@property (nonatomic, copy, readonly) NSString *bundleShortVersionString;
|
||||
@property (nonatomic, copy, readonly) NSDate *crashedOnDate;
|
||||
@property (nonatomic, copy, readonly) NSString *OSVersion;
|
||||
@property (nonatomic, copy, readonly) NSString *OSBuildVersion;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can
|
||||
* use this class to get information about the event, and can also set some values after the
|
||||
* event has occured.
|
||||
**/
|
||||
@interface CLSReport : NSObject <CLSCrashReport>
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Returns the session identifier for the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *identifier;
|
||||
|
||||
/**
|
||||
* Returns the custom key value data for the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSDictionary *customKeys;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleVersion of the application that generated the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *bundleVersion;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleShortVersionString of the application that generated the report.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *bundleShortVersionString;
|
||||
|
||||
/**
|
||||
* Returns the date that the report was created.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSDate *dateCreated;
|
||||
|
||||
/**
|
||||
* Returns the os version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *OSVersion;
|
||||
|
||||
/**
|
||||
* Returns the os build version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, copy, readonly) NSString *OSBuildVersion;
|
||||
|
||||
/**
|
||||
* Returns YES if the report contains any crash information, otherwise returns NO.
|
||||
**/
|
||||
@property (nonatomic, assign, readonly) BOOL isCrash;
|
||||
|
||||
/**
|
||||
* You can use this method to set, after the event, additional custom keys. The rules
|
||||
* and semantics for this method are the same as those documented in Crashlytics.h. Be aware
|
||||
* that the maximum size and count of custom keys is still enforced, and you can overwrite keys
|
||||
* and/or cause excess keys to be deleted by using this method.
|
||||
**/
|
||||
- (void)setObjectValue:(nullable id)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Record an application-specific user identifier. See Crashlytics.h for details.
|
||||
**/
|
||||
@property (nonatomic, copy, nullable) NSString * userIdentifier;
|
||||
|
||||
/**
|
||||
* Record a user name. See Crashlytics.h for details.
|
||||
**/
|
||||
@property (nonatomic, copy, nullable) NSString * userName;
|
||||
|
||||
/**
|
||||
* Record a user email. See Crashlytics.h for details.
|
||||
**/
|
||||
@property (nonatomic, copy, nullable) NSString * userEmail;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
37
External/iOS/Crashlytics.framework/Headers/CLSStackFrame.h
vendored
Normal file
37
External/iOS/Crashlytics.framework/Headers/CLSStackFrame.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// CLSStackFrame.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "CLSAttributes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
*
|
||||
* This class is used in conjunction with -[Crashlytics recordCustomExceptionName:reason:frameArray:] to
|
||||
* record information about non-ObjC/C++ exceptions. All information included here will be displayed
|
||||
* in the Crashlytics UI, and can influence crash grouping. Be particularly careful with the use of the
|
||||
* address property. If set, Crashlytics will attempt symbolication and could overwrite other properities
|
||||
* in the process.
|
||||
*
|
||||
**/
|
||||
@interface CLSStackFrame : NSObject
|
||||
|
||||
+ (instancetype)stackFrame;
|
||||
+ (instancetype)stackFrameWithAddress:(NSUInteger)address;
|
||||
+ (instancetype)stackFrameWithSymbol:(NSString *)symbol;
|
||||
|
||||
@property (nonatomic, copy, nullable) NSString *symbol;
|
||||
@property (nonatomic, copy, nullable) NSString *library;
|
||||
@property (nonatomic, copy, nullable) NSString *fileName;
|
||||
@property (nonatomic, assign) uint32_t lineNumber;
|
||||
@property (nonatomic, assign) uint64_t offset;
|
||||
@property (nonatomic, assign) uint64_t address;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
248
External/iOS/Crashlytics.framework/Headers/Crashlytics.h
vendored
Normal file
248
External/iOS/Crashlytics.framework/Headers/Crashlytics.h
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// Crashlytics.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright (c) 2015 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "CLSAttributes.h"
|
||||
#import "CLSLogging.h"
|
||||
#import "CLSReport.h"
|
||||
#import "CLSStackFrame.h"
|
||||
#import "Answers.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol CrashlyticsDelegate;
|
||||
|
||||
/**
|
||||
* Crashlytics. Handles configuration and initialization of Crashlytics.
|
||||
*/
|
||||
@interface Crashlytics : NSObject
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *APIKey;
|
||||
@property (nonatomic, readonly, copy) NSString *version;
|
||||
@property (nonatomic, assign) BOOL debugMode;
|
||||
|
||||
/**
|
||||
*
|
||||
* The delegate can be used to influence decisions on reporting and behavior, as well as reacting
|
||||
* to previous crashes.
|
||||
*
|
||||
* Make certain that the delegate is setup before starting Crashlytics with startWithAPIKey:... or
|
||||
* via +[Fabric with:...]. Failure to do will result in missing any delegate callbacks that occur
|
||||
* synchronously during start.
|
||||
*
|
||||
**/
|
||||
@property (nonatomic, assign, nullable) id <CrashlyticsDelegate> delegate;
|
||||
|
||||
/**
|
||||
* The recommended way to install Crashlytics into your application is to place a call to +startWithAPIKey:
|
||||
* in your -application:didFinishLaunchingWithOptions: or -applicationDidFinishLaunching:
|
||||
* method.
|
||||
*
|
||||
* Note: Starting with 3.0, the submission process has been significantly improved. The delay parameter
|
||||
* is no longer required to throttle submissions on launch, performance will be great without it.
|
||||
*
|
||||
* @param apiKey The Crashlytics API Key for this app
|
||||
*
|
||||
* @return The singleton Crashlytics instance
|
||||
*/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey: instead.");
|
||||
|
||||
/**
|
||||
* If you need the functionality provided by the CrashlyticsDelegate protocol, you can use
|
||||
* these convenience methods to activate the framework and set the delegate in one call.
|
||||
*
|
||||
* @param apiKey The Crashlytics API Key for this app
|
||||
* @param delegate A delegate object which conforms to CrashlyticsDelegate.
|
||||
*
|
||||
* @return The singleton Crashlytics instance
|
||||
*/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id<CrashlyticsDelegate>)delegate;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(nullable id<CrashlyticsDelegate>)delegate afterDelay:(NSTimeInterval)delay CLS_DEPRECATED("Crashlytics no longer needs or uses the delay parameter. Please use +startWithAPIKey:delegate: instead.");
|
||||
|
||||
/**
|
||||
* Access the singleton Crashlytics instance.
|
||||
*
|
||||
* @return The singleton Crashlytics instance
|
||||
*/
|
||||
+ (Crashlytics *)sharedInstance;
|
||||
|
||||
/**
|
||||
* The easiest way to cause a crash - great for testing!
|
||||
*/
|
||||
- (void)crash;
|
||||
|
||||
/**
|
||||
* The easiest way to cause a crash with an exception - great for testing.
|
||||
*/
|
||||
- (void)throwException;
|
||||
|
||||
/**
|
||||
* Specify a user identifier which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* Many of our customers have requested the ability to tie crashes to specific end-users of their
|
||||
* application in order to facilitate responses to support requests or permit the ability to reach
|
||||
* out for more information. We allow you to specify up to three separate values for display within
|
||||
* the Crashlytics UI - but please be mindful of your end-user's privacy.
|
||||
*
|
||||
* We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record
|
||||
* in your system. This could be a database id, hash, or other value that is meaningless to a
|
||||
* third-party observer but can be indexed and queried by you.
|
||||
*
|
||||
* Optionally, you may also specify the end-user's name or username, as well as email address if you
|
||||
* do not have a system that works well with obscured identifiers.
|
||||
*
|
||||
* Pursuant to our EULA, this data is transferred securely throughout our system and we will not
|
||||
* disseminate end-user data unless required to by law. That said, if you choose to provide end-user
|
||||
* contact information, we strongly recommend that you disclose this in your application's privacy
|
||||
* policy. Data privacy is of our utmost concern.
|
||||
*
|
||||
* @param identifier An arbitrary user identifier string which ties an end-user to a record in your system.
|
||||
*/
|
||||
- (void)setUserIdentifier:(nullable NSString *)identifier;
|
||||
|
||||
/**
|
||||
* Specify a user name which will be visible in the Crashlytics UI.
|
||||
* Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs.
|
||||
* @see setUserIdentifier:
|
||||
*
|
||||
* @param name An end user's name.
|
||||
*/
|
||||
- (void)setUserName:(nullable NSString *)name;
|
||||
|
||||
/**
|
||||
* Specify a user email which will be visible in the Crashlytics UI.
|
||||
* Please be mindful of your end-user's privacy and see if setUserIdentifier: can fulfil your needs.
|
||||
*
|
||||
* @see setUserIdentifier:
|
||||
*
|
||||
* @param email An end user's email address.
|
||||
*/
|
||||
- (void)setUserEmail:(nullable NSString *)email;
|
||||
|
||||
+ (void)setUserIdentifier:(nullable NSString *)identifier CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setUserName:(nullable NSString *)name CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setUserEmail:(nullable NSString *)email CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
|
||||
/**
|
||||
* Set a value for a for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
* When setting an object value, the object is converted to a string. This is typically done by calling
|
||||
* -[NSObject description].
|
||||
*
|
||||
* @param value The object to be associated with the key
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setObjectValue:(nullable id)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Set an int value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* @param value The integer value to be set
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setIntValue:(int)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Set an BOOL value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* @param value The BOOL value to be set
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* Set an float value for a key to be associated with your crash data which will be visible in the Crashlytics UI.
|
||||
*
|
||||
* @param value The float value to be set
|
||||
* @param key The key with which to associate the value
|
||||
*/
|
||||
- (void)setFloatValue:(float)value forKey:(NSString *)key;
|
||||
|
||||
+ (void)setObjectValue:(nullable id)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setIntValue:(int)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
+ (void)setFloatValue:(float)value forKey:(NSString *)key CLS_DEPRECATED("Please access this method via +sharedInstance");
|
||||
|
||||
/**
|
||||
* This method can be used to record a single exception structure in a report. This is particularly useful
|
||||
* when your code interacts with non-native languages like Lua, C#, or Javascript. This call can be
|
||||
* expensive and should only be used shortly before process termination. This API is not intended be to used
|
||||
* to log NSException objects. All safely-reportable NSExceptions are automatically captured by
|
||||
* Crashlytics.
|
||||
*
|
||||
* @param name The name of the custom exception
|
||||
* @param reason The reason this exception occured
|
||||
* @param frameArray An array of CLSStackFrame objects
|
||||
*/
|
||||
- (void)recordCustomExceptionName:(NSString *)name reason:(nullable NSString *)reason frameArray:(CLS_GENERIC_NSARRAY(CLSStackFrame *) *)frameArray;
|
||||
|
||||
- (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
- (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
+ (void)logEvent:(NSString *)eventName CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
+ (void)logEvent:(NSString *)eventName attributes:(nullable NSDictionary *) attributes CLS_DEPRECATED("Please refer to Answers +logCustomEventWithName:");
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
*
|
||||
* The CrashlyticsDelegate protocol provides a mechanism for your application to take
|
||||
* action on events that occur in the Crashlytics crash reporting system. You can make
|
||||
* use of these calls by assigning an object to the Crashlytics' delegate property directly,
|
||||
* or through the convenience +startWithAPIKey:delegate: method.
|
||||
*
|
||||
*/
|
||||
@protocol CrashlyticsDelegate <NSObject>
|
||||
@optional
|
||||
|
||||
|
||||
- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:");
|
||||
- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash CLS_DEPRECATED("Please refer to -crashlyticsDidDetectReportForLastExecution:");
|
||||
|
||||
/**
|
||||
*
|
||||
* Called when a Crashlytics instance has determined that the last execution of the
|
||||
* application ended in a crash. This is called synchronously on Crashlytics
|
||||
* initialization. Your delegate must invoke the completionHandler, but does not need to do so
|
||||
* synchronously, or even on the main thread. Invoking completionHandler with NO will cause the
|
||||
* detected report to be deleted and not submitted to Crashlytics. This is useful for
|
||||
* implementing permission prompts, or other more-complex forms of logic around submitting crashes.
|
||||
*
|
||||
* @warning Failure to invoke the completionHandler will prevent submissions from being reported. Watch out.
|
||||
*
|
||||
* @warning Just implementing this delegate method will disable all forms of synchronous report submission. This can
|
||||
* impact the reliability of reporting crashes very early in application launch.
|
||||
*
|
||||
* @param report The CLSReport object representing the last detected crash
|
||||
* @param completionHandler The completion handler to call when your logic has completed.
|
||||
*
|
||||
*/
|
||||
- (void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report completionHandler:(void (^)(BOOL submit))completionHandler;
|
||||
|
||||
/**
|
||||
* If your app is running on an OS that supports it (OS X 10.9+, iOS 7.0+), Crashlytics will submit
|
||||
* most reports using out-of-process background networking operations. This results in a significant
|
||||
* improvement in reliability of reporting, as well as power and performance wins for your users.
|
||||
* If you don't want this functionality, you can disable by returning NO from this method.
|
||||
*
|
||||
* @warning Background submission is not supported for extensions on iOS or OS X.
|
||||
*
|
||||
* @param crashlytics The Crashlytics singleton instance
|
||||
*
|
||||
* @return Return NO if you don't want out-of-process background network operations.
|
||||
*
|
||||
*/
|
||||
- (BOOL)crashlyticsCanUseBackgroundSessions:(Crashlytics *)crashlytics;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* `CrashlyticsKit` can be used as a parameter to `[Fabric with:@[CrashlyticsKit]];` in Objective-C. In Swift, use Crashlytics.sharedInstance()
|
||||
*/
|
||||
#define CrashlyticsKit [Crashlytics sharedInstance]
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
55
External/iOS/Crashlytics.framework/Info.plist
vendored
Normal file
55
External/iOS/Crashlytics.framework/Info.plist
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>14F1021</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Crashlytics</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.twitter.crashlytics.ios</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Crashlytics</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.4.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>92</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>13B137</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>9.1</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>13B137</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>iphoneos9.1</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0710</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>7B91b</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2015 Crashlytics, Inc. All rights reserved.</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,14 @@
|
||||
framework module Crashlytics {
|
||||
umbrella header "Crashlytics.h"
|
||||
header "Crashlytics.h"
|
||||
header "Answers.h"
|
||||
header "ANSCompatibility.h"
|
||||
header "CLSLogging.h"
|
||||
header "CLSReport.h"
|
||||
header "CLSStackFrame.h"
|
||||
header "CLSAttributes.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
export *
|
||||
|
||||
link "z"
|
||||
link "c++"
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,220 +0,0 @@
|
||||
//
|
||||
// Crashlytics.h
|
||||
// Crashlytics
|
||||
//
|
||||
// Copyright 2013 Crashlytics, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* The CLS_LOG macro provides as easy way to gather more information in your log messages that are
|
||||
* sent with your crash data. CLS_LOG prepends your custom log message with the function name and
|
||||
* line number where the macro was used. If your app was built with the DEBUG preprocessor macro
|
||||
* defined CLS_LOG uses the CLSNSLog function which forwards your log message to NSLog and CLSLog.
|
||||
* If the DEBUG preprocessor macro is not defined CLS_LOG uses CLSLog only.
|
||||
*
|
||||
* Example output:
|
||||
* -[AppDelegate login:] line 134 $ login start
|
||||
*
|
||||
* If you would like to change this macro, create a new header file, unset our define and then define
|
||||
* your own version. Make sure this new header file is imported after the Crashlytics header file.
|
||||
*
|
||||
* #undef CLS_LOG
|
||||
* #define CLS_LOG(__FORMAT__, ...) CLSNSLog...
|
||||
*
|
||||
**/
|
||||
#ifdef DEBUG
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will not show up in the system.log
|
||||
* and will only be visible in your Crashlytics dashboard.
|
||||
*
|
||||
**/
|
||||
OBJC_EXTERN void CLSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
/**
|
||||
*
|
||||
* Add logging that will be sent with your crash data. This logging will show up in the system.log
|
||||
* and your Crashlytics dashboard. It is not recommended for Release builds.
|
||||
*
|
||||
**/
|
||||
OBJC_EXTERN void CLSNSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
|
||||
OBJC_EXTERN void CLSNSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0);
|
||||
|
||||
|
||||
@protocol CrashlyticsDelegate;
|
||||
|
||||
@interface Crashlytics : NSObject
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *apiKey;
|
||||
@property (nonatomic, readonly, copy) NSString *version;
|
||||
@property (nonatomic, assign) BOOL debugMode;
|
||||
|
||||
@property (nonatomic, assign) NSObject <CrashlyticsDelegate> *delegate;
|
||||
|
||||
/**
|
||||
*
|
||||
* The recommended way to install Crashlytics into your application is to place a call
|
||||
* to +startWithAPIKey: in your -application:didFinishLaunchingWithOptions: method.
|
||||
*
|
||||
* This delay defaults to 1 second in order to generally give the application time to
|
||||
* fully finish launching.
|
||||
*
|
||||
**/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay;
|
||||
|
||||
/**
|
||||
*
|
||||
* If you need the functionality provided by the CrashlyticsDelegate protocol, you can use
|
||||
* these convenience methods to activate the framework and set the delegate in one call.
|
||||
*
|
||||
**/
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject <CrashlyticsDelegate> *)delegate;
|
||||
+ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject <CrashlyticsDelegate> *)delegate afterDelay:(NSTimeInterval)delay;
|
||||
|
||||
/**
|
||||
*
|
||||
* Access the singleton Crashlytics instance.
|
||||
*
|
||||
**/
|
||||
+ (Crashlytics *)sharedInstance;
|
||||
|
||||
/**
|
||||
*
|
||||
* The easiest way to cause a crash - great for testing!
|
||||
*
|
||||
**/
|
||||
- (void)crash;
|
||||
|
||||
/**
|
||||
*
|
||||
* Many of our customers have requested the ability to tie crashes to specific end-users of their
|
||||
* application in order to facilitate responses to support requests or permit the ability to reach
|
||||
* out for more information. We allow you to specify up to three separate values for display within
|
||||
* the Crashlytics UI - but please be mindful of your end-user's privacy.
|
||||
*
|
||||
* We recommend specifying a user identifier - an arbitrary string that ties an end-user to a record
|
||||
* in your system. This could be a database id, hash, or other value that is meaningless to a
|
||||
* third-party observer but can be indexed and queried by you.
|
||||
*
|
||||
* Optionally, you may also specify the end-user's name or username, as well as email address if you
|
||||
* do not have a system that works well with obscured identifiers.
|
||||
*
|
||||
* Pursuant to our EULA, this data is transferred securely throughout our system and we will not
|
||||
* disseminate end-user data unless required to by law. That said, if you choose to provide end-user
|
||||
* contact information, we strongly recommend that you disclose this in your application's privacy
|
||||
* policy. Data privacy is of our utmost concern.
|
||||
*
|
||||
**/
|
||||
- (void)setUserIdentifier:(NSString *)identifier;
|
||||
- (void)setUserName:(NSString *)name;
|
||||
- (void)setUserEmail:(NSString *)email;
|
||||
|
||||
+ (void)setUserIdentifier:(NSString *)identifier;
|
||||
+ (void)setUserName:(NSString *)name;
|
||||
+ (void)setUserEmail:(NSString *)email;
|
||||
|
||||
/**
|
||||
*
|
||||
* Set a value for a key to be associated with your crash data.
|
||||
*
|
||||
**/
|
||||
- (void)setObjectValue:(id)value forKey:(NSString *)key;
|
||||
- (void)setIntValue:(int)value forKey:(NSString *)key;
|
||||
- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
|
||||
- (void)setFloatValue:(float)value forKey:(NSString *)key;
|
||||
|
||||
+ (void)setObjectValue:(id)value forKey:(NSString *)key;
|
||||
+ (void)setIntValue:(int)value forKey:(NSString *)key;
|
||||
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
|
||||
+ (void)setFloatValue:(float)value forKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* The CLSCrashReport protocol exposes methods that you can call on crash report objects passed
|
||||
* to delegate methods. If you want these values or the entire object to stay in memory retain
|
||||
* them or copy them.
|
||||
**/
|
||||
@protocol CLSCrashReport <NSObject>
|
||||
@required
|
||||
|
||||
/**
|
||||
* Returns the session identifier for the crash report.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *identifier;
|
||||
|
||||
/**
|
||||
* Returns the custom key value data for the crash report.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSDictionary *customKeys;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleVersion of the application that crashed.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *bundleVersion;
|
||||
|
||||
/**
|
||||
* Returns the CFBundleShortVersionString of the application that crashed.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *bundleShortVersionString;
|
||||
|
||||
/**
|
||||
* Returns the date that the application crashed at.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSDate *crashedOnDate;
|
||||
|
||||
/**
|
||||
* Returns the os version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *OSVersion;
|
||||
|
||||
/**
|
||||
* Returns the os build version that the application crashed on.
|
||||
**/
|
||||
@property (nonatomic, readonly) NSString *OSBuildVersion;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
*
|
||||
* The CrashlyticsDelegate protocol provides a mechanism for your application to take
|
||||
* action on events that occur in the Crashlytics crash reporting system. You can make
|
||||
* use of these calls by assigning an object to the Crashlytics' delegate property directly,
|
||||
* or through the convenience startWithAPIKey:delegate:... methods.
|
||||
*
|
||||
**/
|
||||
@protocol CrashlyticsDelegate <NSObject>
|
||||
@optional
|
||||
|
||||
/**
|
||||
*
|
||||
* Called once a Crashlytics instance has determined that the last execution of the
|
||||
* application ended in a crash. This is called some time after the crash reporting
|
||||
* process has begun. If you have specified a delay in one of the
|
||||
* startWithAPIKey:... calls, this will take at least that long to be invoked.
|
||||
*
|
||||
**/
|
||||
- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics;
|
||||
|
||||
/**
|
||||
*
|
||||
* Just like crashlyticsDidDetectCrashDuringPreviousExecution this delegate method is
|
||||
* called once a Crashlytics instance has determined that the last execution of the
|
||||
* application ended in a crash. A CLSCrashReport is passed back that contains data about
|
||||
* the last crash report that was generated. See the CLSCrashReport protocol for method details.
|
||||
* This method is called after crashlyticsDidDetectCrashDuringPreviousExecution.
|
||||
*
|
||||
**/
|
||||
- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id <CLSCrashReport>)crash;
|
||||
|
||||
@end
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Crashlytics</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.crashlytics.ios</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Crashlytics</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.2.5</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>40</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>4.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
External/iOS/Crashlytics.framework/run
vendored
BIN
External/iOS/Crashlytics.framework/run
vendored
Binary file not shown.
BIN
External/iOS/Crashlytics.framework/submit
vendored
BIN
External/iOS/Crashlytics.framework/submit
vendored
Binary file not shown.
BIN
External/iOS/Crashlytics.framework/uploadDSYM
vendored
Executable file
BIN
External/iOS/Crashlytics.framework/uploadDSYM
vendored
Executable file
Binary file not shown.
BIN
External/iOS/Fabric.framework/Fabric
vendored
Executable file
BIN
External/iOS/Fabric.framework/Fabric
vendored
Executable file
Binary file not shown.
48
External/iOS/Fabric.framework/Headers/FABAttributes.h
vendored
Normal file
48
External/iOS/Fabric.framework/Headers/FABAttributes.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// FABAttributes.h
|
||||
// Fabric
|
||||
//
|
||||
// Copyright (c) 2015 Twitter. All rights reserved.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define FAB_UNAVAILABLE(x) __attribute__((unavailable(x)))
|
||||
|
||||
#if __has_feature(nullability)
|
||||
#define fab_nullable nullable
|
||||
#define fab_nonnull nonnull
|
||||
#define fab_null_unspecified null_unspecified
|
||||
#define fab_null_resettable null_resettable
|
||||
#define __fab_nullable __nullable
|
||||
#define __fab_nonnull __nonnull
|
||||
#define __fab_null_unspecified __null_unspecified
|
||||
#else
|
||||
#define fab_nullable
|
||||
#define fab_nonnull
|
||||
#define fab_null_unspecified
|
||||
#define fab_null_resettable
|
||||
#define __fab_nullable
|
||||
#define __fab_nonnull
|
||||
#define __fab_null_unspecified
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_BEGIN
|
||||
#define NS_ASSUME_NONNULL_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef NS_ASSUME_NONNULL_END
|
||||
#define NS_ASSUME_NONNULL_END
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* The following macros are defined here to provide
|
||||
* backwards compatability. If you are still using
|
||||
* them you should migrate to the new versions that
|
||||
* are defined above.
|
||||
*/
|
||||
#define FAB_NONNULL __fab_nonnull
|
||||
#define FAB_NULLABLE __fab_nullable
|
||||
#define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN
|
||||
#define FAB_END_NONNULL NS_ASSUME_NONNULL_END
|
||||
64
External/iOS/Fabric.framework/Headers/Fabric.h
vendored
Normal file
64
External/iOS/Fabric.framework/Headers/Fabric.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Fabric.h
|
||||
//
|
||||
// Copyright (c) 2015 Twitter. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FABAttributes.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
|
||||
#error "Fabric's minimum iOS version is 6.0"
|
||||
#endif
|
||||
#else
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070
|
||||
#error "Fabric's minimum OS X version is 10.7"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Fabric Base. Coordinates configuration and starts all provided kits.
|
||||
*/
|
||||
@interface Fabric : NSObject
|
||||
|
||||
/**
|
||||
* Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use.
|
||||
*
|
||||
* For example, in Objective-C:
|
||||
*
|
||||
* `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];`
|
||||
*
|
||||
* Swift:
|
||||
*
|
||||
* `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])`
|
||||
*
|
||||
* Only the first call to this method is honored. Subsequent calls are no-ops.
|
||||
*
|
||||
* @param kitClasses An array of kit Class objects
|
||||
*
|
||||
* @return Returns the shared Fabric instance. In most cases this can be ignored.
|
||||
*/
|
||||
+ (instancetype)with:(NSArray *)kitClasses;
|
||||
|
||||
/**
|
||||
* Returns the Fabric singleton object.
|
||||
*/
|
||||
+ (instancetype)sharedSDK;
|
||||
|
||||
/**
|
||||
* This BOOL enables or disables debug logging, such as kit version information. The default value is NO.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL debug;
|
||||
|
||||
/**
|
||||
* Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance.
|
||||
*/
|
||||
- (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance.");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
55
External/iOS/Fabric.framework/Info.plist
vendored
Normal file
55
External/iOS/Fabric.framework/Info.plist
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>14F1021</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Fabric</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.fabric.sdk.ios</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Fabric</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.6.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>37</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>13B137</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphoneos</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>9.1</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>13B137</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>iphoneos9.1</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0710</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>7B91b</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2015 Twitter. All rights reserved.</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
6
External/iOS/Fabric.framework/Modules/module.modulemap
vendored
Normal file
6
External/iOS/Fabric.framework/Modules/module.modulemap
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
framework module Fabric {
|
||||
umbrella header "Fabric.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
28
External/iOS/Fabric.framework/run
vendored
Executable file
28
External/iOS/Fabric.framework/run
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
# run
|
||||
#
|
||||
# Copyright (c) 2015 Crashlytics. All rights reserved.
|
||||
|
||||
# Figure out where we're being called from
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
# Quote path in case of spaces or special chars
|
||||
DIR="\"${DIR}"
|
||||
|
||||
PATH_SEP="/"
|
||||
VALIDATE_COMMAND="uploadDSYM\" $@ validate"
|
||||
UPLOAD_COMMAND="uploadDSYM\" $@"
|
||||
|
||||
# Ensure params are as expected, run in sync mode to validate
|
||||
eval $DIR$PATH_SEP$VALIDATE_COMMAND
|
||||
return_code=$?
|
||||
|
||||
if [[ $return_code != 0 ]]; then
|
||||
exit $return_code
|
||||
fi
|
||||
|
||||
# Verification passed, upload dSYM in background to prevent Xcode from waiting
|
||||
# Note: Validation is performed again before upload.
|
||||
# Output can still be found in Console.app
|
||||
eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 &
|
||||
BIN
External/iOS/Fabric.framework/uploadDSYM
vendored
Executable file
BIN
External/iOS/Fabric.framework/uploadDSYM
vendored
Executable file
Binary file not shown.
1
External/iOS/Reveal.framework
vendored
Symbolic link
1
External/iOS/Reveal.framework
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/Reveal.framework
|
||||
1
External/iOS/Reveal.framework/Headers
vendored
1
External/iOS/Reveal.framework/Headers
vendored
@@ -1 +0,0 @@
|
||||
Versions/Current/Headers
|
||||
1
External/iOS/Reveal.framework/Reveal
vendored
1
External/iOS/Reveal.framework/Reveal
vendored
@@ -1 +0,0 @@
|
||||
Versions/Current/Reveal
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2013 Itty Bitty Apps. All rights reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString * const IBARevealLoaderRequestStartNotification;
|
||||
extern NSString * const IBARevealLoaderRequestStopNotification;
|
||||
|
||||
extern NSString * const IBARevealLoaderSetOptionsNotification;
|
||||
extern NSString * const IBARevealLoaderOptionsLogLevelMaskKey;
|
||||
|
||||
@interface IBARevealLoader : NSObject
|
||||
|
||||
+ (void)startServer;
|
||||
+ (void)stopServer;
|
||||
|
||||
@end
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright (c) 2013 Itty Bitty Apps Pty Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
CF_EXTERN_C_BEGIN
|
||||
|
||||
/*!
|
||||
\brief The Reveal Log level bit flags.
|
||||
\discussion These flags are additive. i.e. you should bitwise OR them together.
|
||||
|
||||
\seealso IBARevealLoggerSetLevelMask
|
||||
\seealso IBARevealLoggerGetLevelMask
|
||||
|
||||
Example:
|
||||
|
||||
// Enable Error, Warning and Info logger levels.
|
||||
IBARevealLoggerSetLevelMask(IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo);
|
||||
|
||||
*/
|
||||
typedef NS_OPTIONS(int32_t, IBARevealLogLevel)
|
||||
{
|
||||
IBARevealLogLevelNone = 0,
|
||||
IBARevealLogLevelDebug = (1 << 0),
|
||||
IBARevealLogLevelInfo = (1 << 1),
|
||||
IBARevealLogLevelWarn = (1 << 2),
|
||||
IBARevealLogLevelError = (1 << 3)
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Set the Reveal logger level mask.
|
||||
\param mask A bit mask which is a combination of the IBARevealLogLevel enum options.
|
||||
|
||||
\discussion If you do not wish to see log messages from Reveal you should call this function with an appropriate level mask as early in your application's lifecycle as possible. For example in your application's main() function.
|
||||
|
||||
Example:
|
||||
|
||||
// Enable Error, Warning and Info logger levels.
|
||||
IBARevealLoggerSetLevelMask(IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo);
|
||||
|
||||
*/
|
||||
CF_EXPORT void IBARevealLoggerSetLevelMask(int32_t mask);
|
||||
|
||||
/*!
|
||||
\brief Get the current Reveal logger level mask.
|
||||
\return A bit mask representing the levels at which Reveal is currently logging.
|
||||
\discussion The default Reveal Logger level mask is IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo.
|
||||
|
||||
Example:
|
||||
|
||||
// Turn off the Info log level.
|
||||
IBARevealLoggerSetLevelMask(IBARevealLoggerGetLevelMask() & ~IBARevealLogLevelInfo);
|
||||
|
||||
*/
|
||||
CF_EXPORT int32_t IBARevealLoggerGetLevelMask(void);
|
||||
|
||||
CF_EXTERN_C_END
|
||||
@@ -1,5 +0,0 @@
|
||||
// Copyright (c) 2013 Itty Bitty Apps Pty Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
#import "IBARevealLogger.h"
|
||||
#import "IBARevealLoader.h"
|
||||
BIN
External/iOS/Reveal.framework/Versions/A/Reveal
vendored
BIN
External/iOS/Reveal.framework/Versions/A/Reveal
vendored
Binary file not shown.
@@ -1 +0,0 @@
|
||||
A
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "F788B28042EDBEF29EFE34687DA79A778C2CC260",
|
||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
|
||||
|
||||
},
|
||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
|
||||
"304AD0F97EA7B4893D91DFB8C3413D4E627B9472" : 0,
|
||||
"2A70319CE0F91B35406CA7D970AE7CB4957B0A75" : 0,
|
||||
"8A15A8EA0B3D0B497C4883425BC74DF995224BB3" : 0,
|
||||
"1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA" : 0,
|
||||
"1AA8C0BE-EEC3-4FBC-A801-8939A1AC093A" : 0,
|
||||
"3E67FB08419C920516AAC3B00DAAF23073B8CF77" : 0,
|
||||
"3ED8592497DB6A564366943C9AAD5A46341B5076" : 0,
|
||||
"4DDCFFD91B41F00326AD14553BD66CFD366ABD91" : 0,
|
||||
"E47DEC29CB0D0FDE3560EF46E1808FA1C723D657" : 0,
|
||||
"2FE140B36B7D26140DC8D5E5C639DC5900EFCF35" : 0,
|
||||
"F788B28042EDBEF29EFE34687DA79A778C2CC260" : 0
|
||||
},
|
||||
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "1DC75A27-0030-4493-ACE8-E1D49AB9A549",
|
||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
|
||||
"304AD0F97EA7B4893D91DFB8C3413D4E627B9472" : "MasterPassword\/External\/KCOrderedAccessorFix",
|
||||
"2A70319CE0F91B35406CA7D970AE7CB4957B0A75" : "",
|
||||
"8A15A8EA0B3D0B497C4883425BC74DF995224BB3" : "MasterPassword\/External\/Pearl\/External\/jrswizzle",
|
||||
"1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA" : "MasterPassword\/External\/InAppSettingsKit",
|
||||
"1AA8C0BE-EEC3-4FBC-A801-8939A1AC093A" : "MasterPassword\/External\/LoveLyndir",
|
||||
"3E67FB08419C920516AAC3B00DAAF23073B8CF77" : "MasterPassword\/External\/RHStatusItemView",
|
||||
"3ED8592497DB6A564366943C9AAD5A46341B5076" : "MasterPassword\/External\/AttributedMarkdown",
|
||||
"4DDCFFD91B41F00326AD14553BD66CFD366ABD91" : "MasterPassword\/External\/Pearl",
|
||||
"E47DEC29CB0D0FDE3560EF46E1808FA1C723D657" : "MasterPassword\/External\/UbiquityStoreManager",
|
||||
"2FE140B36B7D26140DC8D5E5C639DC5900EFCF35" : "MasterPassword\/External\/Pearl\/External\/uicolor-utilities",
|
||||
"F788B28042EDBEF29EFE34687DA79A778C2CC260" : "MasterPassword"
|
||||
},
|
||||
"DVTSourceControlWorkspaceBlueprintNameKey" : "MasterPassword",
|
||||
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
|
||||
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "MasterPassword.xcworkspace",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/lhunath\/InAppSettingsKit.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "1712FC0BC3C9AABD8B7B5376E310E93FBDB3BCFA"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/Lyndir\/love-lyndir.client.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "1AA8C0BE-EEC3-4FBC-A801-8939A1AC093A"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:Lyndir\/Lyndir.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "2A70319CE0F91B35406CA7D970AE7CB4957B0A75"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/lhunath\/uicolor-utilities.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "2FE140B36B7D26140DC8D5E5C639DC5900EFCF35"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/CFKevinRef\/KCOrderedAccessorFix.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "304AD0F97EA7B4893D91DFB8C3413D4E627B9472"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/lhunath\/RHStatusItemView.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "3E67FB08419C920516AAC3B00DAAF23073B8CF77"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/dreamwieber\/AttributedMarkdown.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "3ED8592497DB6A564366943C9AAD5A46341B5076"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "ssh:\/\/github.com\/Lyndir\/Pearl.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "4DDCFFD91B41F00326AD14553BD66CFD366ABD91"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/jonmarimba\/jrswizzle.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8A15A8EA0B3D0B497C4883425BC74DF995224BB3"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git:\/\/github.com\/lhunath\/UbiquityStoreManager.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "E47DEC29CB0D0FDE3560EF46E1808FA1C723D657"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "ssh:\/\/github.com\/Lyndir\/MasterPassword.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "F788B28042EDBEF29EFE34687DA79A778C2CC260"
|
||||
}
|
||||
]
|
||||
}
|
||||
61
MasterPassword/C/bashcomplib
Normal file
61
MasterPassword/C/bashcomplib
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# FIXME
|
||||
# partials are currently readline words, but these can't be reliably compared against literal data. We need to make them literal first.. in a safe way. Currently using xargs' quote parser as a hack.
|
||||
|
||||
# Process literal completion options in COMPREPLY
|
||||
#
|
||||
# 1. Filter COMPREPLY by excluding the options that do not match the word that is being completed.
|
||||
# 2. Shell-escape the COMPREPLY words so they remain syntactical words when injected into the completed command.
|
||||
# 3. Add a space after the words so successful completions advance to the next word
|
||||
# (we disabled this default behavior with -o nospace so we can do completions that don't want this, eg. directory names)
|
||||
_comp_finish_completions() {
|
||||
local partial=$(xargs <<< "${COMP_WORDS[COMP_CWORD]}") # FIXME
|
||||
local word words=( "${COMPREPLY[@]}" )
|
||||
|
||||
COMPREPLY=()
|
||||
for word in "${words[@]}"; do
|
||||
( shopt -s nocasematch; [[ $word = $partial* ]] ) && COMPREPLY+=( "$(printf '%q ' "$word")" )
|
||||
done
|
||||
|
||||
if (( ${#COMPREPLY[@]} > 1 )) && [[ $_comp_title ]]; then
|
||||
printf '\n%s:' "$_comp_title"
|
||||
unset _comp_title
|
||||
fi
|
||||
}
|
||||
|
||||
# Perform pathname completion.
|
||||
#
|
||||
# 1. Populate COMPREPLY with pathnames.
|
||||
# 2. Shell-escape the COMPREPLY words so they remain syntactical words when injected into the completed command.
|
||||
# 3. Add a space after file names so successful completions advance to the next word.
|
||||
# Directory names are suffixed with a / instead so we can keep completing the files inside.
|
||||
_comp_complete_path() {
|
||||
local partial=$(xargs <<< "${COMP_WORDS[COMP_CWORD]}")
|
||||
local path
|
||||
|
||||
COMPREPLY=()
|
||||
for path in "$partial"*; do
|
||||
if [[ -d $path ]]; then
|
||||
COMPREPLY+=( "$(printf '%q/' "$path")" )
|
||||
|
||||
elif [[ -e $path ]]; then
|
||||
COMPREPLY+=( "$(printf '%q ' "$path")" )
|
||||
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_show_args() {
|
||||
echo
|
||||
local i=0
|
||||
for arg; do
|
||||
printf "arg %d: %s\n" "$((i++))" "$arg"
|
||||
done
|
||||
|
||||
i=0
|
||||
for word in "${COMP_WORDS[@]}"; do
|
||||
printf "word %d: %s -> %s %s\n" "$i" "$word" "$(xargs <<< "$word")" "$( ((i == $COMP_CWORD)) && echo '<CWORD>' )"
|
||||
let i++
|
||||
done
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
# ______________________________________________________________________
|
||||
# | |
|
||||
# | .:: TABLE OF CONTENTS ::. |
|
||||
# | .: TABLE OF CONTENTS :. |
|
||||
# |______________________________________________________________________|
|
||||
#
|
||||
# chr decimal
|
||||
@@ -66,12 +66,6 @@
|
||||
# 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.
|
||||
@@ -132,7 +126,7 @@ _tocHash=71e13f42e1ea82c1c7019b27a3bc71f3
|
||||
|
||||
# ______________________________________________________________________
|
||||
# | |
|
||||
# | .:: GLOBAL CONFIGURATION ::. |
|
||||
# | .: GLOBAL CONFIGURATION :. |
|
||||
# |______________________________________________________________________|
|
||||
|
||||
# Unset all exported functions. Exported functions are evil.
|
||||
@@ -177,7 +171,7 @@ genToc() {
|
||||
|
||||
# ______________________________________________________________________
|
||||
# | |
|
||||
# | .:: GLOBAL DECLARATIONS ::. |
|
||||
# | .: GLOBAL DECLARATIONS :. |
|
||||
# |______________________________________________________________________|
|
||||
|
||||
# Variables for convenience sequences.
|
||||
@@ -190,8 +184,8 @@ runner=( '> >' \
|
||||
|
||||
# Variables for terminal requests.
|
||||
[[ -t 2 && $TERM != dumb ]] && {
|
||||
COLUMNS=$( tput cols || tput co ) # Columns in a line
|
||||
LINES=$( tput lines || tput li ) # Lines on screen
|
||||
COLUMNS=$({ tput cols || tput co;} 2>&3) # Columns in a line
|
||||
LINES=$({ tput lines || tput li;} 2>&3) # 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
|
||||
@@ -230,7 +224,7 @@ runner=( '> >' \
|
||||
tput eA; tput as;
|
||||
tput ac; tput ae; } ) # Drawing characters
|
||||
back=$'\b'
|
||||
} 2>/dev/null ||:
|
||||
} 3>&2 2>/dev/null ||:
|
||||
|
||||
|
||||
|
||||
@@ -238,7 +232,7 @@ runner=( '> >' \
|
||||
|
||||
# ______________________________________________________________________
|
||||
# | |
|
||||
# | .:: FUNCTION DECLARATIONS ::. |
|
||||
# | .: FUNCTION DECLARATIONS :. |
|
||||
# |______________________________________________________________________|
|
||||
|
||||
|
||||
@@ -465,23 +459,6 @@ readwhile() {
|
||||
|
||||
|
||||
|
||||
# __________________________________________________________________________
|
||||
# |__ 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"
|
||||
} # _____________________________________________________________________
|
||||
|
||||
|
||||
|
||||
# ______________________________________________________________________
|
||||
# |__ Latest ____________________________________________________________|
|
||||
#
|
||||
@@ -1566,7 +1543,7 @@ stackTrace() {
|
||||
|
||||
# ______________________________________________________________________
|
||||
# | |
|
||||
# | .:: ENTRY POINT ::. |
|
||||
# | .: ENTRY POINT :. |
|
||||
# |______________________________________________________________________|
|
||||
|
||||
# Make sure this file is sourced and not executed.
|
||||
@@ -1586,6 +1563,6 @@ stackTrace() {
|
||||
}
|
||||
|
||||
:
|
||||
: .:: END SOURCING ::.
|
||||
: .: END SOURCING :.
|
||||
: ______________________________________________________________________
|
||||
:
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
# try ./build -lrt instead.
|
||||
# - If you see 'x86.S:202: Error: junk at end of line, first unrecognized character is `,'',
|
||||
# try commenting the line in lib/bcrypt/x86.S.
|
||||
# - Take a look at the "Optional features" section. Some features have dependencies,
|
||||
# either make sure you have them or disable those features.
|
||||
#
|
||||
# BUGS
|
||||
# masterpassword@lyndir.com
|
||||
@@ -31,10 +33,21 @@ else
|
||||
# Modify here or override using targets='mpw mpw-bench' ./build
|
||||
targets=(
|
||||
mpw # C CLI version of Master Password.
|
||||
#mpw-bench # C CLI Master Password benchmark utility.
|
||||
mpw-bench # C CLI Master Password benchmark utility.
|
||||
mpw-tests # C Master Password algorithm tester.
|
||||
)
|
||||
fi
|
||||
|
||||
# Optional features.
|
||||
mpw_color=1 # Colorized Identicon, requires libncurses-dev
|
||||
|
||||
# Distribution specific configuration.
|
||||
# Homebrew
|
||||
if hash brew 2>/dev/null; then
|
||||
opensslPath=$(brew --prefix openssl)
|
||||
export CFLAGS="$CFLAGS -I$opensslPath/include"
|
||||
export LDFLAGS="$LDFLAGS -L$opensslPath/lib"
|
||||
fi
|
||||
|
||||
### DEPENDENCIES
|
||||
|
||||
@@ -49,6 +62,14 @@ fetch() {
|
||||
fi
|
||||
}
|
||||
unpack() {
|
||||
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
||||
[[ $(digest "$1") = $2 ]] || {
|
||||
printf ' mismatch!\n'
|
||||
echo 2>&1 "Downloaded package doesn't match digest."
|
||||
exit 1
|
||||
}
|
||||
printf ' OK!\n'
|
||||
|
||||
if [[ $1 = *.tar.gz || $1 = *.tgz ]]; then
|
||||
tar -xvzf "$1"
|
||||
|
||||
@@ -62,62 +83,58 @@ unpack() {
|
||||
echo 2>&1 "Don't know how to unpack: $1"
|
||||
fi
|
||||
|
||||
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
||||
[[ $(digest "$1") = $2 ]] || {
|
||||
printf ' mismatch!\n'
|
||||
echo 2>&1 "Downloaded package doesn't match digest."
|
||||
exit 1
|
||||
}
|
||||
printf ' OK!\n'
|
||||
|
||||
files=( !("$1") )
|
||||
files=( * )
|
||||
if [[ -d $files ]] && (( ${#files[@]} == 1 )); then
|
||||
mv "$files"/* .
|
||||
rmdir "$files"
|
||||
fi
|
||||
}
|
||||
fetchSource() (
|
||||
local name=${PWD##*/}
|
||||
source .source
|
||||
|
||||
if [[ $pkg && -e "${pkg##*/}" ]]; then
|
||||
files=( !("${pkg##*/}") )
|
||||
[[ -e $files ]] || {
|
||||
if [[ -e .unpacked ]]; then
|
||||
true
|
||||
|
||||
elif [[ $pkg && -e "${pkg##*/}" ]]; then
|
||||
[[ -e src ]] || {
|
||||
echo
|
||||
echo "Unpacking: ${PWD##*/}, using package..."
|
||||
unpack "${pkg##*/}" "$pkg_sha256"
|
||||
echo "Unpacking: $name, using package..."
|
||||
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $git ]] && hash git 2>/dev/null; then
|
||||
[[ -e .git ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using git..."
|
||||
git clone "$svn" .
|
||||
printf '%s' "$(git describe --always)" > "${PWD##*/}-version"
|
||||
echo "Fetching: $name, using git..."
|
||||
git clone "$git" src
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $svn ]] && hash git 2>/dev/null && [[ -x "$(git --exec-path)/git-svn" ]]; then
|
||||
[[ -e .git ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using git-svn..."
|
||||
git svn clone --prefix=origin/ --stdlayout "$svn" .
|
||||
printf '%s' "$(git describe --always)" > "${PWD##*/}-version"
|
||||
echo "Fetching: $name, using git-svn..."
|
||||
git svn clone --prefix=origin/ --stdlayout "$svn" src
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $svn ]] && hash svn 2>/dev/null; then
|
||||
[[ -e .svn ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using svn..."
|
||||
svn checkout "$svn/trunk" .
|
||||
printf 'r%s' "$(svn info | awk '/^Revision:/{ print $2 }')" > "${PWD##*/}-version"
|
||||
echo "Fetching: $name, using svn..."
|
||||
svn checkout "$svn/trunk" src
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
elif [[ $pkg ]]; then
|
||||
files=( !("${pkg##*/}") )
|
||||
[[ -e $files ]] || {
|
||||
[[ -e src ]] || {
|
||||
echo
|
||||
echo "Fetching: ${PWD##*/}, using package..."
|
||||
echo "Fetching: $name, using package..."
|
||||
fetch "$pkg"
|
||||
unpack "${pkg##*/}" "$pkg_sha256"
|
||||
( mkdir src && cd src && unpack "../${pkg##*/}" "$pkg_sha256" )
|
||||
touch .unpacked
|
||||
}
|
||||
|
||||
else
|
||||
@@ -125,26 +142,39 @@ fetchSource() (
|
||||
echo >&2 "error: Missing git-svn or svn."
|
||||
echo >&2 "error: Please install either or manually check out the sources"
|
||||
echo >&2 "error: from: $home"
|
||||
echo >&2 "error: into: $PWD"
|
||||
echo >&2 "error: into: $PWD/src"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -e .patched ]] && (( ${#patches[@]} )); then
|
||||
pushd src
|
||||
for patch in "${patches[@]}"; do
|
||||
echo
|
||||
echo "Patching: $name, for $patch..."
|
||||
patch -p0 < "../$patch.patch"
|
||||
done
|
||||
popd
|
||||
touch .patched
|
||||
fi
|
||||
)
|
||||
depend() {
|
||||
local name=$1
|
||||
|
||||
echo
|
||||
echo "Checking dependency: $1..."
|
||||
[[ -e "lib/$1/.built" ]] && return
|
||||
echo "Checking dependency: $name..."
|
||||
[[ -e "lib/include/$name" ]] && return
|
||||
|
||||
pushd "lib/$1"
|
||||
pushd "lib/$name"
|
||||
fetchSource
|
||||
pushd "src"
|
||||
|
||||
echo
|
||||
echo "Configuring dependency: $1..."
|
||||
echo "Configuring dependency: $name..."
|
||||
if [[ -e configure.ac ]]; then
|
||||
if [[ ! -e configure ]]; then
|
||||
# create configure using autotools.
|
||||
if ! hash aclocal || ! hash automake; then
|
||||
echo >&2 "Need autotools to build $1. Please install automake and autoconf."
|
||||
echo >&2 "Need autotools to build $name. Please install automake and autoconf."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -161,20 +191,22 @@ depend() {
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Building dependency: $1..."
|
||||
echo "Building dependency: $name..."
|
||||
if [[ -e Makefile ]]; then
|
||||
if ! hash make; then
|
||||
echo >&2 "Need make to build $1. Please install GNU make."
|
||||
echo >&2 "Need make to build $name. Please install GNU make."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make
|
||||
date > .built
|
||||
install -d "../../include/$name/"
|
||||
find . -name '*.h' -exec install -m 444 {} "../../include/$name/" \;
|
||||
else
|
||||
echo >&2 "error: Don't know how to build: $1"
|
||||
echo >&2 "error: Don't know how to build: $name"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
popd
|
||||
}
|
||||
|
||||
|
||||
@@ -184,26 +216,27 @@ mpw() {
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
CFLAGS=(
|
||||
local CFLAGS=(
|
||||
# include paths
|
||||
-I"lib/scrypt/lib" -I"lib/scrypt/libcperciva"
|
||||
-I"lib/include"
|
||||
)
|
||||
LDFLAGS=(
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt"
|
||||
# link libraries
|
||||
-l"crypto" -l"curses"
|
||||
local LDFLAGS=(
|
||||
# scrypt
|
||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||
"lib/scrypt/scrypt-sha256.o"
|
||||
"lib/scrypt/scrypt-crypto_scrypt-nosse.o"
|
||||
"lib/scrypt/scrypt-memlimit.o"
|
||||
"lib/scrypt/scrypt-scryptenc_cpuperf.o"
|
||||
"lib/scrypt/scrypt-scryptenc.o"
|
||||
"lib/scrypt/src/libcperciva/"*/*.o
|
||||
"lib/scrypt/src/lib/crypto/"*.o
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt/src"
|
||||
# link libraries
|
||||
-l"crypto"
|
||||
)
|
||||
# optional features
|
||||
(( mpw_color )) && CFLAGS+=( -DCOLOR ) LDFLAGS+=( -l"curses" )
|
||||
|
||||
cc "${CFLAGS[@]}" -c types.c -o types.o "$@"
|
||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" mpw.c -o mpw "$@"
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-types.c -o mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-util.c -o mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "mpw-cli.c" -o "mpw"
|
||||
echo "done! Now run ./install or use ./mpw"
|
||||
}
|
||||
|
||||
@@ -215,37 +248,67 @@ mpw-bench() {
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
CFLAGS=(
|
||||
local CFLAGS=(
|
||||
# include paths
|
||||
-I"lib/scrypt/lib" -I"lib/scrypt/libcperciva"
|
||||
-I"lib/bcrypt"
|
||||
-I"lib/include"
|
||||
)
|
||||
LDFLAGS=(
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt"
|
||||
-L"lib/bcrypt"
|
||||
# libraries
|
||||
-l"crypto"
|
||||
local LDFLAGS=(
|
||||
# scrypt
|
||||
"lib/scrypt/scrypt-crypto_aesctr.o"
|
||||
"lib/scrypt/scrypt-sha256.o"
|
||||
"lib/scrypt/scrypt-crypto_scrypt-nosse.o"
|
||||
"lib/scrypt/scrypt-memlimit.o"
|
||||
"lib/scrypt/scrypt-scryptenc_cpuperf.o"
|
||||
"lib/scrypt/scrypt-scryptenc.o"
|
||||
"lib/scrypt/src/libcperciva/"*/*.o
|
||||
"lib/scrypt/src/lib/crypto/"*.o
|
||||
# bcrypt
|
||||
"lib/bcrypt/crypt_blowfish.o"
|
||||
"lib/bcrypt/crypt_gensalt.o"
|
||||
"lib/bcrypt/wrapper.o"
|
||||
"lib/bcrypt/x86.o"
|
||||
"lib/bcrypt/src/crypt_blowfish.o"
|
||||
"lib/bcrypt/src/crypt_gensalt.o"
|
||||
"lib/bcrypt/src/wrapper.o"
|
||||
"lib/bcrypt/src/x86.o"
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt/src"
|
||||
-L"lib/bcrypt/src"
|
||||
# link libraries
|
||||
-l"crypto"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" -c types.c -o types.o "$@"
|
||||
cc "${CFLAGS[@]}" "${LDFLAGS[@]}" "types.o" mpw-bench.c -o mpw-bench "$@"
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-types.c -o mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-util.c -o mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "mpw-bench.c" -o "mpw-bench"
|
||||
echo "done! Now use ./mpw-bench"
|
||||
}
|
||||
|
||||
|
||||
### MPW-TESTS
|
||||
mpw-tests() {
|
||||
depend scrypt
|
||||
|
||||
echo
|
||||
echo "Building target: $target..."
|
||||
local CFLAGS=(
|
||||
# include paths
|
||||
-I"lib/include"
|
||||
-I"/usr/include/libxml2"
|
||||
-I"/usr/local/include/libxml2"
|
||||
)
|
||||
local LDFLAGS=(
|
||||
# scrypt
|
||||
"lib/scrypt/src/libcperciva/"*/*.o
|
||||
"lib/scrypt/src/lib/crypto/"*.o
|
||||
# library paths
|
||||
-L"." -L"lib/scrypt/src"
|
||||
# link libraries
|
||||
-l"crypto" -l"xml2"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-algorithm.c -o mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-types.c -o mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-util.c -o mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c mpw-tests-util.c -o mpw-tests-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "mpw-algorithm.o" "mpw-types.o" "mpw-util.o" "mpw-tests-util.o" \
|
||||
"${LDFLAGS[@]}" "mpw-tests.c" -o "mpw-tests"
|
||||
echo "done! Now use ./mpw-tests"
|
||||
}
|
||||
|
||||
|
||||
### TARGETS
|
||||
|
||||
haslib() {
|
||||
|
||||
7
MasterPassword/C/clean
Executable file
7
MasterPassword/C/clean
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Clean all generated build files.
|
||||
set -e
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
|
||||
rm -vfr lib/*/{.unpacked,.patched,src} lib/include
|
||||
@@ -4,14 +4,14 @@ set -e
|
||||
cd "${BASH_SOURCE%/*}"
|
||||
tag=$(git describe)
|
||||
commit=$(git describe --long --dirty)
|
||||
[[ $tag && $commit = $tag-* ]] || exit 1
|
||||
[[ $tag && $commit = $tag* ]] || exit 1
|
||||
git show --show-signature --pretty=format:%H --quiet "$tag" > VERSION
|
||||
|
||||
mpwArchive=mpw-$commit.tar.gz
|
||||
[[ -e $mpwArchive ]] && echo "WARNING: $mpwArchive already exists. Will overwrite."
|
||||
read -n1 -p "Will prepare and release $mpwArchive. Press a key to continue or ^C to abort."
|
||||
|
||||
git ls-files -z . | xargs -0 tar -cvzf "$mpwArchive"
|
||||
git ls-files -z . | xargs -0 tar -Lcvzf "$mpwArchive"
|
||||
echo "$mpwArchive ready, SHA256: $(openssl sha -sha256 < "$mpwArchive")"
|
||||
|
||||
cd ../../Site/current
|
||||
|
||||
@@ -45,8 +45,8 @@ fi
|
||||
echo
|
||||
|
||||
inf "You can also save your user name in ~/.bashrc. Leave blank to skip this step."
|
||||
if MP_USERNAME=$(ask "Your full name:") && [[ $MP_USERNAME ]] ; then
|
||||
printf 'export MP_USERNAME=%q\n' "$MP_USERNAME" >> ~/.bashrc
|
||||
if MP_FULLNAME=$(ask "Your full name:") && [[ $MP_FULLNAME ]] ; then
|
||||
printf 'export MP_FULLNAME=%q\n' "$MP_FULLNAME" >> ~/.bashrc
|
||||
fi
|
||||
echo
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
home=http://www.openwall.com/crypt/
|
||||
pkg=http://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz
|
||||
pkg_sha256=83fa01fca6996fe8d882b7f8e9ba0305a5664936100b01481ea3c6a8ce8d72fd
|
||||
patches=(arm)
|
||||
|
||||
12
MasterPassword/C/lib/bcrypt/arm.patch
Normal file
12
MasterPassword/C/lib/bcrypt/arm.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
--- x86.S 2014-11-21 09:09:58.000000000 -0500
|
||||
+++ x86.S 2014-11-21 09:11:01.000000000 -0500
|
||||
@@ -199,5 +199,9 @@
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
+#if defined(__arm__)
|
||||
+.section .note.GNU-stack,"",%progbits
|
||||
+#else
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
||||
+#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
home=https://code.google.com/p/scrypt/
|
||||
svn=http://scrypt.googlecode.com/svn
|
||||
pkg=http://masterpasswordapp.com/libscrypt-b12b554.tar.gz
|
||||
pkg_sha256=c726daec68a345e420896f005394a948dc5a6924713ed94b684c856d4c247f0b
|
||||
home=http://www.tarsnap.com/scrypt.html
|
||||
git=https://github.com/Tarsnap/scrypt.git
|
||||
pkg=http://www.tarsnap.com/scrypt/scrypt-1.2.0.tgz
|
||||
pkg_sha256=1754bc89405277c8ac14220377a4c240ddc34b1ce70882aa92cd01bfdc8569d4
|
||||
|
||||
53
MasterPassword/C/mpw-algorithm.c
Normal file
53
MasterPassword/C/mpw-algorithm.c
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-algorithm_v0.c"
|
||||
#include "mpw-algorithm_v1.c"
|
||||
#include "mpw-algorithm_v2.c"
|
||||
#include "mpw-algorithm_v3.c"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
const uint8_t *mpw_masterKeyForUser(const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
switch (algorithmVersion) {
|
||||
case MPAlgorithmVersion0:
|
||||
return mpw_masterKeyForUser_v0( fullName, masterPassword );
|
||||
case MPAlgorithmVersion1:
|
||||
return mpw_masterKeyForUser_v1( fullName, masterPassword );
|
||||
case MPAlgorithmVersion2:
|
||||
return mpw_masterKeyForUser_v2( fullName, masterPassword );
|
||||
case MPAlgorithmVersion3:
|
||||
return mpw_masterKeyForUser_v3( fullName, masterPassword );
|
||||
default:
|
||||
ftl( "Unsupported version: %d", algorithmVersion );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char *mpw_passwordForSite(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion) {
|
||||
|
||||
switch (algorithmVersion) {
|
||||
case MPAlgorithmVersion0:
|
||||
return mpw_passwordForSite_v0( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
case MPAlgorithmVersion1:
|
||||
return mpw_passwordForSite_v1( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
case MPAlgorithmVersion2:
|
||||
return mpw_passwordForSite_v2( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
case MPAlgorithmVersion3:
|
||||
return mpw_passwordForSite_v3( masterKey, siteName, siteType, siteCounter, siteVariant, siteContext );
|
||||
default:
|
||||
ftl( "Unsupported version: %d", algorithmVersion );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
33
MasterPassword/C/mpw-algorithm.h
Normal file
33
MasterPassword/C/mpw-algorithm.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// mpw-algorithm.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
// NOTE: mpw is currently NOT thread-safe.
|
||||
#include "mpw-types.h"
|
||||
|
||||
typedef enum(unsigned int, MPAlgorithmVersion) {
|
||||
/** V0 did math with chars whose signedness was platform-dependent. */
|
||||
MPAlgorithmVersion0,
|
||||
/** V1 miscounted the byte-length of multi-byte site names. */
|
||||
MPAlgorithmVersion1,
|
||||
/** V2 miscounted the byte-length of multi-byte user names. */
|
||||
MPAlgorithmVersion2,
|
||||
/** V3 is the current version. */
|
||||
MPAlgorithmVersion3,
|
||||
};
|
||||
#define MPAlgorithmVersionCurrent MPAlgorithmVersion3
|
||||
|
||||
/** Derive the master key for a user based on their name and master password.
|
||||
* @return A new MP_dkLen-byte allocated buffer or NULL if an allocation error occurred. */
|
||||
const uint8_t *mpw_masterKeyForUser(
|
||||
const char *fullName, const char *masterPassword, const MPAlgorithmVersion algorithmVersion);
|
||||
|
||||
/** Encode a password for the site from the given master key and site parameters.
|
||||
* @return A newly allocated string or NULL if an allocation error occurred. */
|
||||
const char *mpw_passwordForSite(
|
||||
const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext, const MPAlgorithmVersion algorithmVersion);
|
||||
130
MasterPassword/C/mpw-algorithm_v0.c
Normal file
130
MasterPassword/C/mpw-algorithm_v0.c
Normal file
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const char *mpw_templateForType_v0(MPSiteType type, uint16_t seedByte) {
|
||||
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
if (!count)
|
||||
return NULL;
|
||||
|
||||
return templates[seedByte % count];
|
||||
}
|
||||
|
||||
static const char mpw_characterFromClass_v0(char characterClass, uint16_t seedByte) {
|
||||
|
||||
const char *classCharacters = mpw_charactersInClass( characterClass );
|
||||
return classCharacters[seedByte % strlen( classCharacters )];
|
||||
}
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v0(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 0 );
|
||||
trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( mpw_charlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v0(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "algorithm: v%d\n", 0 );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||
mpw_hex_l( htonl( siteCounter ) ),
|
||||
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const char *sitePasswordSeed = (const char *)mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType_v0( siteType, htons( sitePasswordSeed[0] ) );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass_v0( template[c], htons( sitePasswordSeed[c + 1] ) );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n",
|
||||
template[c], htons( sitePasswordSeed[c + 1] ), htons( sitePasswordSeed[c + 1] ), sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
114
MasterPassword/C/mpw-algorithm_v1.c
Normal file
114
MasterPassword/C/mpw-algorithm_v1.c
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v1(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 1 );
|
||||
trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( mpw_charlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v1(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "algorithm: v%d\n", 1 );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||
mpw_hex_l( htonl( siteCounter ) ),
|
||||
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( mpw_charlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
114
MasterPassword/C/mpw-algorithm_v2.c
Normal file
114
MasterPassword/C/mpw-algorithm_v2.c
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v2(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 2 );
|
||||
trc( "fullName: %s (%zu)\n", fullName, mpw_charlen( fullName ) );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( mpw_charlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v2(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "algorithm: v%d\n", 2 );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||
mpw_hex_l( htonl( siteCounter ) ),
|
||||
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
114
MasterPassword/C/mpw-algorithm_v3.c
Normal file
114
MasterPassword/C/mpw-algorithm_v3.c
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// mpw-algorithm.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static const uint8_t *mpw_masterKeyForUser_v3(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *mpKeyScope = mpw_scopeForVariant( MPSiteVariantPassword );
|
||||
trc( "algorithm: v%d\n", 3 );
|
||||
trc( "fullName: %s (%zu)\n", fullName, strlen( fullName ) );
|
||||
trc( "masterPassword: %s\n", masterPassword );
|
||||
trc( "key scope: %s\n", mpKeyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
// masterKeySalt = mpKeyScope . #fullName . fullName
|
||||
size_t masterKeySaltSize = 0;
|
||||
uint8_t *masterKeySalt = NULL;
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, mpKeyScope );
|
||||
mpw_pushInt( &masterKeySalt, &masterKeySaltSize, htonl( strlen( fullName ) ) );
|
||||
mpw_pushString( &masterKeySalt, &masterKeySaltSize, fullName );
|
||||
if (!masterKeySalt) {
|
||||
ftl( "Could not allocate master key salt: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKeySalt ID: %s\n", mpw_idForBuf( masterKeySalt, masterKeySaltSize ) );
|
||||
|
||||
// Calculate the master key.
|
||||
// masterKey = scrypt( masterPassword, masterKeySalt )
|
||||
const uint8_t *masterKey = mpw_scrypt( MP_dkLen, masterPassword, masterKeySalt, masterKeySaltSize, MP_N, MP_r, MP_p );
|
||||
mpw_free( masterKeySalt, masterKeySaltSize );
|
||||
if (!masterKey) {
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "masterKey ID: %s\n", mpw_idForBuf( masterKey, MP_dkLen ) );
|
||||
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
static const char *mpw_passwordForSite_v3(const uint8_t *masterKey, const char *siteName, const MPSiteType siteType, const uint32_t siteCounter,
|
||||
const MPSiteVariant siteVariant, const char *siteContext) {
|
||||
|
||||
const char *siteScope = mpw_scopeForVariant( siteVariant );
|
||||
trc( "algorithm: v%d\n", 3 );
|
||||
trc( "siteName: %s\n", siteName );
|
||||
trc( "siteCounter: %d\n", siteCounter );
|
||||
trc( "siteVariant: %d\n", siteVariant );
|
||||
trc( "siteType: %d\n", siteType );
|
||||
trc( "site scope: %s, context: %s\n", siteScope, siteContext? "<empty>": siteContext );
|
||||
trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n",
|
||||
siteScope, mpw_hex_l( htonl( strlen( siteName ) ) ), siteName,
|
||||
mpw_hex_l( htonl( siteCounter ) ),
|
||||
mpw_hex_l( htonl( siteContext? strlen( siteContext ): 0 ) ), siteContext? "(null)": siteContext );
|
||||
|
||||
// Calculate the site seed.
|
||||
// sitePasswordSeed = hmac-sha256( masterKey, siteScope . #siteName . siteName . siteCounter . #siteContext . siteContext )
|
||||
size_t sitePasswordInfoSize = 0;
|
||||
uint8_t *sitePasswordInfo = NULL;
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteScope );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteName ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteName );
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( siteCounter ) );
|
||||
if (siteContext) {
|
||||
mpw_pushInt( &sitePasswordInfo, &sitePasswordInfoSize, htonl( strlen( siteContext ) ) );
|
||||
mpw_pushString( &sitePasswordInfo, &sitePasswordInfoSize, siteContext );
|
||||
}
|
||||
if (!sitePasswordInfo) {
|
||||
ftl( "Could not allocate site seed info: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordInfo ID: %s\n", mpw_idForBuf( sitePasswordInfo, sitePasswordInfoSize ) );
|
||||
|
||||
const uint8_t *sitePasswordSeed = mpw_hmac_sha256( masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoSize );
|
||||
mpw_free( sitePasswordInfo, sitePasswordInfoSize );
|
||||
if (!sitePasswordSeed) {
|
||||
ftl( "Could not allocate site seed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
trc( "sitePasswordSeed ID: %s\n", mpw_idForBuf( sitePasswordSeed, 32 ) );
|
||||
|
||||
// Determine the template.
|
||||
const char *template = mpw_templateForType( siteType, sitePasswordSeed[0] );
|
||||
trc( "type %d, template: %s\n", siteType, template );
|
||||
if (strlen( template ) > 32) {
|
||||
ftl( "Template too long for password seed: %lu", strlen( template ) );
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
char *const sitePassword = calloc( strlen( template ) + 1, sizeof( char ) );
|
||||
for (size_t c = 0; c < strlen( template ); ++c) {
|
||||
sitePassword[c] = mpw_characterFromClass( template[c], sitePasswordSeed[c + 1] );
|
||||
trc( "class %c, index %u (0x%02X) -> character: %c\n", template[c], sitePasswordSeed[c + 1], sitePasswordSeed[c + 1],
|
||||
sitePassword[c] );
|
||||
}
|
||||
mpw_free( sitePasswordSeed, sizeof( sitePasswordSeed ) );
|
||||
|
||||
return sitePassword;
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
#include <sys/time.h>
|
||||
//
|
||||
// mpw-bench.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <pwd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <alg/sha256.h>
|
||||
#include <crypto/crypto_scrypt.h>
|
||||
#include <ow-crypt.h>
|
||||
#include "types.h"
|
||||
#include <scrypt/sha256.h>
|
||||
#include <bcrypt/ow-crypt.h>
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
@@ -22,166 +23,84 @@
|
||||
#define MP_dkLen 64
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
static void mpw_getTime(struct timeval *time) {
|
||||
|
||||
if (gettimeofday( time, NULL ) != 0)
|
||||
ftl( "Could not get time: %d\n", errno );
|
||||
}
|
||||
|
||||
static const double mpw_showSpeed(struct timeval startTime, const unsigned int iterations, const char *operation) {
|
||||
|
||||
struct timeval endTime;
|
||||
mpw_getTime( &endTime );
|
||||
|
||||
const time_t dsec = (endTime.tv_sec - startTime.tv_sec);
|
||||
const suseconds_t dusec = (endTime.tv_usec - startTime.tv_usec);
|
||||
const double elapsed = dsec + dusec / 1000000.;
|
||||
const double speed = iterations / elapsed;
|
||||
|
||||
fprintf( stderr, " done. " );
|
||||
fprintf( stdout, "%d %s iterations in %llds %lldµs -> %.2f/s\n", iterations, operation, (long long)dsec, (long long)dusec, speed );
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
int main(int argc, char *const argv[]) {
|
||||
|
||||
char *userName = "Robert Lee Mitchel";
|
||||
char *masterPassword = "banana colored duckling";
|
||||
char *siteName = "masterpasswordapp.com";
|
||||
uint32_t siteCounter = 1;
|
||||
MPElementType siteType = MPElementTypeGeneratedLong;
|
||||
|
||||
// Start MP
|
||||
const char *fullName = "Robert Lee Mitchel";
|
||||
const char *masterPassword = "banana colored duckling";
|
||||
const char *siteName = "masterpasswordapp.com";
|
||||
const uint32_t siteCounter = 1;
|
||||
const MPSiteType siteType = MPSiteTypeGeneratedLong;
|
||||
const MPSiteVariant siteVariant = MPSiteVariantPassword;
|
||||
const char *siteContext = NULL;
|
||||
struct timeval startTime;
|
||||
if (gettimeofday(&startTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int iterations = 100;
|
||||
// Start MPW
|
||||
unsigned int iterations = 100;
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Calculate the master key salt.
|
||||
char *mpNameSpace = "com.lyndir.masterpassword";
|
||||
const uint32_t n_userNameLength = htonl(strlen(userName));
|
||||
const size_t masterKeySaltLength = strlen(mpNameSpace) + sizeof(n_userNameLength) + strlen(userName);
|
||||
char *masterKeySalt = malloc( masterKeySaltLength );
|
||||
if (!masterKeySalt) {
|
||||
fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
fullName, masterPassword, MPAlgorithmVersionCurrent );
|
||||
if (!masterKey)
|
||||
ftl( "Could not allocate master key: %d\n", errno );
|
||||
free( (void *)mpw_passwordForSite(
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContext, MPAlgorithmVersionCurrent ) );
|
||||
free( (void *)masterKey );
|
||||
|
||||
char *mKS = masterKeySalt;
|
||||
memcpy(mKS, mpNameSpace, strlen(mpNameSpace)); mKS += strlen(mpNameSpace);
|
||||
memcpy(mKS, &n_userNameLength, sizeof(n_userNameLength)); mKS += sizeof(n_userNameLength);
|
||||
memcpy(mKS, userName, strlen(userName)); mKS += strlen(userName);
|
||||
if (mKS - masterKeySalt != masterKeySaltLength)
|
||||
abort();
|
||||
trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
|
||||
|
||||
// Calculate the master key.
|
||||
uint8_t *masterKey = malloc( MP_dkLen );
|
||||
if (!masterKey) {
|
||||
fprintf(stderr, "Could not allocate master key: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) {
|
||||
fprintf(stderr, "Could not generate master key: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
memset(masterKeySalt, 0, masterKeySaltLength);
|
||||
free(masterKeySalt);
|
||||
|
||||
// Calculate the site seed.
|
||||
const uint32_t n_siteNameLength = htonl(strlen(siteName));
|
||||
const uint32_t n_siteCounter = htonl(siteCounter);
|
||||
const size_t sitePasswordInfoLength = strlen(mpNameSpace) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
|
||||
char *sitePasswordInfo = malloc( sitePasswordInfoLength );
|
||||
if (!sitePasswordInfo) {
|
||||
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *sPI = sitePasswordInfo;
|
||||
memcpy(sPI, mpNameSpace, strlen(mpNameSpace)); sPI += strlen(mpNameSpace);
|
||||
memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
|
||||
memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
|
||||
memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
|
||||
if (sPI - sitePasswordInfo != sitePasswordInfoLength)
|
||||
abort();
|
||||
|
||||
uint8_t sitePasswordSeed[32];
|
||||
HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed);
|
||||
memset(masterKey, 0, MP_dkLen);
|
||||
memset(sitePasswordInfo, 0, sitePasswordInfoLength);
|
||||
free(masterKey);
|
||||
free(sitePasswordInfo);
|
||||
|
||||
// Determine the cipher.
|
||||
const char *cipher = CipherForType(siteType, sitePasswordSeed[0]);
|
||||
trc("type %d, cipher: %s\n", siteType, cipher);
|
||||
if (strlen(cipher) > 32)
|
||||
abort();
|
||||
|
||||
// Encode the password from the seed using the cipher.
|
||||
char *sitePassword = calloc(strlen(cipher) + 1, sizeof(char));
|
||||
for (int c = 0; c < strlen(cipher); ++c) {
|
||||
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
|
||||
trc("class %c, character: %c\n", cipher[c], sitePassword[c]);
|
||||
}
|
||||
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
|
||||
|
||||
if (i % 1 == 0)
|
||||
fprintf( stderr, "\rmpw: iteration %d / %d..", i, iterations );
|
||||
if (i % ( iterations / 100 ) == 0)
|
||||
fprintf( stderr, "\rmpw: iteration %d / %d (%d%%)..", i, iterations, i * 100 / iterations );
|
||||
}
|
||||
|
||||
// Output timing results.
|
||||
struct timeval endTime;
|
||||
if (gettimeofday(&endTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
long long secs = (endTime.tv_sec - startTime.tv_sec);
|
||||
long long usecs = (endTime.tv_usec - startTime.tv_usec);
|
||||
double elapsed = secs + usecs / 1000000.0;
|
||||
double mpwSpeed = iterations / elapsed;
|
||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, mpwSpeed );
|
||||
const double mpwSpeed = mpw_showSpeed( startTime, iterations, "mpw" );
|
||||
|
||||
// Start SHA-256
|
||||
if (gettimeofday(&startTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
iterations = 50000000;
|
||||
iterations = 45000000;
|
||||
uint8_t hash[32];
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
SHA256_Buf(masterPassword, strlen(masterPassword), hash);
|
||||
SHA256_Buf( masterPassword, strlen( masterPassword ), hash );
|
||||
|
||||
if (i % 1000 == 0)
|
||||
fprintf( stderr, "\rsha256: iteration %d / %d..", i, iterations );
|
||||
if (i % ( iterations / 100 ) == 0)
|
||||
fprintf( stderr, "\rsha256: iteration %d / %d (%d%%)..", i, iterations, i * 100 / iterations );
|
||||
}
|
||||
|
||||
// Output timing results.
|
||||
if (gettimeofday(&endTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
secs = (endTime.tv_sec - startTime.tv_sec);
|
||||
usecs = (endTime.tv_usec - startTime.tv_usec);
|
||||
elapsed = secs + usecs / 1000000.0;
|
||||
double sha256Speed = iterations / elapsed;
|
||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, sha256Speed );
|
||||
const double sha256Speed = mpw_showSpeed( startTime, iterations, "sha256" );
|
||||
|
||||
// Start BCrypt
|
||||
if (gettimeofday(&startTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bcrypt_cost = 9;
|
||||
iterations = 600;
|
||||
iterations = 1000;
|
||||
mpw_getTime( &startTime );
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
crypt(masterPassword, crypt_gensalt("$2b$", bcrypt_cost, userName, strlen(userName)));
|
||||
crypt( masterPassword, crypt_gensalt( "$2b$", bcrypt_cost, fullName, strlen( fullName ) ) );
|
||||
|
||||
if (i % 10 == 0)
|
||||
fprintf( stderr, "\rbcrypt (cost %d): iteration %d / %d..", bcrypt_cost, i, iterations );
|
||||
if (i % ( iterations / 100 ) == 0)
|
||||
fprintf( stderr, "\rbcrypt (cost %d): iteration %d / %d (%d%%)..", bcrypt_cost, i, iterations, i * 100 / iterations );
|
||||
}
|
||||
|
||||
// Output timing results.
|
||||
if (gettimeofday(&endTime, NULL) != 0) {
|
||||
fprintf(stderr, "Could not get time: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
secs = (endTime.tv_sec - startTime.tv_sec);
|
||||
usecs = (endTime.tv_usec - startTime.tv_usec);
|
||||
elapsed = secs + usecs / 1000000.0;
|
||||
double bcrypt9Speed = iterations / elapsed;
|
||||
fprintf( stdout, " done. %d iterations in %llds %lldµs -> %.2f/s\n", iterations, secs, usecs, bcrypt9Speed );
|
||||
const double bcrypt9Speed = mpw_showSpeed( startTime, iterations, "bcrypt9" );
|
||||
|
||||
// Summarize.
|
||||
fprintf( stdout, "\n== SUMMARY ==\nOn this machine,\n" );
|
||||
fprintf( stdout, "mpw is %f times slower than sha256\n", sha256Speed / mpwSpeed );
|
||||
fprintf( stdout, "mpw is %f times slower than bcrypt (cost 9)\n", bcrypt9Speed / mpwSpeed );
|
||||
fprintf( stdout, " - mpw is %f times slower than sha256 (reference: 320000 on an MBP Late 2013).\n", sha256Speed / mpwSpeed );
|
||||
fprintf( stdout, " - mpw is %f times slower than bcrypt (cost 9) (reference: 22 on an MBP Late 2013).\n", bcrypt9Speed / mpwSpeed );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
222
MasterPassword/C/mpw-cli.c
Normal file
222
MasterPassword/C/mpw-cli.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(READLINE)
|
||||
#include <readline/readline.h>
|
||||
#elif defined(EDITLINE)
|
||||
#include <histedit.h>
|
||||
#endif
|
||||
|
||||
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); exit(2); } while (0)
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#define MP_env_fullname "MP_FULLNAME"
|
||||
#define MP_env_sitetype "MP_SITETYPE"
|
||||
#define MP_env_sitecounter "MP_SITECOUNTER"
|
||||
#define MP_env_algorithm "MP_ALGORITHM"
|
||||
|
||||
static void usage() {
|
||||
|
||||
fprintf( stderr, "Usage: mpw [-u name] [-t type] [-c counter] [-V version] [-v variant] [-C context] [-h] site\n\n" );
|
||||
fprintf( stderr, " -u name Specify the full name of the user.\n"
|
||||
" Defaults to %s in env.\n\n", MP_env_fullname );
|
||||
fprintf( stderr, " -t type Specify the password's template.\n"
|
||||
" Defaults to %s in env or 'long' for password, 'name' for login.\n"
|
||||
" x, max, maximum | 20 characters, contains symbols.\n"
|
||||
" l, long | Copy-friendly, 14 characters, contains symbols.\n"
|
||||
" m, med, medium | Copy-friendly, 8 characters, contains symbols.\n"
|
||||
" b, basic | 8 characters, no symbols.\n"
|
||||
" s, short | Copy-friendly, 4 characters, no symbols.\n"
|
||||
" i, pin | 4 numbers.\n"
|
||||
" n, name | 9 letter name.\n"
|
||||
" p, phrase | 20 character sentence.\n\n", MP_env_sitetype );
|
||||
fprintf( stderr, " -c counter The value of the counter.\n"
|
||||
" Defaults to %s in env or 1.\n\n", MP_env_sitecounter );
|
||||
fprintf( stderr, " -V version The algorithm version to use.\n"
|
||||
" Defaults to %s in env or %d.\n\n", MP_env_algorithm, MPAlgorithmVersionCurrent );
|
||||
fprintf( stderr, " -v variant The kind of content to generate.\n"
|
||||
" Defaults to 'password'.\n"
|
||||
" p, password | The password to log in with.\n"
|
||||
" l, login | The username to log in as.\n"
|
||||
" a, answer | The answer to a security question.\n\n" );
|
||||
fprintf( stderr, " -C context A variant-specific context.\n"
|
||||
" Defaults to empty.\n"
|
||||
" -v p, password | Doesn't currently use a context.\n"
|
||||
" -v l, login | Doesn't currently use a context.\n"
|
||||
" -v a, answer | Empty for a universal site answer or\n"
|
||||
" | the most significant word(s) of the question.\n\n" );
|
||||
fprintf( stderr, " ENVIRONMENT\n\n"
|
||||
" MP_FULLNAME | The full name of the user.\n"
|
||||
" MP_SITETYPE | The default password template.\n"
|
||||
" MP_SITECOUNTER | The default counter value.\n\n" );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
static char *homedir(const char *filename) {
|
||||
|
||||
char *homedir = NULL;
|
||||
struct passwd *passwd = getpwuid( getuid() );
|
||||
if (passwd)
|
||||
homedir = passwd->pw_dir;
|
||||
if (!homedir)
|
||||
homedir = getenv( "HOME" );
|
||||
if (!homedir)
|
||||
homedir = getcwd( NULL, 0 );
|
||||
|
||||
char *homefile = NULL;
|
||||
asprintf( &homefile, "%s/%s", homedir, filename );
|
||||
return homefile;
|
||||
}
|
||||
|
||||
static char *getlinep(const char *prompt) {
|
||||
|
||||
char *buf = NULL;
|
||||
size_t bufSize = 0;
|
||||
ssize_t lineSize;
|
||||
fprintf( stderr, "%s", prompt );
|
||||
fprintf( stderr, " " );
|
||||
if ((lineSize = getline( &buf, &bufSize, stdin )) < 0) {
|
||||
free( buf );
|
||||
return NULL;
|
||||
}
|
||||
buf[lineSize - 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int main(int argc, char *const argv[]) {
|
||||
|
||||
// Read the environment.
|
||||
char *fullName = getenv( MP_env_fullname );
|
||||
const char *masterPassword = NULL;
|
||||
const char *siteName = NULL;
|
||||
MPSiteType siteType = MPSiteTypeGeneratedLong;
|
||||
const char *siteTypeString = getenv( MP_env_sitetype );
|
||||
MPSiteVariant siteVariant = MPSiteVariantPassword;
|
||||
const char *siteVariantString = NULL;
|
||||
const char *siteContextString = NULL;
|
||||
uint32_t siteCounter = 1;
|
||||
const char *siteCounterString = getenv( MP_env_sitecounter );
|
||||
MPAlgorithmVersion algorithmVersion = MPAlgorithmVersionCurrent;
|
||||
const char *algorithmVersionString = getenv( MP_env_algorithm );
|
||||
if (algorithmVersionString && strlen( algorithmVersionString ))
|
||||
if (sscanf( algorithmVersionString, "%u", &algorithmVersion ) != 1)
|
||||
ftl( "Invalid %s: %s\n", MP_env_algorithm, algorithmVersionString );
|
||||
|
||||
// Read the options.
|
||||
for (int opt; (opt = getopt( argc, argv, "u:P:t:c:v:V:C:h" )) != -1;)
|
||||
switch (opt) {
|
||||
case 'u':
|
||||
fullName = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
// Do not use this. Passing your master password via the command-line
|
||||
// is insecure. This is here for non-interactive testing purposes only.
|
||||
masterPassword = strcpy( malloc( strlen( optarg ) + 1 ), optarg );
|
||||
break;
|
||||
case 't':
|
||||
siteTypeString = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
siteCounterString = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
siteVariantString = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
if (sscanf( optarg, "%u", &algorithmVersion ) != 1)
|
||||
ftl( "Not a version: %s\n", optarg );
|
||||
break;
|
||||
case 'C':
|
||||
siteContextString = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
case '?':
|
||||
switch (optopt) {
|
||||
case 'u':
|
||||
ftl( "Missing full name to option: -%c\n", optopt );
|
||||
break;
|
||||
case 't':
|
||||
ftl( "Missing type name to option: -%c\n", optopt );
|
||||
break;
|
||||
case 'c':
|
||||
ftl( "Missing counter value to option: -%c\n", optopt );
|
||||
break;
|
||||
default:
|
||||
ftl( "Unknown option: -%c\n", optopt );
|
||||
}
|
||||
default:
|
||||
ftl("Unexpected option: %c", opt);
|
||||
}
|
||||
if (optind < argc)
|
||||
siteName = argv[optind];
|
||||
|
||||
// Convert and validate input.
|
||||
if (!fullName && !(fullName = getlinep( "Your full name:" )))
|
||||
ftl( "Missing full name.\n" );
|
||||
if (!siteName && !(siteName = getlinep( "Site name:" )))
|
||||
ftl( "Missing site name.\n" );
|
||||
if (siteCounterString)
|
||||
siteCounter = (uint32_t)atol( siteCounterString );
|
||||
if (siteCounter < 1)
|
||||
ftl( "Invalid site counter: %d\n", siteCounter );
|
||||
if (siteVariantString)
|
||||
siteVariant = mpw_variantWithName( siteVariantString );
|
||||
if (siteVariant == MPSiteVariantLogin)
|
||||
siteType = MPSiteTypeGeneratedName;
|
||||
if (siteVariant == MPSiteVariantAnswer)
|
||||
siteType = MPSiteTypeGeneratedPhrase;
|
||||
if (siteTypeString)
|
||||
siteType = mpw_typeWithName( siteTypeString );
|
||||
trc( "algorithmVersion: %u\n", algorithmVersion );
|
||||
|
||||
// Read the master password.
|
||||
char *mpwConfigPath = homedir( ".mpw" );
|
||||
if (!mpwConfigPath)
|
||||
ftl( "Couldn't resolve path for configuration file: %d\n", errno );
|
||||
trc( "mpwConfigPath: %s\n", mpwConfigPath );
|
||||
FILE *mpwConfig = fopen( mpwConfigPath, "r" );
|
||||
free( mpwConfigPath );
|
||||
if (mpwConfig) {
|
||||
char *line = NULL;
|
||||
size_t linecap = 0;
|
||||
while (getline( &line, &linecap, mpwConfig ) > 0) {
|
||||
char *lineData = line;
|
||||
if (strcmp( strsep( &lineData, ":" ), fullName ) == 0) {
|
||||
masterPassword = strcpy( malloc( strlen( lineData ) ), strsep( &lineData, "\n" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
mpw_free( line, linecap );
|
||||
}
|
||||
while (!masterPassword || !strlen(masterPassword))
|
||||
masterPassword = getpass( "Your master password: " );
|
||||
|
||||
// Summarize operation.
|
||||
fprintf( stderr, "%s's password for %s:\n[ %s ]: ", fullName, siteName, mpw_identicon( fullName, masterPassword ) );
|
||||
|
||||
// Output the password.
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
fullName, masterPassword, algorithmVersion );
|
||||
mpw_freeString( masterPassword );
|
||||
if (!masterKey)
|
||||
ftl( "Couldn't derive master key." );
|
||||
|
||||
const char *sitePassword = mpw_passwordForSite(
|
||||
masterKey, siteName, siteType, siteCounter, siteVariant, siteContextString, algorithmVersion );
|
||||
mpw_free( masterKey, MP_dkLen );
|
||||
if (!sitePassword)
|
||||
ftl( "Couldn't derive site password." );
|
||||
|
||||
fprintf( stdout, "%s\n", sitePassword );
|
||||
return 0;
|
||||
}
|
||||
76
MasterPassword/C/mpw-tests-util.c
Normal file
76
MasterPassword/C/mpw-tests-util.c
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// mpw-tests-util.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-21.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
#include "mpw-tests-util.h"
|
||||
|
||||
static xmlChar const *mpw_xmlPath(xmlNodePtr context) {
|
||||
|
||||
if (context->parent) {
|
||||
char *string = calloc( 256, 1 );
|
||||
snprintf( string, 256, "%s/%s", mpw_xmlPath( context->parent ), context->name );
|
||||
return BAD_CAST string;
|
||||
}
|
||||
|
||||
return context->name? context->name: (xmlChar const *)"";
|
||||
}
|
||||
|
||||
xmlNodePtr mpw_xmlTestCaseNode(xmlNodePtr testCaseNode, const char *nodeName) {
|
||||
|
||||
// Try to find an attribute node.
|
||||
for (xmlAttrPtr child = testCaseNode->properties; child; child = child->next)
|
||||
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == 0)
|
||||
return (xmlNodePtr)child;
|
||||
|
||||
// Try to find an element node.
|
||||
for (xmlNodePtr child = testCaseNode->children; child; child = child->next)
|
||||
if (xmlStrcmp( child->name, BAD_CAST nodeName ) == 0)
|
||||
return child;
|
||||
|
||||
// Missing content, try to find parent case.
|
||||
if (strcmp(nodeName, "parent") == 0)
|
||||
// Was just searching for testCaseNode's parent, none found.
|
||||
return NULL;
|
||||
xmlChar *parentId = mpw_xmlTestCaseString( testCaseNode, "parent" );
|
||||
if (!parentId)
|
||||
// testCaseNode has no parent, give up.
|
||||
return NULL;
|
||||
|
||||
for (xmlNodePtr otherTestCaseNode = testCaseNode->parent->children; otherTestCaseNode; otherTestCaseNode = otherTestCaseNode->next) {
|
||||
xmlChar *id = mpw_xmlTestCaseString( otherTestCaseNode, "id" );
|
||||
int foundParent = xmlStrcmp( id, parentId ) == 0;
|
||||
xmlFree( id );
|
||||
|
||||
if (foundParent) {
|
||||
xmlFree( parentId );
|
||||
return mpw_xmlTestCaseNode( otherTestCaseNode, nodeName );
|
||||
}
|
||||
}
|
||||
|
||||
ftl( "Missing parent: %s, for case: %s\n", parentId, mpw_xmlTestCaseString( testCaseNode, "id" ) );
|
||||
}
|
||||
|
||||
xmlChar *mpw_xmlTestCaseString(xmlNodePtr context, const char *nodeName) {
|
||||
|
||||
xmlNodePtr child = mpw_xmlTestCaseNode( context, nodeName );
|
||||
return xmlNodeGetContent( child );
|
||||
}
|
||||
|
||||
uint32_t mpw_xmlTestCaseInteger(xmlNodePtr context, const char *nodeName) {
|
||||
|
||||
xmlChar *string = mpw_xmlTestCaseString( context, nodeName );
|
||||
uint32_t integer = (uint32_t)atol( (char *)string );
|
||||
xmlFree( string );
|
||||
|
||||
return integer;
|
||||
}
|
||||
16
MasterPassword/C/mpw-tests-util.h
Normal file
16
MasterPassword/C/mpw-tests-util.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// mpw-tests-util.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-21.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <libxml/parser.h>
|
||||
|
||||
xmlNodePtr mpw_xmlTestCaseNode(
|
||||
xmlNodePtr testCaseNode, const char *nodeName);
|
||||
xmlChar *mpw_xmlTestCaseString(
|
||||
xmlNodePtr context, const char *nodeName);
|
||||
uint32_t mpw_xmlTestCaseInteger(
|
||||
xmlNodePtr context, const char *nodeName);
|
||||
81
MasterPassword/C/mpw-tests.c
Normal file
81
MasterPassword/C/mpw-tests.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); exit(2); } while (0)
|
||||
|
||||
#include "mpw-algorithm.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
#include "mpw-tests-util.h"
|
||||
|
||||
int main(int argc, char *const argv[]) {
|
||||
|
||||
int failedTests = 0;
|
||||
|
||||
xmlNodePtr tests = xmlDocGetRootElement( xmlParseFile( "mpw_tests.xml" ) );
|
||||
for (xmlNodePtr testCase = tests->children; testCase; testCase = testCase->next) {
|
||||
if (testCase->type != XML_ELEMENT_NODE || xmlStrcmp( testCase->name, BAD_CAST "case" ) != 0)
|
||||
continue;
|
||||
|
||||
// Read in the test case.
|
||||
xmlChar *id = mpw_xmlTestCaseString( testCase, "id" );
|
||||
uint32_t algorithm = mpw_xmlTestCaseInteger( testCase, "algorithm" );
|
||||
xmlChar *fullName = mpw_xmlTestCaseString( testCase, "fullName" );
|
||||
xmlChar *masterPassword = mpw_xmlTestCaseString( testCase, "masterPassword" );
|
||||
xmlChar *keyID = mpw_xmlTestCaseString( testCase, "keyID" );
|
||||
xmlChar *siteName = mpw_xmlTestCaseString( testCase, "siteName" );
|
||||
uint32_t siteCounter = mpw_xmlTestCaseInteger( testCase, "siteCounter" );
|
||||
xmlChar *siteTypeString = mpw_xmlTestCaseString( testCase, "siteType" );
|
||||
xmlChar *siteVariantString = mpw_xmlTestCaseString( testCase, "siteVariant" );
|
||||
xmlChar *siteContext = mpw_xmlTestCaseString( testCase, "siteContext" );
|
||||
xmlChar *result = mpw_xmlTestCaseString( testCase, "result" );
|
||||
|
||||
MPSiteType siteType = mpw_typeWithName( (char *)siteTypeString );
|
||||
MPSiteVariant siteVariant = mpw_variantWithName( (char *)siteVariantString );
|
||||
|
||||
// Run the test case.
|
||||
fprintf( stdout, "test case %s... ", id );
|
||||
if (!xmlStrlen( result )) {
|
||||
fprintf( stdout, "abstract.\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. calculate the master key.
|
||||
const uint8_t *masterKey = mpw_masterKeyForUser(
|
||||
(char *)fullName, (char *)masterPassword, algorithm );
|
||||
if (!masterKey)
|
||||
ftl( "Couldn't derive master key." );
|
||||
|
||||
// 2. calculate the site password.
|
||||
const char *sitePassword = mpw_passwordForSite(
|
||||
masterKey, (char *)siteName, siteType, siteCounter, siteVariant, (char *)siteContext, algorithm );
|
||||
mpw_free( masterKey, MP_dkLen );
|
||||
if (!sitePassword)
|
||||
ftl( "Couldn't derive site password." );
|
||||
|
||||
// Check the result.
|
||||
if (xmlStrcmp( result, BAD_CAST sitePassword ) == 0)
|
||||
fprintf( stdout, "pass.\n" );
|
||||
|
||||
else {
|
||||
++failedTests;
|
||||
fprintf( stdout, "FAILED! (got %s != expected %s)\n", sitePassword, result );
|
||||
}
|
||||
|
||||
// Free test case.
|
||||
mpw_freeString( sitePassword );
|
||||
xmlFree( id );
|
||||
xmlFree( fullName );
|
||||
xmlFree( masterPassword );
|
||||
xmlFree( keyID );
|
||||
xmlFree( siteName );
|
||||
xmlFree( siteTypeString );
|
||||
xmlFree( siteVariantString );
|
||||
xmlFree( siteContext );
|
||||
xmlFree( result );
|
||||
}
|
||||
|
||||
return failedTests;
|
||||
}
|
||||
195
MasterPassword/C/mpw-types.c
Normal file
195
MasterPassword/C/mpw-types.c
Normal file
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// mpw-types.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2012-02-01.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef COLOR
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
#endif
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
|
||||
const MPSiteType mpw_typeWithName(const char *typeName) {
|
||||
|
||||
// Lower-case and trim optionally leading "Generated" string from typeName to standardize it.
|
||||
size_t stdTypeNameOffset = 0;
|
||||
size_t stdTypeNameSize = strlen( typeName );
|
||||
if (strstr(typeName, "Generated" ) == typeName)
|
||||
stdTypeNameSize -= (stdTypeNameOffset = strlen( "Generated" ));
|
||||
char stdTypeName[stdTypeNameSize + 1];
|
||||
for (size_t c = 0; c < stdTypeNameSize; ++c)
|
||||
stdTypeName[c] = (char)tolower( typeName[c + stdTypeNameOffset] );
|
||||
stdTypeName[stdTypeNameSize] = '\0';
|
||||
|
||||
// Find what site type is represented by the type name.
|
||||
if (0 == strcmp( stdTypeName, "x" ) || 0 == strcmp( stdTypeName, "max" ) || 0 == strcmp( stdTypeName, "maximum" ))
|
||||
return MPSiteTypeGeneratedMaximum;
|
||||
if (0 == strcmp( stdTypeName, "l" ) || 0 == strcmp( stdTypeName, "long" ))
|
||||
return MPSiteTypeGeneratedLong;
|
||||
if (0 == strcmp( stdTypeName, "m" ) || 0 == strcmp( stdTypeName, "med" ) || 0 == strcmp( stdTypeName, "medium" ))
|
||||
return MPSiteTypeGeneratedMedium;
|
||||
if (0 == strcmp( stdTypeName, "b" ) || 0 == strcmp( stdTypeName, "basic" ))
|
||||
return MPSiteTypeGeneratedBasic;
|
||||
if (0 == strcmp( stdTypeName, "s" ) || 0 == strcmp( stdTypeName, "short" ))
|
||||
return MPSiteTypeGeneratedShort;
|
||||
if (0 == strcmp( stdTypeName, "i" ) || 0 == strcmp( stdTypeName, "pin" ))
|
||||
return MPSiteTypeGeneratedPIN;
|
||||
if (0 == strcmp( stdTypeName, "n" ) || 0 == strcmp( stdTypeName, "name" ))
|
||||
return MPSiteTypeGeneratedName;
|
||||
if (0 == strcmp( stdTypeName, "p" ) || 0 == strcmp( stdTypeName, "phrase" ))
|
||||
return MPSiteTypeGeneratedPhrase;
|
||||
|
||||
ftl( "Not a generated type name: %s", stdTypeName );
|
||||
}
|
||||
|
||||
const char **mpw_templatesForType(MPSiteType type, size_t *count) {
|
||||
|
||||
if (!(type & MPSiteTypeClassGenerated)) {
|
||||
ftl( "Not a generated type: %d", type );
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MPSiteTypeGeneratedMaximum: {
|
||||
return alloc_array( *count, const char *,
|
||||
"anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" );
|
||||
}
|
||||
case MPSiteTypeGeneratedLong: {
|
||||
return alloc_array( *count, const char *,
|
||||
"CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno",
|
||||
"CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno",
|
||||
"CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno",
|
||||
"CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno",
|
||||
"CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno",
|
||||
"CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno",
|
||||
"CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" );
|
||||
}
|
||||
case MPSiteTypeGeneratedMedium: {
|
||||
return alloc_array( *count, const char *,
|
||||
"CvcnoCvc", "CvcCvcno" );
|
||||
}
|
||||
case MPSiteTypeGeneratedBasic: {
|
||||
return alloc_array( *count, const char *,
|
||||
"aaanaaan", "aannaaan", "aaannaaa" );
|
||||
}
|
||||
case MPSiteTypeGeneratedShort: {
|
||||
return alloc_array( *count, const char *,
|
||||
"Cvcn" );
|
||||
}
|
||||
case MPSiteTypeGeneratedPIN: {
|
||||
return alloc_array( *count, const char *,
|
||||
"nnnn" );
|
||||
}
|
||||
case MPSiteTypeGeneratedName: {
|
||||
return alloc_array( *count, const char *,
|
||||
"cvccvcvcv" );
|
||||
}
|
||||
case MPSiteTypeGeneratedPhrase: {
|
||||
return alloc_array( *count, const char *,
|
||||
"cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" );
|
||||
}
|
||||
default: {
|
||||
ftl( "Unknown generated type: %d", type );
|
||||
*count = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte) {
|
||||
|
||||
size_t count = 0;
|
||||
const char **templates = mpw_templatesForType( type, &count );
|
||||
if (!count)
|
||||
return NULL;
|
||||
|
||||
char const *template = templates[seedByte % count];
|
||||
free( templates );
|
||||
return template;
|
||||
}
|
||||
|
||||
const MPSiteVariant mpw_variantWithName(const char *variantName) {
|
||||
|
||||
// Lower-case and trim optionally leading "generated" string from typeName to standardize it.
|
||||
size_t stdVariantNameSize = strlen( variantName );
|
||||
char stdVariantName[stdVariantNameSize + 1];
|
||||
for (size_t c = 0; c < stdVariantNameSize; ++c)
|
||||
stdVariantName[c] = (char)tolower( variantName[c] );
|
||||
stdVariantName[stdVariantNameSize] = '\0';
|
||||
|
||||
if (0 == strcmp( stdVariantName, "p" ) || 0 == strcmp( stdVariantName, "password" ))
|
||||
return MPSiteVariantPassword;
|
||||
if (0 == strcmp( stdVariantName, "l" ) || 0 == strcmp( stdVariantName, "login" ))
|
||||
return MPSiteVariantLogin;
|
||||
if (0 == strcmp( stdVariantName, "a" ) || 0 == strcmp( stdVariantName, "answer" ))
|
||||
return MPSiteVariantAnswer;
|
||||
|
||||
fprintf( stderr, "Not a variant name: %s", stdVariantName );
|
||||
abort();
|
||||
}
|
||||
|
||||
const char *mpw_scopeForVariant(MPSiteVariant variant) {
|
||||
|
||||
switch (variant) {
|
||||
case MPSiteVariantPassword: {
|
||||
return "com.lyndir.masterpassword";
|
||||
}
|
||||
case MPSiteVariantLogin: {
|
||||
return "com.lyndir.masterpassword.login";
|
||||
}
|
||||
case MPSiteVariantAnswer: {
|
||||
return "com.lyndir.masterpassword.answer";
|
||||
}
|
||||
default: {
|
||||
fprintf( stderr, "Unknown variant: %d", variant );
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *mpw_charactersInClass(char characterClass) {
|
||||
|
||||
switch (characterClass) {
|
||||
case 'V':
|
||||
return "AEIOU";
|
||||
case 'C':
|
||||
return "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
case 'v':
|
||||
return "aeiou";
|
||||
case 'c':
|
||||
return "bcdfghjklmnpqrstvwxyz";
|
||||
case 'A':
|
||||
return "AEIOUBCDFGHJKLMNPQRSTVWXYZ";
|
||||
case 'a':
|
||||
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
|
||||
case 'n':
|
||||
return "0123456789";
|
||||
case 'o':
|
||||
return "@&%?,=[]_:-+*$#!'^~;()/.";
|
||||
case 'x':
|
||||
return "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()";
|
||||
case ' ':
|
||||
return " ";
|
||||
default: {
|
||||
fprintf( stderr, "Unknown character class: %c", characterClass );
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char mpw_characterFromClass(char characterClass, uint8_t seedByte) {
|
||||
|
||||
const char *classCharacters = mpw_charactersInClass( characterClass );
|
||||
return classCharacters[seedByte % strlen( classCharacters )];
|
||||
}
|
||||
99
MasterPassword/C/mpw-types.h
Normal file
99
MasterPassword/C/mpw-types.h
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// mpw-types.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2012-02-01.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef _MPW_TYPES_H
|
||||
#define _MPW_TYPES_H
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef NS_ENUM
|
||||
#define enum(_type, _name) NS_ENUM(_type, _name)
|
||||
#else
|
||||
#define enum(_type, _name) _type _name; enum
|
||||
#endif
|
||||
|
||||
#define MP_dkLen 64
|
||||
|
||||
//// Types.
|
||||
|
||||
typedef enum( unsigned int, MPSiteVariant ) {
|
||||
/** Generate the password to log in with. */
|
||||
MPSiteVariantPassword,
|
||||
/** Generate the login name to log in as. */
|
||||
MPSiteVariantLogin,
|
||||
/** Generate the answer to a security question. */
|
||||
MPSiteVariantAnswer,
|
||||
};
|
||||
|
||||
typedef enum( unsigned int, MPSiteTypeClass ) {
|
||||
/** Generate the password. */
|
||||
MPSiteTypeClassGenerated = 1 << 4,
|
||||
/** Store the password. */
|
||||
MPSiteTypeClassStored = 1 << 5,
|
||||
};
|
||||
|
||||
typedef enum( unsigned int, MPSiteFeature ) {
|
||||
/** Export the key-protected content data. */
|
||||
MPSiteFeatureExportContent = 1 << 10,
|
||||
/** Never export content. */
|
||||
MPSiteFeatureDevicePrivate = 1 << 11,
|
||||
};
|
||||
|
||||
typedef enum( unsigned int, MPSiteType) {
|
||||
MPSiteTypeGeneratedMaximum = 0x0 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedLong = 0x1 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedMedium = 0x2 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedBasic = 0x4 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedShort = 0x3 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedPIN = 0x5 | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedName = 0xE | MPSiteTypeClassGenerated | 0x0,
|
||||
MPSiteTypeGeneratedPhrase = 0xF | MPSiteTypeClassGenerated | 0x0,
|
||||
|
||||
MPSiteTypeStoredPersonal = 0x0 | MPSiteTypeClassStored | MPSiteFeatureExportContent,
|
||||
MPSiteTypeStoredDevicePrivate = 0x1 | MPSiteTypeClassStored | MPSiteFeatureDevicePrivate,
|
||||
};
|
||||
|
||||
//// Type utilities.
|
||||
|
||||
/**
|
||||
* @return The variant represented by the given name.
|
||||
*/
|
||||
const MPSiteVariant mpw_variantWithName(const char *variantName);
|
||||
/**
|
||||
* @return An internal string containing the scope identifier to apply when encoding for the given variant.
|
||||
*/
|
||||
const char *mpw_scopeForVariant(MPSiteVariant variant);
|
||||
|
||||
/**
|
||||
* @return The type represented by the given name.
|
||||
*/
|
||||
const MPSiteType mpw_typeWithName(const char *typeName);
|
||||
|
||||
/**
|
||||
* @return A newly allocated array of internal strings that express the templates to use for the given type.
|
||||
* The amount of elements in the array is stored in count.
|
||||
* If an unsupported type is given, count will be 0 and will return NULL.
|
||||
* The array needs to be free'ed, the strings themselves must not be free'ed or modified.
|
||||
*/
|
||||
const char **mpw_templatesForType(MPSiteType type, size_t *count);
|
||||
/**
|
||||
* @return An internal string that contains the password encoding template of the given type
|
||||
* for a seed that starts with the given byte.
|
||||
*/
|
||||
const char *mpw_templateForType(MPSiteType type, uint8_t seedByte);
|
||||
|
||||
/**
|
||||
* @return An internal string that contains all the characters that occur in the given character class.
|
||||
*/
|
||||
const char *mpw_charactersInClass(char characterClass);
|
||||
/**
|
||||
* @return A character from given character class that encodes the given byte.
|
||||
*/
|
||||
const char mpw_characterFromClass(char characterClass, uint8_t seedByte);
|
||||
|
||||
#endif // _MPW_TYPES_H
|
||||
218
MasterPassword/C/mpw-util.c
Normal file
218
MasterPassword/C/mpw-util.c
Normal file
@@ -0,0 +1,218 @@
|
||||
//
|
||||
// mpw-util.c
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef COLOR
|
||||
#include <unistd.h>
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
#endif
|
||||
|
||||
#include <scrypt/sha256.h>
|
||||
#include <scrypt/crypto_scrypt.h>
|
||||
|
||||
#include "mpw-util.h"
|
||||
|
||||
void mpw_pushBuf(uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize) {
|
||||
|
||||
if (*bufferSize == (size_t)-1)
|
||||
// The buffer was marked as broken, it is missing a previous push. Abort to avoid corrupt content.
|
||||
return;
|
||||
|
||||
*bufferSize += pushSize;
|
||||
uint8_t *resizedBuffer = realloc( *buffer, *bufferSize );
|
||||
if (!resizedBuffer) {
|
||||
// realloc failed, we can't push. Mark the buffer as broken.
|
||||
mpw_free( *buffer, *bufferSize - pushSize );
|
||||
*bufferSize = (size_t)-1;
|
||||
*buffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*buffer = resizedBuffer;
|
||||
uint8_t *pushDst = *buffer + *bufferSize - pushSize;
|
||||
memcpy( pushDst, pushBuffer, pushSize );
|
||||
}
|
||||
|
||||
void mpw_pushString(uint8_t **buffer, size_t *const bufferSize, const char *pushString) {
|
||||
|
||||
mpw_pushBuf( buffer, bufferSize, pushString, strlen( pushString ) );
|
||||
}
|
||||
|
||||
void mpw_pushInt(uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt) {
|
||||
|
||||
mpw_pushBuf( buffer, bufferSize, &pushInt, sizeof( pushInt ) );
|
||||
}
|
||||
|
||||
void mpw_free(const void *buffer, const size_t bufferSize) {
|
||||
|
||||
memset( (void *)buffer, 0, bufferSize );
|
||||
free( (void *)buffer );
|
||||
}
|
||||
|
||||
void mpw_freeString(const char *string) {
|
||||
|
||||
mpw_free( string, strlen( string ) );
|
||||
}
|
||||
|
||||
uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||
uint64_t N, uint32_t r, uint32_t p) {
|
||||
|
||||
uint8_t *key = malloc( keySize );
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
if (crypto_scrypt( (const uint8_t *)secret, strlen( secret ), salt, saltSize, N, r, p, key, keySize ) < 0) {
|
||||
mpw_free( key, keySize );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
|
||||
|
||||
uint8_t *const buffer = malloc( 32 );
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
HMAC_SHA256_Buf( key, keySize, salt, saltSize, buffer );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *mpw_idForBuf(const void *buf, size_t length) {
|
||||
|
||||
uint8_t hash[32];
|
||||
SHA256_Buf( buf, length, hash );
|
||||
|
||||
return mpw_hex( hash, 32 );
|
||||
}
|
||||
|
||||
static char **mpw_hex_buf = NULL;
|
||||
static unsigned int mpw_hex_buf_i = 0;
|
||||
|
||||
const char *mpw_hex(const void *buf, size_t length) {
|
||||
|
||||
// FIXME
|
||||
if (!mpw_hex_buf) {
|
||||
mpw_hex_buf = malloc( 10 * sizeof( char * ) );
|
||||
for (uint8_t i = 0; i < 10; ++i)
|
||||
mpw_hex_buf[i] = NULL;
|
||||
}
|
||||
mpw_hex_buf_i = (mpw_hex_buf_i + 1) % 10;
|
||||
|
||||
mpw_hex_buf[mpw_hex_buf_i] = realloc( mpw_hex_buf[mpw_hex_buf_i], length * 2 + 1 );
|
||||
for (size_t kH = 0; kH < length; kH++)
|
||||
sprintf( &(mpw_hex_buf[mpw_hex_buf_i][kH * 2]), "%02X", ((const uint8_t *)buf)[kH] );
|
||||
|
||||
return mpw_hex_buf[mpw_hex_buf_i];
|
||||
}
|
||||
|
||||
const char *mpw_hex_l(uint32_t number) {
|
||||
|
||||
return mpw_hex( &number, sizeof( number ) );
|
||||
}
|
||||
|
||||
#ifdef COLOR
|
||||
static int putvari;
|
||||
static char *putvarc = NULL;
|
||||
static int istermsetup = 0;
|
||||
static void initputvar() {
|
||||
if (putvarc)
|
||||
free(putvarc);
|
||||
putvarc=(char *)calloc(256, sizeof(char));
|
||||
putvari=0;
|
||||
|
||||
if (!istermsetup)
|
||||
istermsetup = (OK == setupterm(NULL, STDERR_FILENO, NULL));
|
||||
}
|
||||
static int putvar(int c) {
|
||||
putvarc[putvari++]=c;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *mpw_identicon(const char *fullName, const char *masterPassword) {
|
||||
|
||||
const char *leftArm[] = { "╔", "╚", "╰", "═" };
|
||||
const char *rightArm[] = { "╗", "╝", "╯", "═" };
|
||||
const char *body[] = { "█", "░", "▒", "▓", "☺", "☻" };
|
||||
const char *accessory[] = {
|
||||
"◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣",
|
||||
"☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟",
|
||||
"♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌"
|
||||
};
|
||||
|
||||
uint8_t identiconSeed[32];
|
||||
HMAC_SHA256_Buf( masterPassword, strlen( masterPassword ), fullName, strlen( fullName ), identiconSeed );
|
||||
|
||||
char *colorString, *resetString;
|
||||
#ifdef COLOR
|
||||
if (isatty( STDERR_FILENO )) {
|
||||
uint8_t colorIdentifier = (uint8_t)(identiconSeed[4] % 7 + 1);
|
||||
initputvar();
|
||||
tputs(tparm(tgetstr("AF", NULL), colorIdentifier), 1, putvar);
|
||||
colorString = calloc(strlen(putvarc) + 1, sizeof(char));
|
||||
strcpy(colorString, putvarc);
|
||||
tputs(tgetstr("me", NULL), 1, putvar);
|
||||
resetString = calloc(strlen(putvarc) + 1, sizeof(char));
|
||||
strcpy(resetString, putvarc);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
colorString = calloc( 1, sizeof( char ) );
|
||||
resetString = calloc( 1, sizeof( char ) );
|
||||
}
|
||||
|
||||
char *identicon = (char *)calloc( 256, sizeof( char ) );
|
||||
snprintf( identicon, 256, "%s%s%s%s%s%s",
|
||||
colorString,
|
||||
leftArm[identiconSeed[0] % (sizeof( leftArm ) / sizeof( leftArm[0] ))],
|
||||
body[identiconSeed[1] % (sizeof( body ) / sizeof( body[0] ))],
|
||||
rightArm[identiconSeed[2] % (sizeof( rightArm ) / sizeof( rightArm[0] ))],
|
||||
accessory[identiconSeed[3] % (sizeof( accessory ) / sizeof( accessory[0] ))],
|
||||
resetString );
|
||||
|
||||
free( colorString );
|
||||
free( resetString );
|
||||
return identicon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of bytes used by UTF-8 to encode a single character that starts with the given byte.
|
||||
*/
|
||||
static int mpw_charByteSize(unsigned char utf8Byte) {
|
||||
|
||||
if (!utf8Byte)
|
||||
return 0;
|
||||
if ((utf8Byte & 0x80) == 0)
|
||||
return 1;
|
||||
if ((utf8Byte & 0xC0) != 0xC0)
|
||||
return 0;
|
||||
if ((utf8Byte & 0xE0) == 0xC0)
|
||||
return 2;
|
||||
if ((utf8Byte & 0xF0) == 0xE0)
|
||||
return 3;
|
||||
if ((utf8Byte & 0xF8) == 0xF0)
|
||||
return 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t mpw_charlen(const char *utf8String) {
|
||||
|
||||
size_t charlen = 0;
|
||||
char *remainingString = (char *)utf8String;
|
||||
for (int charByteSize; (charByteSize = mpw_charByteSize( (unsigned char)*remainingString )); remainingString += charByteSize)
|
||||
++charlen;
|
||||
|
||||
return charlen;
|
||||
}
|
||||
80
MasterPassword/C/mpw-util.h
Normal file
80
MasterPassword/C/mpw-util.h
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// mpw-util.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 2014-12-20.
|
||||
// Copyright (c) 2014 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//// Logging.
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef trc
|
||||
#define trc(...) fprintf( stderr, __VA_ARGS__ )
|
||||
#endif
|
||||
#else
|
||||
#ifndef trc
|
||||
#define trc(...) do {} while (0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef ftl
|
||||
#define ftl(...) do { fprintf( stderr, __VA_ARGS__ ); abort(); } while (0)
|
||||
#endif
|
||||
|
||||
//// Buffers and memory.
|
||||
|
||||
#define alloc_array(_count, _type, ...) ({ \
|
||||
_type stackElements[] = { __VA_ARGS__ }; \
|
||||
_count = sizeof( stackElements ) / sizeof( _type ); \
|
||||
_type *allocElements = malloc( sizeof( stackElements ) ); \
|
||||
memcpy( allocElements, stackElements, sizeof( stackElements ) ); \
|
||||
allocElements; \
|
||||
})
|
||||
|
||||
/** Push a buffer onto a buffer. reallocs the given buffer and appends the given buffer. */
|
||||
void mpw_pushBuf(
|
||||
uint8_t **const buffer, size_t *const bufferSize, const void *pushBuffer, const size_t pushSize);
|
||||
/** Push a string onto a buffer. reallocs the given buffer and appends the given string. */
|
||||
void mpw_pushString(
|
||||
uint8_t **buffer, size_t *const bufferSize, const char *pushString);
|
||||
/** Push an integer onto a buffer. reallocs the given buffer and appends the given integer. */
|
||||
void mpw_pushInt(
|
||||
uint8_t **const buffer, size_t *const bufferSize, const uint32_t pushInt);
|
||||
/** Free a buffer after zero'ing its contents. */
|
||||
void mpw_free(
|
||||
const void *buffer, const size_t bufferSize);
|
||||
/** Free a string after zero'ing its contents. */
|
||||
void mpw_freeString(
|
||||
const char *string);
|
||||
|
||||
//// Cryptographic functions.
|
||||
|
||||
/** Perform a scrypt-based key derivation on the given key using the given salt and scrypt parameters.
|
||||
* @return A new keySize-size allocated buffer. */
|
||||
uint8_t const *mpw_scrypt(
|
||||
const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||
uint64_t N, uint32_t r, uint32_t p);
|
||||
/** Calculate a SHA256-based HMAC by encrypting the given salt with the given key.
|
||||
* @return A new 32-byte allocated buffer. */
|
||||
uint8_t const *mpw_hmac_sha256(
|
||||
const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize);
|
||||
|
||||
//// Visualizers.
|
||||
|
||||
/** Encode a buffer as a string of hexadecimal characters.
|
||||
* @return A C-string in a reused buffer, do not free or store it. */
|
||||
const char *mpw_hex(const void *buf, size_t length);
|
||||
const char *mpw_hex_l(uint32_t number);
|
||||
/** Encode a fingerprint for a buffer.
|
||||
* @return A C-string in a reused buffer, do not free or store it. */
|
||||
const char *mpw_idForBuf(const void *buf, size_t length);
|
||||
/** Encode a visual fingerprint for a user.
|
||||
* @return A newly allocated string. */
|
||||
const char *mpw_identicon(const char *fullName, const char *masterPassword);
|
||||
|
||||
//// String utilities.
|
||||
|
||||
/** @return The amount of display characters in the given UTF-8 string. */
|
||||
const size_t mpw_charlen(const char *utf8String);
|
||||
@@ -17,8 +17,8 @@ mpw() {
|
||||
:| _copy 2>/dev/null
|
||||
|
||||
# Ask for the user's name and password if not yet known.
|
||||
MP_USERNAME=${MP_USERNAME:-$(ask 'Your Full Name:')}
|
||||
MP_FULLNAME=${MP_FULLNAME:-$(ask 'Your Full Name:')}
|
||||
|
||||
# Start Master Password and copy the output.
|
||||
printf %s "$(MP_USERNAME=$MP_USERNAME command mpw "$@")" | _copy
|
||||
printf %s "$(MP_FULLNAME=$MP_FULLNAME command mpw "$@")" | _copy
|
||||
}
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/fs.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
#include <cygwin/fs.h>
|
||||
#else
|
||||
#include <sys/disk.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <pwd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <alg/sha256.h>
|
||||
#include <crypto/crypto_scrypt.h>
|
||||
#include "types.h"
|
||||
|
||||
#if defined(READLINE)
|
||||
#include <readline/readline.h>
|
||||
#elif defined(EDITLINE)
|
||||
#include <histedit.h>
|
||||
#endif
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
#define MP_p 2
|
||||
#define MP_dkLen 64
|
||||
#define MP_hash PearlHashSHA256
|
||||
|
||||
#define MP_env_username "MP_USERNAME"
|
||||
#define MP_env_sitetype "MP_SITETYPE"
|
||||
#define MP_env_sitecounter "MP_SITECOUNTER"
|
||||
|
||||
void usage() {
|
||||
fprintf(stderr, "Usage: mpw [-u name] [-t type] [-c counter] site\n\n");
|
||||
fprintf(stderr, " -u name Specify the full name of the user.\n"
|
||||
" Defaults to %s in env.\n\n", MP_env_username);
|
||||
fprintf(stderr, " -t type Specify the password's template.\n"
|
||||
" Defaults to %s in env or 'long' for password, 'name' for login.\n"
|
||||
" x, max, maximum | 20 characters, contains symbols.\n"
|
||||
" l, long | Copy-friendly, 14 characters, contains symbols.\n"
|
||||
" m, med, medium | Copy-friendly, 8 characters, contains symbols.\n"
|
||||
" b, basic | 8 characters, no symbols.\n"
|
||||
" s, short | Copy-friendly, 4 characters, no symbols.\n"
|
||||
" i, pin | 4 numbers.\n"
|
||||
" n, name | 9 letter name.\n"
|
||||
" p, phrase | 20 character sentence.\n\n", MP_env_sitetype);
|
||||
fprintf(stderr, " -c counter The value of the counter.\n"
|
||||
" Defaults to %s in env or '1'.\n\n", MP_env_sitecounter);
|
||||
fprintf(stderr, " -v variant The kind of content to generate.\n"
|
||||
" Defaults to 'password'.\n"
|
||||
" p, password | The password to log in with.\n"
|
||||
" l, login | The username to log in as.\n"
|
||||
" a, answer | The answer to a security question.\n\n");
|
||||
fprintf(stderr, " -C context A variant-specific context.\n"
|
||||
" Defaults to empty.\n"
|
||||
" -v p, password | Doesn't currently use a context.\n"
|
||||
" -v l, login | Doesn't currently use a context.\n"
|
||||
" -v a, answer | Empty for a universal site answer or\n"
|
||||
" | the most significant word(s) of the question.\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char *homedir(const char *filename) {
|
||||
char *homedir = NULL;
|
||||
#if defined(__CYGWIN__)
|
||||
homedir = getenv("USERPROFILE");
|
||||
if (!homedir) {
|
||||
const char *homeDrive = getenv("HOMEDRIVE");
|
||||
const char *homePath = getenv("HOMEPATH");
|
||||
homedir = char[strlen(homeDrive) + strlen(homePath) + 1];
|
||||
sprintf(homedir, "%s/%s", homeDrive, homePath);
|
||||
}
|
||||
#else
|
||||
struct passwd* passwd = getpwuid(getuid());
|
||||
if (passwd)
|
||||
homedir = passwd->pw_dir;
|
||||
if (!homedir)
|
||||
homedir = getenv("HOME");
|
||||
#endif
|
||||
if (!homedir)
|
||||
homedir = getcwd(NULL, 0);
|
||||
|
||||
char *homefile = NULL;
|
||||
asprintf(&homefile, "%s/%s", homedir, filename);
|
||||
return homefile;
|
||||
}
|
||||
|
||||
char *getlinep(const char *prompt) {
|
||||
char *buf = NULL;
|
||||
size_t bufSize = 0;
|
||||
ssize_t lineSize;
|
||||
fprintf(stderr, "%s", prompt);
|
||||
fprintf(stderr, " ");
|
||||
if ((lineSize = getline(&buf, &bufSize, stdin)) < 0) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
buf[lineSize - 1]=0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int main(int argc, char *const argv[]) {
|
||||
|
||||
// Read the environment.
|
||||
char *userName = getenv( MP_env_username );
|
||||
const char *masterPassword = NULL;
|
||||
const char *siteName = NULL;
|
||||
MPElementType siteType = MPElementTypeGeneratedLong;
|
||||
const char *siteTypeString = getenv( MP_env_sitetype );
|
||||
MPElementVariant siteVariant = MPElementVariantPassword;
|
||||
const char *siteVariantString = NULL;
|
||||
const char *siteContextString = NULL;
|
||||
uint32_t siteCounter = 1;
|
||||
const char *siteCounterString = getenv( MP_env_sitecounter );
|
||||
|
||||
// Read the options.
|
||||
for (int opt; (opt = getopt(argc, argv, "u:t:c:v:C:h")) != -1;)
|
||||
switch (opt) {
|
||||
case 'u':
|
||||
userName = optarg;
|
||||
break;
|
||||
case 't':
|
||||
siteTypeString = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
siteCounterString = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
siteVariantString = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
siteContextString = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
case '?':
|
||||
switch (optopt) {
|
||||
case 'u':
|
||||
fprintf(stderr, "Missing user name to option: -%c\n", optopt);
|
||||
break;
|
||||
case 't':
|
||||
fprintf(stderr, "Missing type name to option: -%c\n", optopt);
|
||||
break;
|
||||
case 'c':
|
||||
fprintf(stderr, "Missing counter value to option: -%c\n", optopt);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option: -%c\n", optopt);
|
||||
}
|
||||
return 1;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (optind < argc)
|
||||
siteName = argv[optind];
|
||||
|
||||
// Convert and validate input.
|
||||
if (!userName) {
|
||||
if (!(userName = getlinep("Your user name:"))) {
|
||||
fprintf(stderr, "Missing user name.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
trc("userName: %s\n", userName);
|
||||
if (!siteName) {
|
||||
if (!(siteName = getlinep("Site name:"))) {
|
||||
fprintf(stderr, "Missing site name.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
trc("siteName: %s\n", siteName);
|
||||
if (siteCounterString)
|
||||
siteCounter = atoi( siteCounterString );
|
||||
if (siteCounter < 1) {
|
||||
fprintf(stderr, "Invalid site counter: %d\n", siteCounter);
|
||||
return 1;
|
||||
}
|
||||
trc("siteCounter: %d\n", siteCounter);
|
||||
if (siteVariantString)
|
||||
siteVariant = VariantWithName( siteVariantString );
|
||||
trc("siteVariant: %d (%s)\n", siteVariant, siteVariantString);
|
||||
if (siteVariant == MPElementVariantLogin)
|
||||
siteType = MPElementTypeGeneratedName;
|
||||
if (siteVariant == MPElementVariantAnswer)
|
||||
siteType = MPElementTypeGeneratedPhrase;
|
||||
if (siteTypeString)
|
||||
siteType = TypeWithName( siteTypeString );
|
||||
trc("siteType: %d (%s)\n", siteType, siteTypeString);
|
||||
|
||||
// Read the master password.
|
||||
char *mpwConfigPath = homedir(".mpw");
|
||||
if (!mpwConfigPath) {
|
||||
fprintf(stderr, "Couldn't resolve path for configuration file: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
trc("mpwConfigPath: %s\n", mpwConfigPath);
|
||||
FILE *mpwConfig = fopen(mpwConfigPath, "r");
|
||||
free(mpwConfigPath);
|
||||
if (mpwConfig) {
|
||||
char *line = NULL;
|
||||
size_t linecap = 0;
|
||||
ssize_t linelen;
|
||||
while ((linelen = getline(&line, &linecap, mpwConfig)) > 0)
|
||||
if (strcmp(strsep(&line, ":"), userName) == 0) {
|
||||
masterPassword = strsep(&line, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!masterPassword)
|
||||
masterPassword = getpass( "Your master password: " );
|
||||
trc("masterPassword: %s\n", masterPassword);
|
||||
|
||||
// Summarize operation.
|
||||
fprintf(stderr, "%s's password for %s:\n[ %s ]: ", userName, siteName, Identicon( userName, masterPassword ));
|
||||
|
||||
// Calculate the master key salt.
|
||||
const char *mpKeyScope = ScopeForVariant(MPElementVariantPassword);
|
||||
trc("key scope: %s\n", mpKeyScope);
|
||||
const uint32_t n_userNameLength = htonl(strlen(userName));
|
||||
const size_t masterKeySaltLength = strlen(mpKeyScope) + sizeof(n_userNameLength) + strlen(userName);
|
||||
char *masterKeySalt = (char *)malloc( masterKeySaltLength );
|
||||
if (!masterKeySalt) {
|
||||
fprintf(stderr, "Could not allocate master key salt: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *mKS = masterKeySalt;
|
||||
memcpy(mKS, mpKeyScope, strlen(mpKeyScope)); mKS += strlen(mpKeyScope);
|
||||
memcpy(mKS, &n_userNameLength, sizeof(n_userNameLength)); mKS += sizeof(n_userNameLength);
|
||||
memcpy(mKS, userName, strlen(userName)); mKS += strlen(userName);
|
||||
if (mKS - masterKeySalt != masterKeySaltLength)
|
||||
abort();
|
||||
trc("masterKeySalt ID: %s\n", IDForBuf(masterKeySalt, masterKeySaltLength));
|
||||
|
||||
// Calculate the master key.
|
||||
uint8_t *masterKey = (uint8_t *)malloc( MP_dkLen );
|
||||
if (!masterKey) {
|
||||
fprintf(stderr, "Could not allocate master key: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
if (crypto_scrypt( (const uint8_t *)masterPassword, strlen(masterPassword), (const uint8_t *)masterKeySalt, masterKeySaltLength, MP_N, MP_r, MP_p, masterKey, MP_dkLen ) < 0) {
|
||||
fprintf(stderr, "Could not generate master key: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
memset(masterKeySalt, 0, masterKeySaltLength);
|
||||
free(masterKeySalt);
|
||||
trc("masterPassword Hex: %s\n", Hex(masterPassword, strlen(masterPassword)));
|
||||
trc("masterPassword ID: %s\n", IDForBuf(masterPassword, strlen(masterPassword)));
|
||||
trc("masterKey ID: %s\n", IDForBuf(masterKey, MP_dkLen));
|
||||
|
||||
// Calculate the site seed.
|
||||
const char *mpSiteScope = ScopeForVariant(siteVariant);
|
||||
trc("site scope: %s, context: %s\n", mpSiteScope, siteContextString == NULL? "<empty>": siteContextString);
|
||||
const uint32_t n_siteNameLength = htonl(strlen(siteName));
|
||||
const uint32_t n_siteCounter = htonl(siteCounter);
|
||||
const uint32_t n_siteContextLength = siteContextString == NULL? 0: htonl(strlen(siteContextString));
|
||||
size_t sitePasswordInfoLength = strlen(mpSiteScope) + sizeof(n_siteNameLength) + strlen(siteName) + sizeof(n_siteCounter);
|
||||
if (siteContextString)
|
||||
sitePasswordInfoLength += sizeof(n_siteContextLength) + strlen(siteContextString);
|
||||
char *sitePasswordInfo = (char *)malloc( sitePasswordInfoLength );
|
||||
if (!sitePasswordInfo) {
|
||||
fprintf(stderr, "Could not allocate site seed: %d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *sPI = sitePasswordInfo;
|
||||
memcpy(sPI, mpSiteScope, strlen(mpSiteScope)); sPI += strlen(mpSiteScope);
|
||||
memcpy(sPI, &n_siteNameLength, sizeof(n_siteNameLength)); sPI += sizeof(n_siteNameLength);
|
||||
memcpy(sPI, siteName, strlen(siteName)); sPI += strlen(siteName);
|
||||
memcpy(sPI, &n_siteCounter, sizeof(n_siteCounter)); sPI += sizeof(n_siteCounter);
|
||||
if (siteContextString) {
|
||||
memcpy(sPI, &n_siteContextLength, sizeof(n_siteContextLength)); sPI += sizeof(n_siteContextLength);
|
||||
memcpy(sPI, siteContextString, strlen(siteContextString)); sPI += strlen(siteContextString);
|
||||
}
|
||||
if (sPI - sitePasswordInfo != sitePasswordInfoLength)
|
||||
abort();
|
||||
trc("seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)\n", mpSiteScope, Hex(&n_siteNameLength, sizeof(n_siteNameLength)), siteName, Hex(&n_siteCounter, sizeof(n_siteCounter)), Hex(&n_siteContextLength, sizeof(n_siteContextLength)), siteContextString);
|
||||
trc("sitePasswordInfo ID: %s\n", IDForBuf(sitePasswordInfo, sitePasswordInfoLength));
|
||||
|
||||
uint8_t sitePasswordSeed[32];
|
||||
HMAC_SHA256_Buf(masterKey, MP_dkLen, sitePasswordInfo, sitePasswordInfoLength, sitePasswordSeed);
|
||||
memset(masterKey, 0, MP_dkLen);
|
||||
memset(sitePasswordInfo, 0, sitePasswordInfoLength);
|
||||
free(masterKey);
|
||||
free(sitePasswordInfo);
|
||||
trc("sitePasswordSeed ID: %s\n", IDForBuf(sitePasswordSeed, 32));
|
||||
|
||||
// Determine the cipher.
|
||||
const char *cipher = CipherForType(siteType, sitePasswordSeed[0]);
|
||||
trc("type %s, cipher: %s\n", siteTypeString, cipher);
|
||||
if (strlen(cipher) > 32)
|
||||
abort();
|
||||
|
||||
// Encode the password from the seed using the cipher.
|
||||
char *sitePassword = (char *)calloc(strlen(cipher) + 1, sizeof(char));
|
||||
for (int c = 0; c < strlen(cipher); ++c) {
|
||||
sitePassword[c] = CharacterFromClass(cipher[c], sitePasswordSeed[c + 1]);
|
||||
trc("class %c, character: %c\n", cipher[c], sitePassword[c]);
|
||||
}
|
||||
memset(sitePasswordSeed, 0, sizeof(sitePasswordSeed));
|
||||
|
||||
// Output the password.
|
||||
fprintf( stdout, "%s\n", sitePassword );
|
||||
return 0;
|
||||
}
|
||||
69
MasterPassword/C/mpw.completion.bash
Normal file
69
MasterPassword/C/mpw.completion.bash
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
source bashcomplib
|
||||
|
||||
# completing the 'mpw' command.
|
||||
_comp_mpw() {
|
||||
local optarg= cword=${COMP_WORDS[COMP_CWORD]} pcword=
|
||||
(( COMP_CWORD )) && pcword=${COMP_WORDS[COMP_CWORD - 1]}
|
||||
|
||||
case $pcword in
|
||||
-u) # complete full names.
|
||||
COMPREPLY=( ~/.mpw.d/*.mpsites )
|
||||
[[ -e $COMPREPLY ]] || COMPREPLY=()
|
||||
COMPREPLY=( "${COMPREPLY[@]##*/}" ) COMPREPLY=( "${COMPREPLY[@]%.mpsites}" )
|
||||
;;
|
||||
-t) # complete types.
|
||||
COMPREPLY=( maximum long medium basic short pin name phrase )
|
||||
;;
|
||||
-c) # complete counter.
|
||||
COMPREPLY=( 1 )
|
||||
;;
|
||||
-V) # complete versions.
|
||||
COMPREPLY=( 0 1 2 3 )
|
||||
;;
|
||||
-v) # complete variants.
|
||||
COMPREPLY=( password login answer )
|
||||
;;
|
||||
-C) # complete context.
|
||||
;;
|
||||
*)
|
||||
# previous word is not an option we can complete, complete site name (or option if leading -)
|
||||
if [[ $cword = -* ]]; then
|
||||
COMPREPLY=( -u -t -c -V -v -C )
|
||||
else
|
||||
local w fullName=$MP_FULLNAME
|
||||
for (( w = 0; w < ${#COMP_WORDS[@]}; ++w )); do
|
||||
[[ ${COMP_WORDS[w]} = -u ]] && fullName=$(xargs <<< "${COMP_WORDS[w + 1]}") && break
|
||||
done
|
||||
if [[ -e ~/.mpw.d/"$fullName.mpsites" ]]; then
|
||||
IFS=$'\n' read -d '' -ra COMPREPLY < <(awk -F$'\t' '!/^ *#/{sub(/^ */, "", $2); print $2}' ~/.mpw.d/"$fullName.mpsites")
|
||||
printf -v _comp_title 'Sites for %s' "$fullName"
|
||||
else
|
||||
# Default list from the Alexa Top 500
|
||||
COMPREPLY=(
|
||||
163.com 360.cn 9gag.com adobe.com alibaba.com aliexpress.com amazon.com
|
||||
apple.com archive.org ask.com baidu.com battle.net booking.com buzzfeed.com
|
||||
chase.com cnn.com comcast.net craigslist.org dailymotion.com dell.com
|
||||
deviantart.com diply.com disqus.com dropbox.com ebay.com engadget.com
|
||||
espn.go.com evernote.com facebook.com fedex.com feedly.com flickr.com
|
||||
flipkart.com github.com gizmodo.com go.com goodreads.com google.com
|
||||
huffingtonpost.com hulu.com ign.com ikea.com imdb.com imgur.com
|
||||
indiatimes.com instagram.com jd.com kickass.to kickstarter.com linkedin.com
|
||||
live.com livedoor.com mail.ru mozilla.org naver.com netflix.com newegg.com
|
||||
nicovideo.jp nytimes.com pandora.com paypal.com pinterest.com pornhub.com
|
||||
qq.com rakuten.co.jp reddit.com redtube.com shutterstock.com skype.com
|
||||
soso.com spiegel.de spotify.com stackexchange.com steampowered.com
|
||||
stumbleupon.com taobao.com target.com thepiratebay.se tmall.com
|
||||
torrentz.eu tripadvisor.com tube8.com tubecup.com tudou.com tumblr.com
|
||||
twitter.com uol.com.br vimeo.com vk.com walmart.com weibo.com whatsapp.com
|
||||
wikia.com wikipedia.org wired.com wordpress.com xhamster.com xinhuanet.com
|
||||
xvideos.com yahoo.com yandex.ru yelp.com youku.com youporn.com ziddu.com
|
||||
)
|
||||
fi
|
||||
fi ;;
|
||||
esac
|
||||
_comp_finish_completions
|
||||
}
|
||||
|
||||
#complete -F _show_args mpw
|
||||
complete -o nospace -F _comp_mpw mpw
|
||||
1
MasterPassword/C/mpw_tests.xml
Symbolic link
1
MasterPassword/C/mpw_tests.xml
Symbolic link
@@ -0,0 +1 @@
|
||||
../Java/masterpassword-algorithm/src/test/resources/mpw_tests.xml
|
||||
@@ -1,238 +0,0 @@
|
||||
//
|
||||
// MPTypes.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 02/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <alg/sha256.h>
|
||||
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
const MPElementType TypeWithName(const char *typeName) {
|
||||
char lowerTypeName[strlen(typeName)];
|
||||
strcpy(lowerTypeName, typeName);
|
||||
for (char *tN = lowerTypeName; *tN; ++tN)
|
||||
*tN = tolower(*tN);
|
||||
|
||||
if (0 == strcmp(lowerTypeName, "x") || 0 == strcmp(lowerTypeName, "max") || 0 == strcmp(lowerTypeName, "maximum"))
|
||||
return MPElementTypeGeneratedMaximum;
|
||||
if (0 == strcmp(lowerTypeName, "l") || 0 == strcmp(lowerTypeName, "long"))
|
||||
return MPElementTypeGeneratedLong;
|
||||
if (0 == strcmp(lowerTypeName, "m") || 0 == strcmp(lowerTypeName, "med") || 0 == strcmp(lowerTypeName, "medium"))
|
||||
return MPElementTypeGeneratedMedium;
|
||||
if (0 == strcmp(lowerTypeName, "b") || 0 == strcmp(lowerTypeName, "basic"))
|
||||
return MPElementTypeGeneratedBasic;
|
||||
if (0 == strcmp(lowerTypeName, "s") || 0 == strcmp(lowerTypeName, "short"))
|
||||
return MPElementTypeGeneratedShort;
|
||||
if (0 == strcmp(lowerTypeName, "i") || 0 == strcmp(lowerTypeName, "pin"))
|
||||
return MPElementTypeGeneratedPIN;
|
||||
if (0 == strcmp(lowerTypeName, "n") || 0 == strcmp(lowerTypeName, "name"))
|
||||
return MPElementTypeGeneratedName;
|
||||
if (0 == strcmp(lowerTypeName, "p") || 0 == strcmp(lowerTypeName, "phrase"))
|
||||
return MPElementTypeGeneratedPhrase;
|
||||
|
||||
fprintf(stderr, "Not a generated type name: %s", lowerTypeName);
|
||||
abort();
|
||||
}
|
||||
|
||||
const char *CipherForType(MPElementType type, uint8_t seedByte) {
|
||||
if (!(type & MPElementTypeClassGenerated)) {
|
||||
fprintf(stderr, "Not a generated type: %d", type);
|
||||
abort();
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MPElementTypeGeneratedMaximum: {
|
||||
const char *ciphers[] = { "anoxxxxxxxxxxxxxxxxx", "axxxxxxxxxxxxxxxxxno" };
|
||||
return ciphers[seedByte % 2];
|
||||
}
|
||||
case MPElementTypeGeneratedLong: {
|
||||
const char *ciphers[] = { "CvcvnoCvcvCvcv", "CvcvCvcvnoCvcv", "CvcvCvcvCvcvno", "CvccnoCvcvCvcv", "CvccCvcvnoCvcv", "CvccCvcvCvcvno", "CvcvnoCvccCvcv", "CvcvCvccnoCvcv", "CvcvCvccCvcvno", "CvcvnoCvcvCvcc", "CvcvCvcvnoCvcc", "CvcvCvcvCvccno", "CvccnoCvccCvcv", "CvccCvccnoCvcv", "CvccCvccCvcvno", "CvcvnoCvccCvcc", "CvcvCvccnoCvcc", "CvcvCvccCvccno", "CvccnoCvcvCvcc", "CvccCvcvnoCvcc", "CvccCvcvCvccno" };
|
||||
return ciphers[seedByte % 21];
|
||||
}
|
||||
case MPElementTypeGeneratedMedium: {
|
||||
const char *ciphers[] = { "CvcnoCvc", "CvcCvcno" };
|
||||
return ciphers[seedByte % 2];
|
||||
}
|
||||
case MPElementTypeGeneratedBasic: {
|
||||
const char *ciphers[] = { "aaanaaan", "aannaaan", "aaannaaa" };
|
||||
return ciphers[seedByte % 3];
|
||||
}
|
||||
case MPElementTypeGeneratedShort: {
|
||||
return "Cvcn";
|
||||
}
|
||||
case MPElementTypeGeneratedPIN: {
|
||||
return "nnnn";
|
||||
}
|
||||
case MPElementTypeGeneratedName: {
|
||||
return "cvccvcvcv";
|
||||
}
|
||||
case MPElementTypeGeneratedPhrase: {
|
||||
const char *ciphers[] = { "cvcc cvc cvccvcv cvc", "cvc cvccvcvcv cvcv", "cv cvccv cvc cvcvccv" };
|
||||
return ciphers[seedByte % 3];
|
||||
}
|
||||
default: {
|
||||
fprintf(stderr, "Unknown generated type: %d", type);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const MPElementVariant VariantWithName(const char *variantName) {
|
||||
char lowerVariantName[strlen(variantName)];
|
||||
strcpy(lowerVariantName, variantName);
|
||||
for (char *vN = lowerVariantName; *vN; ++vN)
|
||||
*vN = tolower(*vN);
|
||||
|
||||
if (0 == strcmp(lowerVariantName, "p") || 0 == strcmp(lowerVariantName, "password"))
|
||||
return MPElementVariantPassword;
|
||||
if (0 == strcmp(lowerVariantName, "l") || 0 == strcmp(lowerVariantName, "login"))
|
||||
return MPElementVariantLogin;
|
||||
if (0 == strcmp(lowerVariantName, "a") || 0 == strcmp(lowerVariantName, "answer"))
|
||||
return MPElementVariantAnswer;
|
||||
|
||||
fprintf(stderr, "Not a variant name: %s", lowerVariantName);
|
||||
abort();
|
||||
}
|
||||
|
||||
const char *ScopeForVariant(MPElementVariant variant) {
|
||||
switch (variant) {
|
||||
case MPElementVariantPassword: {
|
||||
return "com.lyndir.masterpassword";
|
||||
}
|
||||
case MPElementVariantLogin: {
|
||||
return "com.lyndir.masterpassword.login";
|
||||
}
|
||||
case MPElementVariantAnswer: {
|
||||
return "com.lyndir.masterpassword.answer";
|
||||
}
|
||||
default: {
|
||||
fprintf(stderr, "Unknown variant: %d", variant);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char CharacterFromClass(char characterClass, uint8_t seedByte) {
|
||||
const char *classCharacters;
|
||||
switch (characterClass) {
|
||||
case 'V': {
|
||||
classCharacters = "AEIOU";
|
||||
break;
|
||||
}
|
||||
case 'C': {
|
||||
classCharacters = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
break;
|
||||
}
|
||||
case 'v': {
|
||||
classCharacters = "aeiou";
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
classCharacters = "bcdfghjklmnpqrstvwxyz";
|
||||
break;
|
||||
}
|
||||
case 'A': {
|
||||
classCharacters = "AEIOUBCDFGHJKLMNPQRSTVWXYZ";
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
classCharacters = "0123456789";
|
||||
break;
|
||||
}
|
||||
case 'o': {
|
||||
classCharacters = "@&%?,=[]_:-+*$#!'^~;()/.";
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
classCharacters = "AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()";
|
||||
break;
|
||||
}
|
||||
case ' ': {
|
||||
classCharacters = " ";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
fprintf(stderr, "Unknown character class: %c", characterClass);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
return classCharacters[seedByte % strlen(classCharacters)];
|
||||
}
|
||||
|
||||
const char *IDForBuf(const void *buf, size_t length) {
|
||||
uint8_t hash[32];
|
||||
SHA256_Buf(buf, length, hash);
|
||||
|
||||
char *id = (char *)calloc(65, sizeof(char));
|
||||
for (int kH = 0; kH < 32; kH++)
|
||||
sprintf(&(id[kH * 2]), "%02X", hash[kH]);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
const char *Hex(const void *buf, size_t length) {
|
||||
char *id = (char *)calloc(length*2+1, sizeof(char));
|
||||
for (int kH = 0; kH < length; kH++)
|
||||
sprintf(&(id[kH * 2]), "%02X", ((const uint8_t*)buf)[kH]);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
int putvari;
|
||||
char *putvarc = NULL;
|
||||
static void initputvar() {
|
||||
if (putvarc)
|
||||
free(putvarc);
|
||||
putvari=0;
|
||||
putvarc=(char *)calloc(256, sizeof(char));
|
||||
}
|
||||
static int putvar(int c) {
|
||||
putvarc[putvari++]=c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *Identicon(const char *userName, const char *masterPassword) {
|
||||
const char *left[] = { "╔", "╚", "╰", "═" };
|
||||
const char *right[] = { "╗", "╝", "╯", "═" };
|
||||
const char *body[] = { "█", "░", "▒", "▓", "☺", "☻" };
|
||||
const char *accessory[] = { "◈", "◎", "◐", "◑", "◒", "◓", "☀", "☁", "☂", "☃", "☄", "★", "☆", "☎", "☏", "⎈", "⌂", "☘", "☢", "☣", "☕", "⌚", "⌛", "⏰", "⚡", "⛄", "⛅", "☔", "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟", "♨", "♩", "♪", "♫", "⚐", "⚑", "⚔", "⚖", "⚙", "⚠", "⌘", "⏎", "✄", "✆", "✈", "✉", "✌" };
|
||||
|
||||
uint8_t identiconSeed[32];
|
||||
HMAC_SHA256_Buf(masterPassword, strlen(masterPassword), userName, strlen(userName), identiconSeed);
|
||||
|
||||
char *identicon = (char *)calloc(20, sizeof(char));
|
||||
setupterm(NULL, 2, NULL);
|
||||
initputvar();
|
||||
tputs(tparm(tgetstr("AF", NULL), identiconSeed[4] % 7 + 1), 1, putvar);
|
||||
char red[strlen(putvarc)];
|
||||
strcpy(red, putvarc);
|
||||
tputs(tgetstr("me", NULL), 1, putvar);
|
||||
char reset[strlen(putvarc)];
|
||||
strcpy(reset, putvarc);
|
||||
sprintf(identicon, "%s%s%s%s%s%s",
|
||||
red,
|
||||
left[identiconSeed[0] % (sizeof(left) / sizeof(left[0]))],
|
||||
body[identiconSeed[1] % (sizeof(body) / sizeof(body[0]))],
|
||||
right[identiconSeed[2] % (sizeof(right) / sizeof(right[0]))],
|
||||
accessory[identiconSeed[3] % (sizeof(accessory) / sizeof(accessory[0]))],
|
||||
reset);
|
||||
|
||||
return identicon;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
//
|
||||
// MPTypes.h
|
||||
// MasterPassword
|
||||
//
|
||||
// Created by Maarten Billemont on 02/01/12.
|
||||
// Copyright (c) 2012 Lyndir. All rights reserved.
|
||||
//
|
||||
|
||||
typedef enum {
|
||||
/** Generate the password to log in with. */
|
||||
MPElementVariantPassword,
|
||||
/** Generate the login name to log in as. */
|
||||
MPElementVariantLogin,
|
||||
/** Generate the answer to a security question. */
|
||||
MPElementVariantAnswer,
|
||||
} MPElementVariant;
|
||||
|
||||
typedef enum {
|
||||
/** Generate the password. */
|
||||
MPElementTypeClassGenerated = 1 << 4,
|
||||
/** Store the password. */
|
||||
MPElementTypeClassStored = 1 << 5,
|
||||
} MPElementTypeClass;
|
||||
|
||||
typedef enum {
|
||||
/** Export the key-protected content data. */
|
||||
MPElementFeatureExportContent = 1 << 10,
|
||||
/** Never export content. */
|
||||
MPElementFeatureDevicePrivate = 1 << 11,
|
||||
} MPElementFeature;
|
||||
|
||||
typedef enum {
|
||||
MPElementTypeGeneratedMaximum = 0x0 | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedLong = 0x1 | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedMedium = 0x2 | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedBasic = 0x4 | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedShort = 0x3 | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedPIN = 0x5 | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedName = 0xE | MPElementTypeClassGenerated | 0x0,
|
||||
MPElementTypeGeneratedPhrase = 0xF | MPElementTypeClassGenerated | 0x0,
|
||||
|
||||
MPElementTypeStoredPersonal = 0x0 | MPElementTypeClassStored | MPElementFeatureExportContent,
|
||||
MPElementTypeStoredDevicePrivate = 0x1 | MPElementTypeClassStored | MPElementFeatureDevicePrivate,
|
||||
} MPElementType;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define trc(...) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define trc(...) do {} while (0)
|
||||
#endif
|
||||
|
||||
const MPElementVariant VariantWithName(const char *variantName);
|
||||
const char *ScopeForVariant(MPElementVariant variant);
|
||||
const MPElementType TypeWithName(const char *typeName);
|
||||
const char *CipherForType(MPElementType type, uint8_t seedByte);
|
||||
const char CharacterFromClass(char characterClass, uint8_t seedByte);
|
||||
const char *IDForBuf(const void *buf, size_t length);
|
||||
const char *Hex(const void *buf, size_t length);
|
||||
const char *Identicon(const char *userName, const char *masterPassword);
|
||||
|
||||
2
MasterPassword/Java/.gitignore
vendored
Normal file
2
MasterPassword/Java/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target
|
||||
dependency-reduced-pom.xml
|
||||
@@ -7,13 +7,12 @@
|
||||
<parent>
|
||||
<groupId>com.lyndir.masterpassword</groupId>
|
||||
<artifactId>masterpassword</artifactId>
|
||||
<version>GIT-SNAPSHOT</version>
|
||||
<version>2.3.1</version>
|
||||
</parent>
|
||||
|
||||
<name>Master Password Algorithm Implementation</name>
|
||||
<description>The implementation of the Master Password algorithm</description>
|
||||
|
||||
<groupId>com.lyndir.masterpassword</groupId>
|
||||
<artifactId>masterpassword-algorithm</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -24,20 +23,16 @@
|
||||
<dependency>
|
||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||
<artifactId>opal-system</artifactId>
|
||||
<version>1.6-p6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||
<artifactId>opal-crypto</artifactId>
|
||||
<version>1.6-p6</version>
|
||||
<version>1.6-p9</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- EXTERNAL DEPENDENCIES -->
|
||||
<dependency>
|
||||
<groupId>net.sf.plist</groupId>
|
||||
<artifactId>property-list</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lambdaworks</groupId>
|
||||
<artifactId>scrypt</artifactId>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.lyndir.masterpassword;
|
||||
|
||||
/**
|
||||
* <i>07 04, 2012</i>
|
||||
*
|
||||
* @author lhunath
|
||||
*/
|
||||
public enum MPElementFeature {
|
||||
|
||||
/** Export the key-protected content data. */
|
||||
ExportContent,
|
||||
/** Never export content. */
|
||||
DevicePrivate,
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.lyndir.masterpassword;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* <i>07 04, 2012</i>
|
||||
*
|
||||
* @author lhunath
|
||||
*/
|
||||
public enum MPElementType {
|
||||
|
||||
GeneratedMaximum( "Maximum Security Password", "Maximum", "20 characters, contains symbols.", MPElementTypeClass.Generated ),
|
||||
GeneratedLong( "Long Password", "Long", "Copy-friendly, 14 characters, contains symbols.", MPElementTypeClass.Generated ),
|
||||
GeneratedMedium( "Medium Password", "Medium", "Copy-friendly, 8 characters, contains symbols.", MPElementTypeClass.Generated ),
|
||||
GeneratedBasic( "Basic Password", "Basic", "8 characters, no symbols.", MPElementTypeClass.Generated ),
|
||||
GeneratedShort( "Short Password", "Short", "Copy-friendly, 4 characters, no symbols.", MPElementTypeClass.Generated ),
|
||||
GeneratedPIN( "PIN", "PIN", "4 numbers.", MPElementTypeClass.Generated ),
|
||||
|
||||
StoredPersonal( "Personal Password", "Personal", "AES-encrypted, exportable.", MPElementTypeClass.Stored,
|
||||
MPElementFeature.ExportContent ),
|
||||
StoredDevicePrivate( "Device Private Password", "Private", "AES-encrypted, not exported.", MPElementTypeClass.Stored,
|
||||
MPElementFeature.DevicePrivate );
|
||||
|
||||
static final Logger logger = Logger.get( MPElementType.class );
|
||||
|
||||
private final MPElementTypeClass typeClass;
|
||||
private final Set<MPElementFeature> typeFeatures;
|
||||
private final String name;
|
||||
private final String shortName;
|
||||
private final String description;
|
||||
|
||||
MPElementType(final String name, final String shortName, final String description, final MPElementTypeClass typeClass,
|
||||
final MPElementFeature... typeFeatures) {
|
||||
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
this.typeClass = typeClass;
|
||||
this.description = description;
|
||||
|
||||
ImmutableSet.Builder<MPElementFeature> typeFeaturesBuilder = ImmutableSet.builder();
|
||||
for (final MPElementFeature typeFeature : typeFeatures) {
|
||||
typeFeaturesBuilder.add( typeFeature );
|
||||
}
|
||||
this.typeFeatures = typeFeaturesBuilder.build();
|
||||
}
|
||||
|
||||
public MPElementTypeClass getTypeClass() {
|
||||
|
||||
return typeClass;
|
||||
}
|
||||
|
||||
public Set<MPElementFeature> getTypeFeatures() {
|
||||
|
||||
return typeFeatures;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
|
||||
return shortName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The full or short name of the type we want to look up. It is matched case insensitively.
|
||||
*
|
||||
* @return The type with the given name.
|
||||
*/
|
||||
public static MPElementType forName(final String name) {
|
||||
|
||||
for (final MPElementType type : values())
|
||||
if (type.getName().equalsIgnoreCase( name ) || type.getShortName().equalsIgnoreCase( name ))
|
||||
return type;
|
||||
|
||||
throw logger.bug( "Element type not known: %s", name );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param typeClass The class for which we look up types.
|
||||
*
|
||||
* @return All types that support the given class.
|
||||
*/
|
||||
public static ImmutableList<MPElementType> forClass(final MPElementTypeClass typeClass) {
|
||||
|
||||
ImmutableList.Builder<MPElementType> types = ImmutableList.builder();
|
||||
for (final MPElementType type : values())
|
||||
if (type.getTypeClass() == typeClass)
|
||||
types.add( type );
|
||||
|
||||
return types.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.lyndir.masterpassword;
|
||||
|
||||
import com.lyndir.masterpassword.entity.*;
|
||||
|
||||
|
||||
/**
|
||||
* <i>07 04, 2012</i>
|
||||
*
|
||||
* @author lhunath
|
||||
*/
|
||||
public enum MPElementTypeClass {
|
||||
|
||||
Generated(MPElementGeneratedEntity.class),
|
||||
Stored(MPElementStoredEntity.class);
|
||||
|
||||
private final Class<? extends MPElementEntity> entityClass;
|
||||
|
||||
MPElementTypeClass(final Class<? extends MPElementEntity> entityClass) {
|
||||
|
||||
this.entityClass = entityClass;
|
||||
}
|
||||
|
||||
public Class<? extends MPElementEntity> getEntityClass() {
|
||||
|
||||
return entityClass;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user