1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

Compare commits

...

142 Commits

Author SHA1 Message Date
Kyle Spearrin
2ad55e8a8c New Crowdin translations (#353)
* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (German)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Ukrainian)
2018-08-09 17:34:58 -04:00
Kyle Spearrin
a8a1750d5c version bump 2018-08-09 11:48:10 -04:00
Kyle Spearrin
5407e20150 update libs 2018-08-04 00:55:01 -04:00
Kyle Spearrin
58aa37bf8e catch EnableForegroundDispatch exception. disable
back button on yubikey 2fa.
2018-08-01 15:45:32 -04:00
Kyle Spearrin
7c781b60c5 add protocol if missing 2018-08-01 15:32:12 -04:00
Kyle Spearrin
acdfce7e88 support otpath:// totp secrets 2018-07-31 12:34:10 -04:00
Kyle Spearrin
4e4b56d7fe password updated fixes 2018-07-30 22:42:54 -04:00
Kyle Spearrin
a3174d7015 New Crowdin translations (#349)
* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Thai)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Croatian)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Hindi)

* New translations AppResources.resx (German)

* New translations AppResources.resx (French)
2018-07-30 17:14:39 -04:00
Kyle Spearrin
b595c8aeac contrib updates 2018-07-30 17:07:44 -04:00
Kyle Spearrin
a9a33ad71e save password history changes 2018-07-30 16:15:36 -04:00
Kyle Spearrin
4d08ce90cc Merge branch 'master' of github.com:bitwarden/mobile 2018-07-30 13:16:04 -04:00
Kyle Spearrin
01d9ccc110 add password history and updated dates 2018-07-30 13:15:53 -04:00
Jacob
029f069ad5 fetch image from bitwarden/brand (#345) 2018-07-19 10:51:15 -04:00
Kyle Spearrin
13b9e01604 check lock only if locked on all pages 2018-07-16 23:14:45 -04:00
Kyle Spearrin
19c46a472a fix name bug on section group names 2018-07-16 10:24:53 -04:00
Kyle Spearrin
37edfffb97 move last launch check after _lastQueriedUri 2018-07-16 10:17:05 -04:00
Kyle Spearrin
67fa653d06 prevent multiple main activities from autofill 2018-07-16 10:07:22 -04:00
Kyle Spearrin
366b9ddc4a update libs. update android security provider 2018-07-16 08:55:37 -04:00
Kyle Spearrin
c9354f79b8 add escosia browser autofill 2018-07-16 08:40:38 -04:00
Kyle Spearrin
d5b3bd5905 remove no connection alert on appearing of pages 2018-07-12 13:12:42 -04:00
Kyle Spearrin
45dd240415 include some type info with extension exception 2018-06-30 08:55:54 -04:00
Kyle Spearrin
bf99cea004 possible null pointer fix 2018-06-30 08:19:18 -04:00
Kyle Spearrin
f680b1e856 update libs 2018-06-30 00:06:41 -04:00
Kyle Spearrin
b2f40c7af0 fix track bug 2018-06-29 15:26:46 -04:00
Kyle Spearrin
82b17677b9 default track is alpha 2018-06-29 15:24:19 -04:00
Kyle Spearrin
b7df2d5441 rollout track 2018-06-29 15:05:40 -04:00
Kyle Spearrin
dd511ba365 tracks are now strings 2018-06-29 15:04:34 -04:00
Kyle Spearrin
d705e3c1fb version bump 2018-06-29 14:19:35 -04:00
Kyle Spearrin
4bd1322904 update libs 2018-06-29 14:09:53 -04:00
Kyle Spearrin
ac027ee3a0 add support for kiwi browser 2018-06-29 13:48:47 -04:00
Kyle Spearrin
e5e3ebdbba update to Xamarin forms 3.1 2018-06-29 12:45:10 -04:00
Kyle Spearrin
993fc2e6f4 bump version 2018-06-29 10:42:28 -04:00
Kyle Spearrin
61c480618c try to generate key with and without date 2018-06-29 10:39:29 -04:00
Kyle Spearrin
db7f2622c8 org.chromium.chrome support 2018-06-28 23:33:34 -04:00
kspearrin
a39e78a989 increment ios build num 2018-06-19 20:18:07 -04:00
Kyle Spearrin
5a461d68a7 New Crowdin translations (#330)
* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Ukrainian)
2018-06-19 20:07:48 -04:00
Kyle Spearrin
899816673c change icons server to bitwarden.net 2018-06-19 18:02:49 -04:00
Kyle Spearrin
84a10139c1 designer update 2018-06-19 14:28:31 -04:00
Kyle Spearrin
da3aa56d86 add ko and fa languages 2018-06-18 21:24:29 -04:00
Kyle Spearrin
a6dcd512ea update designer 2018-06-18 15:35:04 -04:00
Kyle Spearrin
572d32c1de New Crowdin translations (#329)
* New translations AppResources.resx (Bulgarian)

* New translations copy.resx (Romanian)

* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Polish)

* New translations copy.resx (Persian)

* New translations copy.resx (Persian)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations copy.resx (Korean)

* New translations copy.resx (Korean)

* New translations copy.resx (Romanian)

* New translations copy.resx (Vietnamese)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Thai)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Czech)

* New translations copy.resx (Dutch)

* New translations copy.resx (Dutch)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Danish)

* New translations copy.resx (Czech)

* New translations copy.resx (Czech)

* New translations AppResources.resx (Croatian)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Hindi)

* New translations AppResources.resx (German)

* New translations AppResources.resx (French)

* New translations copy.resx (Vietnamese)
2018-06-18 15:30:24 -04:00
Kyle Spearrin
e8b67ead1e version bump 2018-06-18 15:23:11 -04:00
Kyle Spearrin
377029226e allow non-nfc keys on android 2018-06-18 14:10:43 -04:00
Kyle Spearrin
72d1421f1d shows both accessibility and autofill from tools 2018-06-18 13:59:56 -04:00
Kyle Spearrin
d359547dab monospace fonts for card code 2018-06-18 09:12:03 -04:00
Neil Burrows
9523c7ab33 Card Security Code masked (bitwarden/desktop issue 78) (#328)
* Card Security Code masked in the same way as Passwords. (bitwarden/desktop issue 78)

By default shows Card Security Code masked in the same way as Passwords. (bitwarden/desktop issue 78)

* Creating property to store value of Masked Card Code Shown
2018-06-18 09:00:45 -04:00
Kyle Spearrin
7cac07c185 add pbkdf2 key stretching 2018-06-13 22:41:18 -04:00
Kyle Spearrin
a607a7f3ef clear cache flag on disk 2018-06-08 09:13:42 -04:00
Kyle Spearrin
b5277e89d5 add bromite autofill support 2018-06-08 08:59:54 -04:00
kspearrin
99713f8ed7 remove password generate event on disappear 2018-06-05 11:13:15 -04:00
Kyle Spearrin
145dac500c appresources for ios yubikey 2018-06-04 21:08:55 -04:00
kspearrin
eefd9bf31c update yubikey options for ios 2018-06-04 21:06:17 -04:00
Kyle Spearrin
3f47ca645b iphone yubikey images 2018-06-04 21:02:20 -04:00
Kyle Spearrin
c906f037b5 checked for locked state on activity resume.
resolves #319
2018-06-04 09:20:38 -04:00
Kyle Spearrin
ffc4e32119 run cloc on install 2018-06-01 14:45:56 -04:00
Kyle Spearrin
51eb46241b Revert "previous 2017"
This reverts commit 541416f64b.
2018-05-29 15:54:57 -04:00
Kyle Spearrin
541416f64b previous 2017 2018-05-29 15:47:39 -04:00
Kyle Spearrin
14d1d132a3 dont set key validity dates 2018-05-29 15:21:43 -04:00
Kyle Spearrin
22a0045796 try again button for ios yubikey 2018-05-24 22:43:59 -04:00
Kyle Spearrin
2e5ba0335d hide yubikey token cell for ios 2018-05-24 22:40:02 -04:00
Kyle Spearrin
3315704c14 cleanup 2018-05-24 22:34:17 -04:00
Kyle Spearrin
f90c407fb6 move nfc delegate to member of appdelegate class 2018-05-24 22:33:29 -04:00
Kyle Spearrin
d3646e10a5 clearup yubikey reading on ios 2018-05-24 15:34:09 -04:00
Kyle Spearrin
d3003efe72 remove nfc from extension 2018-05-24 14:01:00 -04:00
Kyle Spearrin
235ca947be turn on nfc in plist 2018-05-24 13:50:11 -04:00
Kyle Spearrin
e7bc9ed5ba nfc updates 2018-05-24 12:49:22 -04:00
Kyle Spearrin
740a18dbc0 stub out yubico nfc support for ios 2018-05-24 11:41:57 -04:00
Kyle Spearrin
add5189bb1 add via to oreo trusted browsers 2018-05-21 23:26:54 -04:00
Kyle Spearrin
62002b8bb3 disable test nodes 2018-05-21 22:53:32 -04:00
Kyle Spearrin
41b4ee33fe adjust max_aspect ratio for samsung full screen 2018-05-20 10:14:54 -04:00
Kyle Spearrin
85c67ac676 version bump 2018-05-18 21:42:51 -04:00
Kyle Spearrin
4637b7d93f update fingerprint lib 2018-04-28 00:25:58 -04:00
Kyle Spearrin
8b9a178c87 faceid description in info.plist 2018-04-28 00:23:31 -04:00
Kyle Spearrin
c595c381a9 bump android version 2018-04-26 00:06:43 -04:00
Kyle Spearrin
c308d7a610 look for password fields from HtmlInfo attributes 2018-04-26 00:04:07 -04:00
Kyle Spearrin
f7570122c6 ignore "edit" fields on autofill 2018-04-26 00:04:07 -04:00
Kyle Spearrin
1e5f186b58 Search Login URI as well 2018-04-26 00:04:07 -04:00
kspearrin
b732b2ffa7 remove password debug code 2018-04-20 20:14:39 -04:00
Kyle Spearrin
617a7be4f3 version bump 2018-04-17 11:28:23 -04:00
Kyle Spearrin
5c5e368d6b comment out password debug 2018-04-17 11:03:36 -04:00
Kyle Spearrin
ff9f49416a track with node id + hash code 2018-04-16 11:01:32 -04:00
Kyle Spearrin
93cae0e9cc dont check ids 2018-04-16 09:00:51 -04:00
Kyle Spearrin
61e75ce747 remove UWP projects so CI will work 2018-04-16 08:28:17 -04:00
Kyle Spearrin
50affe26c5 update resources 2018-04-16 08:18:54 -04:00
kspearrin
8566362607 no need to update vs anymore 2018-04-15 22:00:21 -04:00
kspearrin
36925770d0 show ut8 password alert 2018-04-15 21:45:05 -04:00
kspearrin
d17ca1686e ignore recipient search fields 2018-04-15 21:02:55 -04:00
kspearrin
2ad709dae4 fix ipad crash on doc picker 2018-04-07 12:15:59 -04:00
kspearrin
5a3d86a12a Only adjust insets on phone devices 2018-04-07 11:32:01 -04:00
Kyle Spearrin
1a4ba36820 add support for via browser 2018-04-03 16:08:11 -04:00
Kyle Spearrin
ddeae3b5ba add support for Duo Organization 2FA 2018-04-03 15:59:58 -04:00
Kyle Spearrin
10df9e7cd5 multibutton alert, autofill and save new uri 2018-04-02 13:37:46 -04:00
Kyle Spearrin
be11933c60 remove persian language until further verification 2018-03-29 11:46:09 -04:00
Kyle Spearrin
d2db68b781 New Crowdin translations (#299)
* New translations AppResources.resx (Bulgarian)

* New translations copy.resx (Persian)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Thai)

* New translations copy.resx (Portuguese, Brazilian)

* New translations copy.resx (Portuguese)

* New translations copy.resx (Polish)

* New translations AppResources.resx (Polish)

* New translations copy.resx (Persian)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Persian)

* New translations copy.resx (Italian)

* New translations copy.resx (German)

* New translations copy.resx (German)

* New translations AppResources.resx (German)

* New translations copy.resx (French)

* New translations copy.resx (Danish)

* New translations copy.resx (Danish)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Croatian)

* New translations copy.resx (Vietnamese)
2018-03-29 11:42:49 -04:00
Kyle Spearrin
da6e271584 refactor ignoresearch and password terms detection 2018-03-28 11:48:49 -04:00
Kyle Spearrin
5103c80e1e set default uri on add cipher 2018-03-26 17:06:58 -04:00
Kyle Spearrin
b5c80ea267 version bump 2018-03-22 12:01:17 -04:00
Kyle Spearrin
b5747fbb44 show/hide loading are async now 2018-03-22 11:07:41 -04:00
Kyle Spearrin
215ded8a77 fixes for match detection selection 2018-03-22 09:08:19 -04:00
Kyle Spearrin
e7ab6da068 fix param names for arg null exceptions 2018-03-21 07:35:27 -04:00
Kyle Spearrin
ee881f67ee version bump 2018-03-20 20:21:11 -04:00
Kyle Spearrin
f33248aa4f crash fixes 2018-03-20 20:19:44 -04:00
Kyle Spearrin
c6a40bac03 null checks on dialogs 2018-03-19 21:07:27 -04:00
Kyle Spearrin
aa38e79d08 resource update 2018-03-19 15:57:19 -04:00
Kyle Spearrin
9cac10e559 version bump 2018-03-19 10:24:54 -04:00
Kyle Spearrin
efbd418f56 New Crowdin translations (#296)
* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Estonian)

* New translations copy.resx (Estonian)

* New translations AppResources.resx (French)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Ukrainian)
2018-03-19 10:15:52 -04:00
Kyle Spearrin
4ff3464abd new ic_launcher for adaptive icons 2018-03-17 17:26:10 -04:00
Kyle Spearrin
907ddbf903 collapse no folder listing if more than 99 items 2018-03-16 10:59:54 -04:00
Kyle Spearrin
7041991d5a android dialog is not cancelable 2018-03-16 10:42:07 -04:00
Kyle Spearrin
b26067e5da domain search term must be at least 3 characters 2018-03-16 10:41:53 -04:00
Kyle Spearrin
e519b13533 extension add login adjustments 2018-03-15 19:57:18 -04:00
Kyle Spearrin
30bc3867bf New Crowdin translations (#295)
* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Romanian)

* New translations copy.resx (Portuguese, Brazilian)

* New translations copy.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations copy.resx (Portuguese)

* New translations copy.resx (Portuguese)

* New translations copy.resx (Polish)

* New translations copy.resx (Russian)

* New translations copy.resx (Polish)

* New translations AppResources.resx (Polish)

* New translations copy.resx (Persian)

* New translations copy.resx (Persian)

* New translations AppResources.resx (Persian)

* New translations copy.resx (Norwegian Bokmal)

* New translations copy.resx (Norwegian Bokmal)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (Russian)

* New translations copy.resx (Russian)

* New translations copy.resx (Japanese)

* New translations AppResources.resx (Vietnamese)

* New translations copy.resx (Ukrainian)

* New translations copy.resx (Ukrainian)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Thai)

* New translations copy.resx (Swedish)

* New translations copy.resx (Swedish)

* New translations AppResources.resx (Swedish)

* New translations copy.resx (Spanish)

* New translations copy.resx (Spanish)

* New translations AppResources.resx (Spanish)

* New translations copy.resx (Japanese)

* New translations AppResources.resx (Japanese)

* New translations copy.resx (Bulgarian)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Danish)

* New translations copy.resx (Croatian)

* New translations copy.resx (Estonian)

* New translations copy.resx (Croatian)

* New translations AppResources.resx (Croatian)

* New translations copy.resx (Chinese Traditional)

* New translations copy.resx (Chinese Traditional)

* New translations AppResources.resx (Chinese Traditional)

* New translations copy.resx (Chinese Simplified)

* New translations copy.resx (Chinese Simplified)

* New translations AppResources.resx (Chinese Simplified)

* New translations copy.resx (Bulgarian)

* New translations AppResources.resx (Estonian)

* New translations copy.resx (Estonian)

* New translations AppResources.resx (Italian)

* New translations copy.resx (Indonesian)

* New translations copy.resx (Indonesian)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Hindi)

* New translations copy.resx (German)

* New translations copy.resx (German)

* New translations AppResources.resx (German)

* New translations copy.resx (French)

* New translations copy.resx (French)

* New translations AppResources.resx (French)

* New translations copy.resx (Finnish)

* New translations copy.resx (Finnish)
2018-03-15 12:41:09 -04:00
Kyle Spearrin
5326c3aecc Match detection string 2018-03-15 10:37:08 -04:00
Kyle Spearrin
c95251c903 switch cell for fields, btn widths on ios too 2018-03-14 22:59:31 -04:00
Kyle Spearrin
e08a0a0938 cog alt buttons 2018-03-14 18:26:07 -04:00
Kyle Spearrin
fcb072c37d fix null ref when no uri 2018-03-14 17:41:18 -04:00
Kyle Spearrin
262c19b194 Change context options to action sheet w/ button 2018-03-13 17:33:45 -04:00
Kyle Spearrin
1031ddcd83 proper class on ExtendedViewCell 2018-03-12 22:46:46 -04:00
Kyle Spearrin
aaee0212f0 ios fixes 2018-03-12 15:42:53 -04:00
Kyle Spearrin
8fc95759ba support login uris from app extension 2018-03-12 13:29:12 -04:00
Kyle Spearrin
b6a3a0a54f noop on ios 2018-03-12 13:18:35 -04:00
Kyle Spearrin
e3091be314 Update ISSUE_TEMPLATE.md 2018-03-10 16:36:40 -05:00
Kyle Spearrin
045d0678b3 Create ISSUE_TEMPLATE.md 2018-03-10 09:47:52 -05:00
Kyle Spearrin
e3eeaddb3e normalize passwords 2018-03-09 22:29:59 -05:00
Kyle Spearrin
f2b202c714 only ignore vault.bitwarden.com 2018-03-08 10:34:07 -05:00
Kyle Spearrin
e6f3ad60ef move fields above attachments on view 2018-03-06 13:32:58 -05:00
Kyle Spearrin
fb6e0c9eb8 moved password generation link to button 2018-03-06 12:40:42 -05:00
Kyle Spearrin
fb6e488339 select URI match option from action sheet 2018-03-06 11:58:02 -05:00
Kyle Spearrin
0bccc8f0d5 loginUri no longer used 2018-03-06 08:51:05 -05:00
Kyle Spearrin
560d831e92 masked password string constant 2018-03-06 07:41:40 -05:00
Mark Cohen
7c8f6a1cc7 Don't leak password length through mask (#293) 2018-03-06 07:37:46 -05:00
Kyle Spearrin
deb1ead4ea trim Uri proper from stored json on save 2018-03-05 23:49:48 -05:00
Kyle Spearrin
005b2a4fb6 add support for uri match rules detection 2018-03-05 23:37:02 -05:00
Kyle Spearrin
4c8204f29a view/add/edit login uris 2018-03-05 22:39:56 -05:00
Kyle Spearrin
83fd19784a refactor for cipher model changes and multi-uris 2018-03-05 17:18:18 -05:00
Kyle Spearrin
1f21a2ecc7 add/edit/delete custom fields. remove field page. 2018-03-05 15:15:20 -05:00
Kyle Spearrin
c3f4d56d1e New Crowdin translations (#288)
* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations copy.resx (Russian)

* New translations AppResources.resx (Russian)

* New translations copy.resx (Romanian)

* New translations AppResources.resx (Romanian)

* New translations copy.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Slovak)

* New translations copy.resx (Portuguese)

* New translations AppResources.resx (Portuguese)

* New translations copy.resx (Polish)

* New translations AppResources.resx (Polish)

* New translations copy.resx (Norwegian Bokmal)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations copy.resx (Russian)

* New translations copy.resx (Slovak)

* New translations copy.resx (Japanese)

* New translations AppResources.resx (Turkish)

* New translations copy.resx (Vietnamese)

* New translations AppResources.resx (Vietnamese)

* New translations copy.resx (Ukrainian)

* New translations AppResources.resx (Ukrainian)

* New translations copy.resx (Turkish)

* New translations copy.resx (Thai)

* New translations copy.resx (Thai)

* New translations AppResources.resx (Thai)

* New translations copy.resx (Swedish)

* New translations AppResources.resx (Swedish)

* New translations copy.resx (Spanish)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Japanese)

* New translations copy.resx (Chinese Simplified)

* New translations AppResources.resx (Estonian)

* New translations copy.resx (Dutch)

* New translations AppResources.resx (Dutch)

* New translations copy.resx (Danish)

* New translations AppResources.resx (Danish)

* New translations copy.resx (Czech)

* New translations copy.resx (Estonian)

* New translations AppResources.resx (Czech)

* New translations copy.resx (Croatian)

* New translations AppResources.resx (Croatian)

* New translations copy.resx (Chinese Traditional)

* New translations copy.resx (Chinese Traditional)

* New translations AppResources.resx (Chinese Traditional)

* New translations copy.resx (Estonian)

* New translations AppResources.resx (Finnish)

* New translations copy.resx (Italian)

* New translations AppResources.resx (Italian)

* New translations copy.resx (Indonesian)

* New translations AppResources.resx (Indonesian)

* New translations copy.resx (Hungarian)

* New translations AppResources.resx (Hungarian)

* New translations copy.resx (Hindi)

* New translations copy.resx (Finnish)

* New translations AppResources.resx (Hindi)

* New translations copy.resx (German)

* New translations AppResources.resx (German)

* New translations copy.resx (French)

* New translations AppResources.resx (French)

* New translations copy.resx (Finnish)

* New translations copy.resx (Vietnamese)
2018-02-27 23:49:47 -05:00
Kyle Spearrin
7e4f79bacb uppercase Bitwarden 2018-02-27 13:37:46 -05:00
Kyle Spearrin
b8267d4329 Uppercase Bitwarden 2018-02-27 13:27:07 -05:00
Kyle Spearrin
205ca693b3 crowdin update_option: update_as_unapproved 2018-02-20 16:17:15 -05:00
Kyle Spearrin
23159c2201 catch ActivityNotFoundException with alert 2018-02-14 17:11:27 -05:00
Kyle Spearrin
884521ced0 premium message on attachments edit page 2018-02-12 08:54:31 -05:00
267 changed files with 17444 additions and 7609 deletions

View File

@@ -6,8 +6,8 @@ Code contributions are welcome! Please commit any pull requests against the `mas
We use a translation tool called [Crowdin](https://crowdin.com) to help manage our localization efforts across many different languages.
If you are interested in helping translate the bitwarden mobile app into another language (or make a translation correction), please register an account at Crowdin and join our project here: https://crowdin.com/project/bitwarden-mobile
If you are interested in helping translate the Bitwarden mobile app into another language (or make a translation correction), please register an account at Crowdin and join our project here: https://crowdin.com/project/bitwarden-mobile
If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/mail/compose/kspearrin).
If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/profile/kspearrin).
You can read Crowdin's getting started guide for translators here: https://support.crowdin.com/crowdin-intro/

5
ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1,5 @@
<!--
Please do not submit feature requests. The [Community Forums][1] has a
section for submitting, voting for, and discussing product feature requests.
[1]: https://community.bitwarden.com
-->

View File

@@ -2,13 +2,13 @@
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-mobile/localized.svg)](https://crowdin.com/project/bitwarden-mobile)
[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby)
# bitwarden mobile
# Bitwarden Mobile Application
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
The bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, UWP, and Xamarin Forms.
The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, UWP, and Xamarin Forms.
<img src="https://i.imgur.com/R7H2tkQ.png" alt="" width="300" height="533" /> <img src="https://i.imgur.com/3BO1Wcg.png" alt="" width="300" height="533" />
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android.png" alt="" width="300" height="533" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios.png" alt="" width="300" height="533" />
# Build/Run
@@ -16,10 +16,14 @@ The bitwarden mobile application is written in C# with Xamarin Android, Xamarin
- [Visual Studio](https://store.xamarin.com/)
**API endpoint**
By default the app is targeting the production API. If you are running the [Core](https://github.com/bitwarden/core) API locally,
you'll need to switch the app to target your local instance. Open `src/App/Utilities/ApiHttpClient.cs` and `src/App/Utilities/IdentityHttpClient.cs` and set the `BaseAddress` to your local
API endpoints (ex. `new Uri("http://localhost:5000")`). Alternatively, you can also adjust the environment endpoints from the environment settings page on the home screen of the app (log out).
**Run the app**
After restoring the nuget packages, you can now build and run the app.
# Contribute

View File

@@ -1,4 +1,4 @@
bitwarden believes that working with security researchers across the globe is crucial to keeping our
Bitwarden believes that working with security researchers across the globe is crucial to keeping our
users safe. If you believe you've found a security issue in our product or service, we encourage you to
notify us. We welcome working with you to resolve the issue promptly. Thanks in advance!
@@ -16,7 +16,7 @@ notify us. We welcome working with you to resolve the issue promptly. Thanks in
# In-scope
- Security issues in any current release of bitwarden. This includes the web vault, browser extension,
- Security issues in any current release of Bitwarden. This includes the web vault, browser extension,
and mobile apps (iOS and Android). Product downloads are available at https://bitwarden.com. Source
code is available at https://github.com/bitwarden.
@@ -24,14 +24,14 @@ notify us. We welcome working with you to resolve the issue promptly. Thanks in
The following bug classes are out-of scope:
- Bugs that are already reported on any of bitwarden's issue trackers (https://github.com/bitwarden),
- Bugs that are already reported on any of Bitwarden's issue trackers (https://github.com/bitwarden),
or that we already know of. Note that some of our issue tracking is private.
- Issues in an upstream software dependency (ex: Xamarin, ASP.NET) which are already reported to the
upstream maintainer.
- Attacks requiring physical access to a user's device.
- Self-XSS
- Issues related to software or protocols not under bitwarden's control
- Vulnerabilities in outdated versions of bitwarden
- Issues related to software or protocols not under Bitwarden's control
- Vulnerabilities in outdated versions of Bitwarden
- Missing security best practices that do not directly lead to a vulnerability
- Issues that do not have any impact on the general public
@@ -39,7 +39,7 @@ While researching, we'd like to ask you to refrain from:
- Denial of service
- Spamming
- Social engineering (including phishing) of bitwarden staff or contractors
- Any physical attempts against bitwarden property or data centers
- Social engineering (including phishing) of Bitwarden staff or contractors
- Any physical attempts against Bitwarden property or data centers
Thank you for helping keep bitwarden and our users safe!
Thank you for helping keep Bitwarden and our users safe!

View File

@@ -1,7 +1,9 @@
install:
- appveyor DownloadFile https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
- appveyor DownloadFile https://aka.ms/vs/15/release/vs_community.exe
- vs_community.exe update --wait --quiet --norestart --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community"
- choco install cloc --no-progress
- "cloc --vcs git --exclude-dir Resources,store,test,UWP,Properties --include-lang C#,JavaScript,TypeScript,PowerShell"
# - appveyor DownloadFile https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
# - appveyor DownloadFile https://aka.ms/vs/15/release/vs_community.exe
# - vs_community.exe update --wait --quiet --norestart --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community"
before_build:
- nuget restore
- IF DEFINED keystore_dec_secret nuget install secure-file -ExcludeVersion

View File

@@ -21,10 +21,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "store", "store", "{92470CBD
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "google", "google", "{2E399654-26A2-46F6-B9CA-1B496A3F370A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWP", "src\UWP\UWP.csproj", "{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "UWP.Images", "src\UWP.Images\UWP.Images.shproj", "{0BE54BBB-7772-4289-BD51-1FDBB0CC2446}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "src\App\App.csproj", "{8A279EE4-4537-4656-9C93-44945E594556}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Publisher", "store\google\Publisher\Publisher.csproj", "{D5D91152-CB01-4F24-A503-304D3A94408B}"
@@ -39,10 +35,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProjectSection
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\UWP.Images\UWP.Images.projitems*{0be54bbb-7772-4289-bd51-1fdbb0cc2446}*SharedItemsImports = 13
src\UWP.Images\UWP.Images.projitems*{3a2d5669-ed71-4f2b-ba85-2d36baa05141}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|ARM = Ad-Hoc|ARM
@@ -344,84 +336,6 @@ Global
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|x64.Build.0 = Release|Any CPU
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|x86.ActiveCfg = Release|Any CPU
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|x86.Build.0 = Release|Any CPU
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|Any CPU.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|Any CPU.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|Any CPU.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|ARM.ActiveCfg = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|ARM.Build.0 = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|ARM.Deploy.0 = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhone.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhone.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhone.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x64.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x64.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x64.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x86.ActiveCfg = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x86.Build.0 = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x86.Deploy.0 = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|Any CPU.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|Any CPU.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|Any CPU.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|ARM.ActiveCfg = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|ARM.Build.0 = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|ARM.Deploy.0 = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhone.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhone.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhone.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhoneSimulator.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhoneSimulator.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhoneSimulator.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x64.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x64.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x64.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x86.ActiveCfg = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x86.Build.0 = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x86.Deploy.0 = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|Any CPU.ActiveCfg = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|ARM.ActiveCfg = Debug|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|ARM.Build.0 = Debug|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|ARM.Deploy.0 = Debug|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|iPhone.ActiveCfg = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x64.ActiveCfg = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x64.Build.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x64.Deploy.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x86.ActiveCfg = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x86.Build.0 = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x86.Deploy.0 = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|Any CPU.ActiveCfg = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|Any CPU.Build.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|Any CPU.Deploy.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|ARM.ActiveCfg = Debug|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|ARM.Build.0 = Debug|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|ARM.Deploy.0 = Debug|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|iPhone.ActiveCfg = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|iPhone.Build.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|iPhone.Deploy.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|iPhoneSimulator.ActiveCfg = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|iPhoneSimulator.Build.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|iPhoneSimulator.Deploy.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|x64.ActiveCfg = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|x64.Build.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|x64.Deploy.0 = Debug|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|x86.ActiveCfg = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|x86.Build.0 = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.FDroid|x86.Deploy.0 = Debug|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|Any CPU.ActiveCfg = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|ARM.ActiveCfg = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|ARM.Build.0 = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|ARM.Deploy.0 = Release|ARM
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|iPhone.ActiveCfg = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|iPhoneSimulator.ActiveCfg = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x64.ActiveCfg = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x64.Build.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x64.Deploy.0 = Release|x64
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x86.ActiveCfg = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x86.Build.0 = Release|x86
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x86.Deploy.0 = Release|x86
{8A279EE4-4537-4656-9C93-44945E594556}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{8A279EE4-4537-4656-9C93-44945E594556}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{8A279EE4-4537-4656-9C93-44945E594556}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
@@ -553,8 +467,6 @@ Global
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
{B2538ADA-B605-4D6F-ACD2-62A409680F84} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
{2E399654-26A2-46F6-B9CA-1B496A3F370A} = {92470CBD-9047-4C3C-8EA3-D972D6622D84}
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
{0BE54BBB-7772-4289-BD51-1FDBB0CC2446} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
{8A279EE4-4537-4656-9C93-44945E594556} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
{D5D91152-CB01-4F24-A503-304D3A94408B} = {2E399654-26A2-46F6-B9CA-1B496A3F370A}
EndGlobalSection

View File

@@ -1,6 +1,7 @@
files:
- source: /src/App/Resources/AppResources.resx
translation: /src/App/Resources/AppResources.%two_letters_code%.resx
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
zh-CN: zh-Hans
@@ -9,6 +10,7 @@ files:
pt-BR: pt-BR
- source: /store/apple/en/copy.resx
translation: /store/apple/%two_letters_code%/copy.resx
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
zh-CN: zh-Hans
@@ -17,6 +19,7 @@ files:
pt-BR: pt-BR
- source: /store/google/en/copy.resx
translation: /store/google/%two_letters_code%/copy.resx
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
zh-CN: zh-Hans

View File

@@ -15,7 +15,7 @@
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<AndroidStoreUncompressedFileExtensions />
@@ -472,21 +472,6 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable\list_selector.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\notification_sm.png" />
</ItemGroup>
@@ -873,20 +858,35 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Firebase.Messaging">
<Version>42.1021.1</Version>
<Version>60.1142.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.GooglePlayServices.Analytics">
<Version>42.1021.1</Version>
<Version>60.1142.1</Version>
</PackageReference>
<PackageReference Include="SimpleInjector">
<Version>4.0.12</Version>
<Version>4.3.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Design">
<Version>27.0.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v4">
<Version>27.0.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat">
<Version>25.4.0.2</Version>
<Version>27.0.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v7.CardView">
<Version>27.0.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v7.MediaRouter">
<Version>27.0.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet">
<Version>60.1142.1</Version>
</PackageReference>
<PackageReference Include="XLabs.IoC.SimpleInjector" Version="2.0.5782" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.3" />
<PackageReference Include="Plugin.CurrentActivity" Version="1.0.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.2" />
<PackageReference Include="Plugin.CurrentActivity" Version="2.1.0.4" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\bottom_nav_bg.xml" />
@@ -906,5 +906,119 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\pencil.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\refresh_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\refresh_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\refresh_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\refresh_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\refresh_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\cog_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\cog_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\cog_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\cog_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\cog_alt.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher_round.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_foreground.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_round.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_foreground.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_round.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_foreground.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_round.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_foreground.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_round.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_foreground.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values\ic_launcher_background.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\upload2.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\upload2.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\upload2.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\upload2.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\upload2.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
</Project>

View File

@@ -14,7 +14,7 @@ using XLabs.Ioc;
namespace Bit.Android.Autofill
{
[Service(Permission = Manifest.Permission.BindAutofillService, Label = "bitwarden")]
[Service(Permission = Manifest.Permission.BindAutofillService, Label = "Bitwarden")]
[IntentFilter(new string[] { "android.service.autofill.AutofillService" })]
[MetaData("android.autofill", Resource = "@xml/autofillservice")]
[Register("com.x8bit.bitwarden.Autofill.AutofillService")]

View File

@@ -16,6 +16,7 @@ namespace Bit.Android.Autofill
public Field(ViewNode node)
{
Id = node.Id;
TrackingId = $"{node.Id}_{node.GetHashCode()}";
IdEntry = node.IdEntry;
AutofillId = node.AutofillId;
AutofillType = node.AutofillType;
@@ -68,6 +69,7 @@ namespace Bit.Android.Autofill
}
public string Hint { get; set; }
public int Id { get; private set; }
public string TrackingId { get; private set; }
public string IdEntry { get; set; }
public AutofillId AutofillId { get; private set; }
public AutofillType AutofillType { get; private set; }

View File

@@ -11,8 +11,9 @@ namespace Bit.Android.Autofill
{
private List<Field> _passwordFields = null;
private List<Field> _usernameFields = null;
private HashSet<string> _ignoreSearchTerms = new HashSet<string> { "search", "find", "recipient", "edit" };
private HashSet<string> _passwordTerms = new HashSet<string> { "password", "pswd" };
public HashSet<int> Ids { get; private set; } = new HashSet<int>();
public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>();
public SaveDataType SaveType
{
@@ -32,9 +33,8 @@ namespace Bit.Android.Autofill
}
public HashSet<string> Hints { get; private set; } = new HashSet<string>();
public HashSet<string> FocusedHints { get; private set; } = new HashSet<string>();
public HashSet<string> FieldTrackingIds { get; private set; } = new HashSet<string>();
public List<Field> Fields { get; private set; } = new List<Field>();
public IDictionary<int, Field> IdToFieldMap { get; private set; } =
new Dictionary<int, Field>();
public IDictionary<string, List<Field>> HintToFieldsMap { get; private set; } =
new Dictionary<string, List<Field>>();
public List<AutofillId> IgnoreAutofillIds { get; private set; } = new List<AutofillId>();
@@ -58,21 +58,10 @@ namespace Bit.Android.Autofill
}
else
{
_passwordFields = Fields
.Where(f =>
(!f.IdEntry?.ToLowerInvariant().Contains("search") ?? true) &&
(!f.Hint?.ToLowerInvariant().Contains("search") ?? true) &&
(
f.InputType.HasFlag(InputTypes.TextVariationPassword) ||
f.InputType.HasFlag(InputTypes.TextVariationVisiblePassword) ||
f.InputType.HasFlag(InputTypes.TextVariationWebPassword)
)
).ToList();
_passwordFields = Fields.Where(f => FieldIsPassword(f)).ToList();
if(!_passwordFields.Any())
{
_passwordFields = Fields.Where(f =>
(f.IdEntry?.ToLowerInvariant().Contains("password") ?? false)
|| (f.Hint?.ToLowerInvariant().Contains("password") ?? false)).ToList();
_passwordFields = Fields.Where(f => FieldHasPasswordTerms(f)).ToList();
}
}
@@ -105,7 +94,8 @@ namespace Bit.Android.Autofill
{
foreach(var passwordField in PasswordFields)
{
var usernameField = Fields.TakeWhile(f => f.AutofillId != passwordField.AutofillId).LastOrDefault();
var usernameField = Fields.TakeWhile(f => f.AutofillId != passwordField.AutofillId)
.LastOrDefault();
if(usernameField != null)
{
_usernameFields.Add(usernameField);
@@ -131,19 +121,14 @@ namespace Bit.Android.Autofill
public void Add(Field field)
{
if(Ids.Contains(field.Id))
if(field == null || FieldTrackingIds.Contains(field.TrackingId))
{
return;
}
_passwordFields = _usernameFields = null;
if(field.Id > -1)
{
Ids.Add(field.Id);
IdToFieldMap.Add(field.Id, field);
}
FieldTrackingIds.Add(field.TrackingId);
Fields.Add(field);
AutofillIds.Add(field.AutofillId);
@@ -312,5 +297,45 @@ namespace Bit.Android.Autofill
return null;
}
private bool FieldIsPassword(Field f)
{
var inputTypePassword = f.InputType.HasFlag(InputTypes.TextVariationPassword) ||
f.InputType.HasFlag(InputTypes.TextVariationVisiblePassword) ||
f.InputType.HasFlag(InputTypes.TextVariationWebPassword);
if(!inputTypePassword && f.HtmlInfo != null && f.HtmlInfo.Tag == "input" &&
(f.HtmlInfo.Attributes?.Any() ?? false))
{
foreach(var a in f.HtmlInfo.Attributes)
{
var key = a.First as Java.Lang.String;
var val = a.Second as Java.Lang.String;
if(key != null && val != null && key.ToString() == "type" && val.ToString() == "password")
{
return true;
}
}
}
return inputTypePassword && !ValueContainsAnyTerms(f.IdEntry, _ignoreSearchTerms) &&
!ValueContainsAnyTerms(f.Hint, _ignoreSearchTerms);
}
private bool FieldHasPasswordTerms(Field f)
{
return ValueContainsAnyTerms(f.IdEntry, _passwordTerms) || ValueContainsAnyTerms(f.Hint, _passwordTerms);
}
private bool ValueContainsAnyTerms(string value, HashSet<string> terms)
{
if(string.IsNullOrWhiteSpace(value))
{
return false;
}
var lowerValue = value.ToLowerInvariant();
return terms.Any(t => lowerValue.Contains(t));
}
}
}

View File

@@ -14,7 +14,8 @@ namespace Bit.Android.Autofill
"com.opera.browser.beta","com.opera.mini.native","com.chrome.dev","com.chrome.canary",
"com.google.android.apps.chrome","com.google.android.apps.chrome_dev","com.yandex.browser",
"com.sec.android.app.sbrowser","com.sec.android.app.sbrowser.beta","org.codeaurora.swe.browser",
"com.amazon.cloud9","org.mozilla.klar", "com.duckduckgo.mobile.android"
"com.amazon.cloud9","org.mozilla.klar","com.duckduckgo.mobile.android","mark.via.gp","org.bromite.bromite",
"org.chromium.chrome", "com.kiwibrowser.browser", "com.ecosia.android"
};
public static HashSet<string> ExcludedPackageIds = new HashSet<string>

View File

@@ -3,15 +3,14 @@ using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using System;
namespace Bit.Android
{
[Activity(Theme = "@style/BitwardenTheme.Splash",
Label = "bitwarden",
Icon = "@drawable/icon",
WindowSoftInputMode = SoftInput.StateHidden)]
[Activity(Theme = "@style/BitwardenTheme.Splash", WindowSoftInputMode = SoftInput.StateHidden)]
public class AutofillActivity : Activity
{
private DateTime? _lastLaunch = null;
private string _lastQueriedUri;
public static AutofillCredentials LastCredentials { get; set; }
@@ -93,6 +92,13 @@ namespace Bit.Android
return;
}
var now = DateTime.UtcNow;
if(_lastLaunch.HasValue && (now - _lastLaunch.Value <= TimeSpan.FromSeconds(2)))
{
return;
}
_lastLaunch = now;
var intent = new Intent(this, typeof(MainActivity));
if(!callingIntent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
{

View File

@@ -12,7 +12,7 @@ using Bit.App.Resources;
namespace Bit.Android
{
[Service(Permission = global::Android.Manifest.Permission.BindAccessibilityService, Label = "bitwarden")]
[Service(Permission = global::Android.Manifest.Permission.BindAccessibilityService, Label = "Bitwarden")]
[IntentFilter(new string[] { "android.accessibilityservice.AccessibilityService" })]
[MetaData("android.accessibilityservice", Resource = "@xml/accessibilityservice")]
public class AutofillService : AccessibilityService
@@ -23,12 +23,13 @@ namespace Bit.Android
private const int AutoFillNotificationId = 34573;
private const string SystemUiPackage = "com.android.systemui";
private const string BitwardenPackage = "com.x8bit.bitwarden";
private const string BitwardenWebsite = "bitwarden.com";
private const string BitwardenWebsite = "vault.bitwarden.com";
private static Dictionary<string, Browser> SupportedBrowsers => new List<Browser>
{
new Browser("com.android.chrome", "url_bar"),
new Browser("com.chrome.beta", "url_bar"),
new Browser("org.chromium.chrome", "url_bar"),
new Browser("com.android.browser", "url"),
new Browser("com.brave.browser", "url_bar"),
new Browser("com.opera.browser", "url_field"),
@@ -62,7 +63,11 @@ namespace Bit.Android
new Browser("acr.browser.lightning", "search"),
new Browser("acr.browser.barebones", "search"),
new Browser("com.microsoft.emmx", "url_bar"),
new Browser("com.duckduckgo.mobile.android", "omnibarTextInput")
new Browser("com.duckduckgo.mobile.android", "omnibarTextInput"),
new Browser("mark.via.gp", "aw"),
new Browser("org.bromite.bromite", "url_bar"),
new Browser("com.kiwibrowser.browser", "url_bar"),
new Browser("com.ecosia.android", "url_bar"),
}.ToDictionary(n => n.PackageName);
// Known packages to skip
@@ -124,7 +129,6 @@ namespace Bit.Android
//var testNodes = GetWindowNodes(root, e, n => n.ViewIdResourceName != null && n.Text != null, false);
//var testNodesData = testNodes.Select(n => new { id = n.ViewIdResourceName, text = n.Text });
//testNodes.Dispose();
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
var cancelNotification = true;

View File

@@ -112,7 +112,7 @@ namespace Bit.Android.Controls
private void Control_EditorAction(object sender, TextView.EditorActionEventArgs e)
{
if(_view.ReturnType != ReturnType.Next)
if(_view.TargetReturnType != Bit.App.Enums.ReturnType.Next)
{
_view.Unfocus();
}
@@ -165,23 +165,23 @@ namespace Bit.Android.Controls
private void SetReturnType(ExtendedEntry view)
{
if(view.ReturnType.HasValue)
if(view.TargetReturnType.HasValue)
{
switch(view.ReturnType.Value)
switch(view.TargetReturnType.Value)
{
case ReturnType.Go:
case App.Enums.ReturnType.Go:
Control.ImeOptions = ImeAction.Go;
Control.SetImeActionLabel("Go", ImeAction.Go);
break;
case ReturnType.Next:
case App.Enums.ReturnType.Next:
Control.ImeOptions = ImeAction.Next;
Control.SetImeActionLabel("Next", ImeAction.Next);
break;
case ReturnType.Search:
case App.Enums.ReturnType.Search:
Control.ImeOptions = ImeAction.Search;
Control.SetImeActionLabel("Search", ImeAction.Search);
break;
case ReturnType.Send:
case App.Enums.ReturnType.Send:
Control.ImeOptions = ImeAction.Send;
Control.SetImeActionLabel("Send", ImeAction.Send);
break;
@@ -206,7 +206,7 @@ namespace Bit.Android.Controls
private void SetMaxLength(ExtendedEntry view)
{
Control.SetFilters(new IInputFilter[] { new InputFilterLengthFilter(view.MaxLength) });
Control.SetFilters(new IInputFilter[] { new InputFilterLengthFilter(view.TargetMaxLength) });
}
}
}

View File

@@ -21,15 +21,14 @@ using Bit.App.Enums;
namespace Bit.Android
{
[Activity(Label = "bitwarden",
Icon = "@drawable/icon",
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
Exported = false)]
[Activity(ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, Exported = false)]
public class MainActivity : FormsAppCompatActivity
{
private const string HockeyAppId = "d3834185b4a643479047b86c65293d42";
private Java.Util.Regex.Pattern _otpPattern = Java.Util.Regex.Pattern.Compile("^.*?([cbdefghijklnrtuv]{32,64})$");
private IDeviceActionService _deviceActionService;
private IDeviceInfoService _deviceInfoService;
private IAppSettingsService _appSettingsService;
private ISettings _settings;
private AppOptions _appOptions;
@@ -72,6 +71,8 @@ namespace Bit.Android
.SetValue(null, Color.FromHex("d2d6de"));
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
_appSettingsService = Resolver.Resolve<IAppSettingsService>();
_settings = Resolver.Resolve<ISettings>();
_appOptions = GetOptions();
LoadApplication(new App.App(
@@ -84,7 +85,7 @@ namespace Bit.Android
Resolver.Resolve<ILockService>(),
Resolver.Resolve<ILocalizeService>(),
Resolver.Resolve<IAppInfoService>(),
Resolver.Resolve<IAppSettingsService>(),
_appSettingsService,
_deviceActionService));
if(_appOptions?.Uri == null)
@@ -137,7 +138,7 @@ namespace Bit.Android
// ref https://bugzilla.xamarin.com/show_bug.cgi?id=36907
Task.Delay(10).Wait();
if(Utilities.NfcEnabled())
if(_deviceInfoService.NfcEnabled)
{
try
{
@@ -148,6 +149,11 @@ namespace Bit.Android
System.Diagnostics.Debug.WriteLine(e);
}
}
if(_appSettingsService.Locked)
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, "Resumed", false);
}
}
protected override void OnNewIntent(Intent intent)
@@ -209,7 +215,7 @@ namespace Bit.Android
private void ListenYubiKey(bool listen)
{
if(!Utilities.NfcEnabled())
if(!_deviceInfoService.NfcEnabled)
{
return;
}
@@ -227,8 +233,12 @@ namespace Bit.Android
ndef.AddDataScheme("https");
var filters = new IntentFilter[] { ndef };
// register for foreground dispatch so we'll receive tags according to our intent filters
adapter.EnableForegroundDispatch(this, pendingIntent, filters, null);
try
{
// register for foreground dispatch so we'll receive tags according to our intent filters
adapter.EnableForegroundDispatch(this, pendingIntent, filters, null);
}
catch { }
}
else
{

View File

@@ -13,9 +13,9 @@ using Plugin.Fingerprint;
using Plugin.Settings;
using XLabs.Ioc;
using System.Threading.Tasks;
using FFImageLoading.Forms.Droid;
using XLabs.Ioc.SimpleInjectorContainer;
using SimpleInjector;
using Android.Gms.Security;
namespace Bit.Android
{
@@ -24,13 +24,11 @@ namespace Bit.Android
#else
[Application(Debuggable = false)]
#endif
public class MainApplication : Application, Application.IActivityLifecycleCallbacks
public class MainApplication : Application, ProviderInstaller.IProviderInstallListener
{
private const string FirstLaunchKey = "firstLaunch";
private const string LastVersionCodeKey = "lastVersionCode";
public static Context AppContext;
public MainApplication(IntPtr handle, JniHandleOwnership transer)
: base(handle, transer)
{
@@ -40,6 +38,11 @@ namespace Bit.Android
{
SetIoc(this);
}
if(Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
{
ProviderInstaller.InstallIfNeededAsync(ApplicationContext, this);
}
}
private void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e)
@@ -56,52 +59,13 @@ namespace Bit.Android
// workaround for app compat bug
// ref https://forums.xamarin.com/discussion/62414/app-resuming-results-in-crash-with-formsappcompatactivity
Task.Delay(10).Wait();
RegisterActivityLifecycleCallbacks(this);
AppContext = ApplicationContext;
}
public override void OnTerminate()
{
base.OnTerminate();
UnregisterActivityLifecycleCallbacks(this);
}
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivityDestroyed(Activity activity)
{
}
public void OnActivityPaused(Activity activity)
{
}
public void OnActivityResumed(Activity activity)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
{
}
public void OnActivityStarted(Activity activity)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivityStopped(Activity activity)
{
CrossCurrentActivity.Current.Init(this);
}
public static void SetIoc(Application application)
{
Refractored.FabControl.Droid.FloatingActionButtonViewRenderer.Init();
CachedImageRenderer.Init(true);
FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true);
ZXing.Net.Mobile.Forms.Android.Platform.Init();
CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity);
@@ -109,8 +73,8 @@ namespace Bit.Android
var container = new Container();
// Android Stuff
container.RegisterSingleton(application.ApplicationContext);
container.RegisterSingleton<Application>(application);
container.RegisterInstance(application.ApplicationContext);
container.RegisterInstance<Application>(application);
// Services
container.RegisterSingleton<IDatabaseService, DatabaseService>();
@@ -158,9 +122,9 @@ namespace Bit.Android
container.RegisterSingleton<ICipherCollectionRepository, CipherCollectionRepository>();
// Other
container.RegisterSingleton(CrossSettings.Current);
container.RegisterSingleton(CrossConnectivity.Current);
container.RegisterSingleton(CrossFingerprint.Current);
container.RegisterInstance(CrossSettings.Current);
container.RegisterInstance(CrossConnectivity.Current);
container.RegisterInstance(CrossFingerprint.Current);
// Push
#if FDROID
@@ -174,5 +138,13 @@ namespace Bit.Android
container.Verify();
Resolver.SetResolver(new SimpleInjectorResolver(container));
}
public void OnProviderInstallFailed(int errorCode, Intent recoveryIntent)
{
}
public void OnProviderInstalled()
{
}
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.x8bit.bitwarden" android:versionName="1.14.4" android:installLocation="auto" android:versionCode="502" xmlns:tools="http://schemas.android.com/tools">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.x8bit.bitwarden" android:versionName="1.18.0" android:installLocation="auto" android:versionCode="502" xmlns:tools="http://schemas.android.com/tools">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.INTERNET" />
@@ -12,7 +12,8 @@
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<application android:label="bitwarden" android:theme="@style/BitwardenTheme" android:allowBackup="false">
<application android:label="Bitwarden" android:theme="@style/BitwardenTheme" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round">
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.x8bit.bitwarden.fileprovider"
@@ -30,10 +31,11 @@
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
<category android:name="com.x8bit.bitwarden" />
</intent-filter>
</receiver>
<activity android:name="net.hockeyapp.android.UpdateActivity" android:exported="false" android:icon="@drawable/icon" />
<activity android:name="net.hockeyapp.android.UpdateActivity" android:exported="false" />
<meta-data android:name="android.max_aspect" android:value="2.1" />
</application>
</manifest>

View File

@@ -10,7 +10,7 @@ using Android.App;
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("8bit Solutions LLC")]
[assembly: AssemblyProduct("bitwarden")]
[assembly: AssemblyProduct("Bitwarden")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#3C8DBC</color>
</resources>

View File

@@ -5,9 +5,9 @@
</string>
<string name="AutoFillServiceDescription">
It can be difficult and insecure for users to switch between apps to copy/paste username and password information
from their bitwarden vault.\n\nUsing this accessibility service allows bitwarden to detect and read input fields on
your device\'s screen. Whenever bitwarden detects a password field on the screen a notification will appear that allows
you to quickly access your bitwarden vault and automatically fill (auto-fill) the correct login information into the
from their Bitwarden vault.\n\nUsing this accessibility service allows Bitwarden to detect and read input fields on
your device\'s screen. Whenever Bitwarden detects a password field on the screen a notification will appear that allows
you to quickly access your Bitwarden vault and automatically fill (auto-fill) the correct login information into the
necessary fields.
</string>
<string name="MyVault">

View File

@@ -13,5 +13,6 @@
<item name="android:windowBackground">@color/lightgray</item>
<item name="windowActionModeOverlay">true</item>
<item name="android:navigationBarColor">@color/darkaccent</item>
<item name="android:actionModeBackground">@color/darkaccent</item>
</style>
</resources>

View File

@@ -44,7 +44,15 @@ namespace Bit.Android.Services
_keyStore = KeyStore.GetInstance(AndroidKeyStore);
_keyStore.Load(null);
GenerateStoreKey();
try
{
GenerateStoreKey(true);
}
catch
{
GenerateStoreKey(false);
}
GenerateAesKey();
}
@@ -128,7 +136,7 @@ namespace Bit.Android.Services
}
}
private void GenerateStoreKey()
private void GenerateStoreKey(bool withDate)
{
if(_keyStore.ContainsAlias(KeyAlias))
{
@@ -144,27 +152,33 @@ namespace Bit.Android.Services
{
var subject = new X500Principal($"CN={KeyAlias}");
var spec = new KeyPairGeneratorSpec.Builder(Application.Context)
var builder = new KeyPairGeneratorSpec.Builder(Application.Context)
.SetAlias(KeyAlias)
.SetSubject(subject)
.SetSerialNumber(BigInteger.Ten)
.SetStartDate(new Date(0))
.SetEndDate(end.Time)
.Build();
.SetSerialNumber(BigInteger.Ten);
if(withDate)
{
builder.SetStartDate(new Date(0)).SetEndDate(end.Time);
}
var spec = builder.Build();
var gen = KeyPairGenerator.GetInstance(KeyProperties.KeyAlgorithmRsa, AndroidKeyStore);
gen.Initialize(spec);
gen.GenerateKeyPair();
}
else
{
var spec = new KeyGenParameterSpec.Builder(KeyAlias, KeyStorePurpose.Decrypt | KeyStorePurpose.Encrypt)
var builder = new KeyGenParameterSpec.Builder(KeyAlias, KeyStorePurpose.Decrypt | KeyStorePurpose.Encrypt)
.SetBlockModes(KeyProperties.BlockModeGcm)
.SetEncryptionPaddings(KeyProperties.EncryptionPaddingNone)
.SetKeyValidityStart(new Date(0))
.SetKeyValidityEnd(end.Time)
.Build();
.SetEncryptionPaddings(KeyProperties.EncryptionPaddingNone);
if(withDate)
{
builder.SetKeyValidityStart(new Date(0)).SetKeyValidityEnd(end.Time);
}
var spec = builder.Build();
var gen = KeyGenerator.GetInstance(KeyProperties.KeyAlgorithmAes, AndroidKeyStore);
gen.Init(spec);
gen.GenerateKey();

View File

@@ -24,6 +24,7 @@ using Bit.Android.Autofill;
using System.Linq;
using Plugin.Settings.Abstractions;
using Android.Views.InputMethods;
using Android.Widget;
namespace Bit.Android.Services
{
@@ -424,36 +425,167 @@ namespace Bit.Android.Services
public void OpenAutofillSettings()
{
var activity = (MainActivity)CurrentContext;
var intent = new Intent(Settings.ActionRequestSetAutofillService);
intent.SetData(global::Android.Net.Uri.Parse("package:com.x8bit.bitwarden"));
activity.StartActivity(intent);
try
{
var activity = (MainActivity)CurrentContext;
var intent = new Intent(Settings.ActionRequestSetAutofillService);
intent.SetData(global::Android.Net.Uri.Parse("package:com.x8bit.bitwarden"));
activity.StartActivity(intent);
}
catch(ActivityNotFoundException)
{
var alertBuilder = new AlertDialog.Builder((MainActivity)CurrentContext);
alertBuilder.SetMessage(AppResources.BitwardenAutofillGoToSettings);
alertBuilder.SetCancelable(true);
alertBuilder.SetPositiveButton(AppResources.Ok, (sender, args) =>
{
(sender as AlertDialog)?.Cancel();
});
alertBuilder.Create().Show();
}
}
public void ShowLoading(string text)
public async Task ShowLoadingAsync(string text)
{
if(_progressDialog != null)
{
HideLoading();
await HideLoadingAsync();
}
var activity = (MainActivity)CurrentContext;
_progressDialog = new ProgressDialog(activity);
_progressDialog.SetMessage(text);
_progressDialog.SetCancelable(true);
_progressDialog.SetCancelable(false);
_progressDialog.Show();
}
public void HideLoading()
public Task HideLoadingAsync()
{
if(_progressDialog == null)
if(_progressDialog != null)
{
return;
_progressDialog.Dismiss();
_progressDialog.Dispose();
_progressDialog = null;
}
_progressDialog.Dismiss();
_progressDialog.Dispose();
_progressDialog = null;
return Task.FromResult(0);
}
public Task<string> DisplayPromptAync(string title = null, string description = null, string text = null)
{
var activity = (MainActivity)CurrentContext;
if(activity == null)
{
return Task.FromResult<string>(null);
}
var alertBuilder = new AlertDialog.Builder(activity);
alertBuilder.SetTitle(title);
alertBuilder.SetMessage(description);
var input = new EditText(activity)
{
InputType = global::Android.Text.InputTypes.ClassText
};
if(text == null)
{
text = string.Empty;
}
input.Text = text;
input.SetSelection(text.Length);
alertBuilder.SetView(input);
var result = new TaskCompletionSource<string>();
alertBuilder.SetPositiveButton(AppResources.Ok, (sender, args) =>
{
result.TrySetResult(input.Text ?? string.Empty);
});
alertBuilder.SetNegativeButton(AppResources.Cancel, (sender, args) =>
{
result.TrySetResult(null);
});
var alert = alertBuilder.Create();
alert.Window.SetSoftInputMode(global::Android.Views.SoftInput.StateVisible);
alert.Show();
return result.Task;
}
public Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons)
{
var activity = (MainActivity)CurrentContext;
if(activity == null)
{
return Task.FromResult<string>(null);
}
var result = new TaskCompletionSource<string>();
var alertBuilder = new AlertDialog.Builder(activity);
alertBuilder.SetTitle(title);
if(!string.IsNullOrWhiteSpace(message))
{
if(buttons != null && buttons.Length > 2)
{
if(!string.IsNullOrWhiteSpace(title))
{
alertBuilder.SetTitle($"{title}: {message}");
}
else
{
alertBuilder.SetTitle(message);
}
}
else
{
alertBuilder.SetMessage(message);
}
}
if(buttons != null)
{
if(buttons.Length > 2)
{
alertBuilder.SetItems(buttons, (sender, args) =>
{
result.TrySetResult(buttons[args.Which]);
});
}
else
{
if(buttons.Length > 0)
{
alertBuilder.SetPositiveButton(buttons[0], (sender, args) =>
{
result.TrySetResult(buttons[0]);
});
}
if(buttons.Length > 1)
{
alertBuilder.SetNeutralButton(buttons[1], (sender, args) =>
{
result.TrySetResult(buttons[1]);
});
}
}
}
if(!string.IsNullOrWhiteSpace(cancel))
{
alertBuilder.SetNegativeButton(cancel, (sender, args) =>
{
result.TrySetResult(cancel);
});
}
var alert = alertBuilder.Create();
alert.CancelEvent += (o, args) => { result.TrySetResult(null); };
alert.Show();
return result.Task;
}
}
}

View File

@@ -1,5 +1,7 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Nfc;
using Android.OS;
using Android.Views.Autofill;
using Bit.App.Abstractions;
@@ -45,7 +47,7 @@ namespace Bit.Android.Services
return 1f;
}
}
public bool NfcEnabled => Utilities.NfcEnabled();
public bool NfcEnabled => NfcIsEnabled();
public bool HasCamera => CrossCurrentActivity.Current.Activity.PackageManager.HasSystemFeature(
PackageManager.FeatureCamera);
public bool AutofillServiceSupported => AutofillSupported();
@@ -56,10 +58,17 @@ namespace Bit.Android.Services
{
return false;
}
var afm = (AutofillManager)CrossCurrentActivity.Current.Activity.GetSystemService(
Java.Lang.Class.FromType(typeof(AutofillManager)));
return afm.IsAutofillSupported;
}
public bool NfcIsEnabled()
{
var activity = CrossCurrentActivity.Current.Activity;
var manager = (NfcManager)activity.GetSystemService(Context.NfcService);
var adapter = manager.DefaultAdapter;
return adapter != null && adapter.IsEnabled;
}
}
}

View File

@@ -3,20 +3,12 @@ using Android.App;
using Android.Content;
using Java.Security;
using System.IO;
using Android.Nfc;
using Android.Provider;
namespace Bit.Android
{
public static class Utilities
{
public static bool NfcEnabled()
{
var manager = (NfcManager)Application.Context.GetSystemService("nfc");
var adapter = manager.DefaultAdapter;
return adapter != null && adapter.IsEnabled;
}
public static void SendCrashEmail(Exception e, bool includeSecurityProviders = true)
{
SendCrashEmail(e.Message + "\n\n" + e.StackTrace, includeSecurityProviders);
@@ -38,7 +30,7 @@ namespace Bit.Android
emailIntent.SetType("plain/text");
emailIntent.PutExtra(Intent.ExtraEmail, new String[] { "hello@bitwarden.com" });
emailIntent.PutExtra(Intent.ExtraSubject, "bitwarden Crash Report");
emailIntent.PutExtra(Intent.ExtraSubject, "Bitwarden Crash Report");
emailIntent.PutExtra(Intent.ExtraText, FormatText(text, includeSecurityProviders));
Application.Context.StartActivity(Intent.CreateChooser(emailIntent, "Send mail..."));
@@ -50,7 +42,7 @@ namespace Bit.Android
emailIntent.SetType("plain/text");
emailIntent.PutExtra(Intent.ExtraEmail, new String[] { "hello@bitwarden.com" });
emailIntent.PutExtra(Intent.ExtraSubject, "bitwarden Crash Report");
emailIntent.PutExtra(Intent.ExtraSubject, "Bitwarden Crash Report");
emailIntent.PutExtra(Intent.ExtraText, FormatText(text, includeSecurityProviders));
act.StartActivity(Intent.CreateChooser(emailIntent, "Send mail..."));
@@ -68,7 +60,7 @@ namespace Bit.Android
private static string FormatText(string text, bool includeSecurityProviders = true)
{
var crashMessage = "bitwarden has crashed. Please send this email to our support team so that we can help " +
var crashMessage = "Bitwarden has crashed. Please send this email to our support team so that we can help " +
"resolve the problem for you. Thank you.";
text = crashMessage + "\n\n =============================================== \n\n" + text;

View File

@@ -17,5 +17,6 @@ namespace Bit.App.Abstractions
string ApiUrl { get; set; }
string IdentityUrl { get; set; }
string IconsUrl { get; set; }
bool ClearCiphersCache { get; set; }
}
}

View File

@@ -6,8 +6,8 @@ namespace Bit.App.Abstractions
{
public interface IDeviceActionService
{
void ShowLoading(string text);
void HideLoading();
Task ShowLoadingAsync(string text);
Task HideLoadingAsync();
void Toast(string text, bool longDuration = false);
void CopyToClipboard(string text);
bool OpenFile(byte[] fileData, string id, string fileName);
@@ -22,5 +22,7 @@ namespace Bit.App.Abstractions
void OpenAccessibilitySettings();
void OpenAutofillSettings();
Task LaunchAppAsync(string appName, Page page);
Task<string> DisplayPromptAync(string title = null, string description = null, string text = null);
Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons);
}
}

View File

@@ -7,8 +7,8 @@ namespace Bit.App.Abstractions
public interface ILockService
{
void UpdateLastActivity();
Task<LockType> GetLockTypeAsync(bool forceLock);
Task CheckLockAsync(bool forceLock);
Task<LockType> GetLockTypeAsync(bool forceLock, bool onlyIfAlreadyLocked = false);
Task CheckLockAsync(bool forceLock, bool onlyIfAlreadyLocked = false);
bool TopPageIsLock();
}
}

View File

@@ -78,14 +78,14 @@ namespace Bit.App
MainPage = new ExtendedNavigationPage(new HomePage());
}
if(Device.RuntimePlatform == Device.iOS)
MessagingCenter.Subscribe<Application, bool>(Current, "Resumed", async (sender, forceLock) =>
{
MessagingCenter.Subscribe<Application, bool>(Current, "Resumed", async (sender, forceLock) =>
Device.BeginInvokeOnMainThread(async () => await _lockService.CheckLockAsync(forceLock));
if(Device.RuntimePlatform == Device.iOS)
{
Device.BeginInvokeOnMainThread(async () => await _lockService.CheckLockAsync(forceLock));
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
});
}
}
});
}
protected async override void OnStart()

View File

@@ -25,17 +25,17 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="HockeySDK.Xamarin" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="HockeySDK.Xamarin" Version="5.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="Plugin.Fingerprint" Version="1.4.6-beta4" />
<PackageReference Include="Plugin.Fingerprint" Version="1.4.7" />
<PackageReference Include="Refractored.FloatingActionButtonForms" Version="2.1.0" />
<PackageReference Include="sqlite-net-pcl" Version="1.5.166-beta" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="Xam.Plugin.Connectivity" Version="3.0.3" />
<PackageReference Include="Xam.Plugin.Connectivity" Version="3.2.0" />
<PackageReference Include="Xam.Plugins.Settings" Version="3.1.1" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.3.4" />
<PackageReference Include="Xamarin.Forms" Version="2.5.0.122203" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.3.840" />
<PackageReference Include="Xamarin.Forms" Version="3.1.0.697729" />
<PackageReference Include="XLabs.IoC" Version="2.0.5782" />
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.1.47" />
</ItemGroup>

View File

@@ -46,6 +46,7 @@
public const string IdentityUrl = "other:identityUrl";
public const string IconsUrl = "other:iconsUrl";
public const string FailedPinAttempts = "other:failedPinAttempts";
public const string ClearCiphersCache = "other:clearCiphersCache";
public const int SelectFileRequestCode = 42;
public const int SelectFilePermissionRequestCode = 43;

View File

@@ -30,7 +30,7 @@ namespace Bit.App.Controls
BackgroundColor = Color.FromHex("efeff4");
}
protected override void OnAppearing()
protected async override void OnAppearing()
{
if(_requireAuth && !_authService.IsAuthenticated)
{
@@ -52,6 +52,7 @@ namespace Bit.App.Controls
}
_googleAnalyticsService.TrackPage(GetType().Name);
await _lockService.CheckLockAsync(false, true);
base.OnAppearing();
}

View File

@@ -25,8 +25,8 @@ namespace Bit.App.Controls
public static readonly BindableProperty BottomBorderColorProperty =
BindableProperty.Create(nameof(BottomBorderColor), typeof(Color), typeof(ExtendedEntry), Color.Default);
public static readonly BindableProperty MaxLengthProperty =
BindableProperty.Create(nameof(MaxLength), typeof(int), typeof(ExtendedEntry), int.MaxValue);
public static readonly BindableProperty TargetMaxLengthProperty =
BindableProperty.Create(nameof(TargetMaxLength), typeof(int), typeof(ExtendedEntry), int.MaxValue);
public bool HasBorder
{
@@ -46,13 +46,13 @@ namespace Bit.App.Controls
set { SetValue(BottomBorderColorProperty, value); }
}
public int MaxLength
public int TargetMaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
set { SetValue(MaxLengthProperty, value); }
get { return (int)GetValue(TargetMaxLengthProperty); }
set { SetValue(TargetMaxLengthProperty, value); }
}
public ReturnType? ReturnType { get; set; }
public Enums.ReturnType? TargetReturnType { get; set; }
public bool? Autocorrect { get; set; }
public bool DisableAutocapitalize { get; set; }
public bool AllowClear { get; set; }

View File

@@ -6,10 +6,10 @@ namespace Bit.App.Controls
public class ExtendedViewCell : ViewCell
{
public static readonly BindableProperty BackgroundColorProperty =
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedTextCell), Color.White);
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedViewCell), Color.White);
public static readonly BindableProperty ShowDisclousureProperty =
BindableProperty.Create(nameof(ShowDisclousure), typeof(bool), typeof(ExtendedTextCell), false);
BindableProperty.Create(nameof(ShowDisclousure), typeof(bool), typeof(ExtendedViewCell), false);
public Color BackgroundColor
{

View File

@@ -1,6 +1,7 @@
using Bit.App.Abstractions;
using FFImageLoading.Forms;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using XLabs.Ioc;
@@ -10,6 +11,7 @@ namespace Bit.App.Controls
{
private VisualElement _nextElement;
private TapGestureRecognizer _tgr;
private StackLayout _buttonStackLayout = null;
public FormEntryCell(
string labelText,
@@ -19,7 +21,8 @@ namespace Bit.App.Controls
bool useLabelAsPlaceholder = false,
string imageSource = null,
Thickness? containerPadding = null,
bool useButton = false)
string button1 = null,
string button2 = null)
{
if(!useLabelAsPlaceholder)
{
@@ -82,6 +85,45 @@ namespace Bit.App.Controls
VerticalOptions = LayoutOptions.CenterAndExpand
};
if(!useLabelAsPlaceholder)
{
formStackLayout.Children.Add(Label);
}
formStackLayout.Children.Add(Entry);
imageStackLayout.Children.Add(formStackLayout);
if(!string.IsNullOrWhiteSpace(button1) || !string.IsNullOrWhiteSpace(button2))
{
_buttonStackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
VerticalOptions = LayoutOptions.CenterAndExpand,
Spacing = 5
};
imageStackLayout.Children.Add(_buttonStackLayout);
if(!string.IsNullOrWhiteSpace(button1))
{
Button1 = new ExtendedButton { Image = button1 };
_buttonStackLayout.Children.Add(Button1);
Button1.Padding = new Thickness(0);
Button1.BackgroundColor = Color.Transparent;
Button1.WidthRequest = 40;
Button1.VerticalOptions = LayoutOptions.FillAndExpand;
}
if(!string.IsNullOrWhiteSpace(button2))
{
Button2 = new ExtendedButton { Image = button2 };
_buttonStackLayout.Children.Add(Button2);
Button2.Padding = new Thickness(0);
Button2.BackgroundColor = Color.Transparent;
Button2.WidthRequest = 40;
Button2.VerticalOptions = LayoutOptions.FillAndExpand;
}
}
if(Device.RuntimePlatform == Device.Android)
{
var deviceInfo = Resolver.Resolve<IDeviceInfoService>();
@@ -106,25 +148,11 @@ namespace Bit.App.Controls
imageStackLayout.AdjustPaddingForDevice();
}
}
if(!useLabelAsPlaceholder)
else if(Device.RuntimePlatform == Device.UWP)
{
formStackLayout.Children.Add(Label);
}
formStackLayout.Children.Add(Entry);
imageStackLayout.Children.Add(formStackLayout);
if(useButton)
{
Button = new ExtendedButton();
imageStackLayout.Children.Add(Button);
if(Device.RuntimePlatform == Device.Android)
if(_buttonStackLayout != null)
{
Button.Padding = new Thickness(0);
Button.BackgroundColor = Color.Transparent;
Button.WidthRequest = 40;
_buttonStackLayout.Spacing = 0;
}
}
@@ -133,7 +161,8 @@ namespace Bit.App.Controls
public Label Label { get; private set; }
public ExtendedEntry Entry { get; private set; }
public ExtendedButton Button { get; private set; }
public ExtendedButton Button1 { get; private set; }
public ExtendedButton Button2 { get; private set; }
public VisualElement NextElement
{
get => _nextElement;
@@ -142,14 +171,15 @@ namespace Bit.App.Controls
_nextElement = value;
if(_nextElement != null && Entry != null)
{
Entry.ReturnType = Enums.ReturnType.Next;
Entry.TargetReturnType = Enums.ReturnType.Next;
}
else if(Entry != null)
{
Entry.ReturnType = null;
Entry.TargetReturnType = null;
}
}
}
public Dictionary<string, object> MetaData { get; set; }
public void InitEvents()
{

View File

@@ -0,0 +1,47 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class FormSwitchCell : ExtendedViewCell
{
public FormSwitchCell(string labelText, string button1 = null)
{
Label = new Label
{
Text = labelText,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalTextAlignment = TextAlignment.Center,
TextColor = Color.Black,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
};
Switch = new Switch
{
VerticalOptions = LayoutOptions.Center
};
var stackLayout = new StackLayout
{
Padding = new Thickness(15, 5),
Orientation = StackOrientation.Horizontal,
Children = { Label, Switch }
};
stackLayout.AdjustPaddingForDevice();
if(!string.IsNullOrWhiteSpace(button1))
{
Button1 = new ExtendedButton { Image = button1 };
stackLayout.Children.Add(Button1);
Button1.BackgroundColor = Color.Transparent;
Button1.Padding = new Thickness(0);
Button1.WidthRequest = 40;
Button1.VerticalOptions = LayoutOptions.FillAndExpand;
}
View = stackLayout;
}
public Switch Switch { get; private set; }
public Label Label { get; set; }
public ExtendedButton Button1 { get; set; }
}
}

View File

@@ -54,7 +54,8 @@ namespace Bit.App.Controls
var buttonStackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
VerticalOptions = LayoutOptions.CenterAndExpand
VerticalOptions = LayoutOptions.CenterAndExpand,
Spacing = 5
};
if(subText != null)
@@ -75,8 +76,11 @@ namespace Bit.App.Controls
{
Image = button1Image,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(0)
VerticalOptions = LayoutOptions.FillAndExpand,
Margin = new Thickness(0),
Padding = new Thickness(0),
BackgroundColor = Color.Transparent,
WidthRequest = 40
};
buttonStackLayout.Children.Add(Button1);
@@ -88,8 +92,11 @@ namespace Bit.App.Controls
{
Image = button2Image,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(0)
VerticalOptions = LayoutOptions.FillAndExpand,
Margin = new Thickness(0),
Padding = new Thickness(0),
BackgroundColor = Color.Transparent,
WidthRequest = 40
};
buttonStackLayout.Children.Add(Button2);
@@ -97,21 +104,6 @@ namespace Bit.App.Controls
if(Device.RuntimePlatform == Device.Android)
{
buttonStackLayout.Spacing = 5;
if(Button1 != null)
{
Button1.Padding = new Thickness(0);
Button1.BackgroundColor = Color.Transparent;
Button1.WidthRequest = 40;
}
if(Button2 != null)
{
Button2.Padding = new Thickness(0);
Button2.BackgroundColor = Color.Transparent;
Button2.WidthRequest = 40;
}
containerStackLayout.AdjustPaddingForDevice();
}
else if(Device.RuntimePlatform == Device.UWP)

View File

@@ -20,7 +20,7 @@ namespace Bit.App.Controls
Entry = new ExtendedEntry
{
Keyboard = Keyboard.Numeric,
MaxLength = 4,
TargetMaxLength = 4,
HideCursor = true
};

View File

@@ -7,6 +7,7 @@
Duo = 2,
YubiKey = 3,
U2f = 4,
Remember = 5
Remember = 5,
OrganizationDuo = 6
}
}

View File

@@ -0,0 +1,12 @@
namespace Bit.App.Enums
{
public enum UriMatchType : byte
{
Domain = 0,
Host = 1,
StartsWith = 2,
Exact = 3,
RegularExpression = 4,
Never = 5
}
}

View File

@@ -1,12 +0,0 @@
namespace Bit.App.Models.Api
{
public class CardDataModel : CipherDataModel
{
public string CardholderName { get; set; }
public string Brand { get; set; }
public string Number { get; set; }
public string ExpMonth { get; set; }
public string ExpYear { get; set; }
public string Code { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
namespace Bit.App.Models.Api
{
public class CardType
{
public CardType() { }
public CardType(Cipher cipher)
{
CardholderName = cipher.Card.CardholderName?.EncryptedString;
Brand = cipher.Card.Brand?.EncryptedString;
Number = cipher.Card.Number?.EncryptedString;
ExpMonth = cipher.Card.ExpMonth?.EncryptedString;
ExpYear = cipher.Card.ExpYear?.EncryptedString;
Code = cipher.Card.Code?.EncryptedString;
}
public string CardholderName { get; set; }
public string Brand { get; set; }
public string Number { get; set; }
public string ExpMonth { get; set; }
public string ExpYear { get; set; }
public string Code { get; set; }
}
}

View File

@@ -1,11 +0,0 @@
using System.Collections.Generic;
namespace Bit.App.Models.Api
{
public abstract class CipherDataModel
{
public string Name { get; set; }
public string Notes { get; set; }
public IEnumerable<FieldDataModel> Fields { get; set; }
}
}

View File

@@ -1,11 +0,0 @@
using Bit.App.Enums;
namespace Bit.App.Models.Api
{
public class FieldDataModel
{
public FieldType Type { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace Bit.App.Models.Api
{
public class FieldType
{
public FieldType() { }
public FieldType(Field field)
{
Type = field.Type;
Name = field.Name?.EncryptedString;
Value = field.Value?.EncryptedString;
}
public Enums.FieldType Type { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
}

View File

@@ -1,24 +0,0 @@
namespace Bit.App.Models.Api
{
public class IdentityDataModel : CipherDataModel
{
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string SSN { get; set; }
public string Username { get; set; }
public string PassportNumber { get; set; }
public string LicenseNumber { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
namespace Bit.App.Models.Api
{
public class IdentityType
{
public IdentityType() { }
public IdentityType(Cipher cipher)
{
Title = cipher.Identity.Title?.EncryptedString;
FirstName = cipher.Identity.FirstName?.EncryptedString;
MiddleName = cipher.Identity.MiddleName?.EncryptedString;
LastName = cipher.Identity.LastName?.EncryptedString;
Address1 = cipher.Identity.Address1?.EncryptedString;
Address2 = cipher.Identity.Address2?.EncryptedString;
Address3 = cipher.Identity.Address3?.EncryptedString;
City = cipher.Identity.City?.EncryptedString;
State = cipher.Identity.State?.EncryptedString;
PostalCode = cipher.Identity.PostalCode?.EncryptedString;
Country = cipher.Identity.Country?.EncryptedString;
Company = cipher.Identity.Company?.EncryptedString;
Email = cipher.Identity.Email?.EncryptedString;
Phone = cipher.Identity.Phone?.EncryptedString;
SSN = cipher.Identity.SSN?.EncryptedString;
Username = cipher.Identity.Username?.EncryptedString;
PassportNumber = cipher.Identity.PassportNumber?.EncryptedString;
LicenseNumber = cipher.Identity.LicenseNumber?.EncryptedString;
}
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string SSN { get; set; }
public string Username { get; set; }
public string PassportNumber { get; set; }
public string LicenseNumber { get; set; }
}
}

View File

@@ -1,10 +0,0 @@
namespace Bit.App.Models.Api
{
public class LoginDataModel : CipherDataModel
{
public string Uri { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Totp { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Bit.App.Models.Api
{
public class LoginType
{
public LoginType() { }
public LoginType(Cipher cipher)
{
Uris = cipher.Login.Uris?.Select(u => new LoginUriType(u));
Username = cipher.Login.Username?.EncryptedString;
Password = cipher.Login.Password?.EncryptedString;
PasswordRevisionDate = cipher.Login.PasswordRevisionDate;
Totp = cipher.Login.Totp?.EncryptedString;
}
public IEnumerable<LoginUriType> Uris { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public System.DateTime? PasswordRevisionDate { get; set; }
public string Totp { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using Bit.App.Enums;
namespace Bit.App.Models.Api
{
public class LoginUriType
{
public LoginUriType() { }
public LoginUriType(LoginUri u)
{
Uri = u.Uri?.EncryptedString;
Match = u.Match;
}
public string Uri { get; set; }
public UriMatchType? Match { get; set; }
}
}

View File

@@ -17,12 +17,12 @@ namespace Bit.App.Models.Api
if(cipher.Fields != null)
{
Fields = cipher.Fields.Select(f => new FieldDataModel
{
Name = f.Name?.EncryptedString,
Value = f.Value?.EncryptedString,
Type = f.Type
});
Fields = cipher.Fields.Select(f => new FieldType(f));
}
if(cipher.PasswordHistory != null)
{
PasswordHistory = cipher.PasswordHistory.Select(h => new PasswordHistoryRequest(h));
}
switch(Type)
@@ -50,101 +50,12 @@ namespace Bit.App.Models.Api
public bool Favorite { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public IEnumerable<FieldDataModel> Fields { get; set; }
public IEnumerable<FieldType> Fields { get; set; }
public IEnumerable<PasswordHistoryRequest> PasswordHistory { get; set; }
public LoginType Login { get; set; }
public CardType Card { get; set; }
public IdentityType Identity { get; set; }
public SecureNoteType SecureNote { get; set; }
public class LoginType
{
public LoginType(Cipher cipher)
{
Uri = cipher.Login.Uri?.EncryptedString;
Username = cipher.Login.Username?.EncryptedString;
Password = cipher.Login.Password?.EncryptedString;
Totp = cipher.Login.Totp?.EncryptedString;
}
public string Uri { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Totp { get; set; }
}
public class CardType
{
public CardType(Cipher cipher)
{
CardholderName = cipher.Card.CardholderName?.EncryptedString;
Brand = cipher.Card.Brand?.EncryptedString;
Number = cipher.Card.Number?.EncryptedString;
ExpMonth = cipher.Card.ExpMonth?.EncryptedString;
ExpYear = cipher.Card.ExpYear?.EncryptedString;
Code = cipher.Card.Code?.EncryptedString;
}
public string CardholderName { get; set; }
public string Brand { get; set; }
public string Number { get; set; }
public string ExpMonth { get; set; }
public string ExpYear { get; set; }
public string Code { get; set; }
}
public class IdentityType
{
public IdentityType(Cipher cipher)
{
Title = cipher.Identity.Title?.EncryptedString;
FirstName = cipher.Identity.FirstName?.EncryptedString;
MiddleName = cipher.Identity.MiddleName?.EncryptedString;
LastName = cipher.Identity.LastName?.EncryptedString;
Address1 = cipher.Identity.Address1?.EncryptedString;
Address2 = cipher.Identity.Address2?.EncryptedString;
Address3 = cipher.Identity.Address3?.EncryptedString;
City = cipher.Identity.City?.EncryptedString;
State = cipher.Identity.State?.EncryptedString;
PostalCode = cipher.Identity.PostalCode?.EncryptedString;
Country = cipher.Identity.Country?.EncryptedString;
Company = cipher.Identity.Company?.EncryptedString;
Email = cipher.Identity.Email?.EncryptedString;
Phone = cipher.Identity.Phone?.EncryptedString;
SSN = cipher.Identity.SSN?.EncryptedString;
Username = cipher.Identity.Username?.EncryptedString;
PassportNumber = cipher.Identity.PassportNumber?.EncryptedString;
LicenseNumber = cipher.Identity.LicenseNumber?.EncryptedString;
}
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string SSN { get; set; }
public string Username { get; set; }
public string PassportNumber { get; set; }
public string LicenseNumber { get; set; }
}
public class SecureNoteType
{
public SecureNoteType(Cipher cipher)
{
Type = cipher.SecureNote.Type;
}
public Enums.SecureNoteType Type { get; set; }
}
}
}

View File

@@ -0,0 +1,14 @@
namespace Bit.App.Models.Api
{
public class PasswordHistoryRequest
{
public PasswordHistoryRequest(PasswordHistory ph)
{
Password = ph.Password?.EncryptedString;
LastUsedDate = ph.LastUsedDate;
}
public string Password { get; set; }
public System.DateTime LastUsedDate { get; set; }
}
}

View File

@@ -1,6 +1,5 @@
using Bit.App.Enums;
using System;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
namespace Bit.App.Models.Api
@@ -15,8 +14,15 @@ namespace Bit.App.Models.Api
public bool Favorite { get; set; }
public bool Edit { get; set; }
public bool OrganizationUseTotp { get; set; }
public JObject Data { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
public LoginType Login { get; set; }
public CardType Card { get; set; }
public IdentityType Identity { get; set; }
public SecureNoteType SecureNote { get; set; }
public IEnumerable<FieldType> Fields { get; set; }
public IEnumerable<AttachmentResponse> Attachments { get; set; }
public IEnumerable<PasswordHistoryResponse> PasswordHistory { get; set; }
public IEnumerable<string> CollectionIds { get; set; }
public DateTime RevisionDate { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace Bit.App.Models.Api
{
public class PasswordHistoryResponse
{
public string Password { get; set; }
public System.DateTime LastUsedDate { get; set; }
}
}

View File

@@ -1,9 +0,0 @@
using Bit.App.Enums;
namespace Bit.App.Models.Api
{
public class SecureNoteDataModel : CipherDataModel
{
public SecureNoteType Type { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace Bit.App.Models.Api
{
public class SecureNoteType
{
public SecureNoteType() { }
public SecureNoteType(Cipher cipher)
{
Type = cipher.SecureNote.Type;
}
public Enums.SecureNoteType Type { get; set; }
}
}

View File

@@ -1,6 +1,6 @@
using Bit.App.Models.Api;
using Bit.App.Models.Data;
using Bit.App.Models.Data;
using Newtonsoft.Json;
using System;
namespace Bit.App.Models
{
@@ -10,7 +10,19 @@ namespace Bit.App.Models
public Card(CipherData data)
{
var deserializedData = JsonConvert.DeserializeObject<CardDataModel>(data.Data);
CardDataModel deserializedData;
if(data.Card != null)
{
deserializedData = JsonConvert.DeserializeObject<CardDataModel>(data.Card);
}
else if(data.Data != null)
{
deserializedData = JsonConvert.DeserializeObject<CardDataModel>(data.Data);
}
else
{
throw new ArgumentNullException(nameof(data.Card));
}
CardholderName = deserializedData.CardholderName != null ?
new CipherString(deserializedData.CardholderName) : null;

View File

@@ -1,5 +1,4 @@
using Bit.App.Enums;
using Bit.App.Models.Api;
using Bit.App.Models.Data;
using Newtonsoft.Json;
using System.Collections.Generic;
@@ -25,6 +24,7 @@ namespace Bit.App.Models
Edit = data.Edit;
OrganizationUseTotp = data.OrganizationUseTotp;
Attachments = attachments?.Select(a => new Attachment(a));
RevisionDate = data.RevisionDateTime;
switch(Type)
{
@@ -53,6 +53,17 @@ namespace Bit.App.Models
}
catch(JsonSerializationException) { }
}
if(!string.IsNullOrWhiteSpace(data.PasswordHistory))
{
try
{
var phModels = JsonConvert.DeserializeObject<IEnumerable<PasswordHistoryDataModel>>(
data.PasswordHistory);
PasswordHistory = phModels?.Select(f => new PasswordHistory(f));
}
catch(JsonSerializationException) { }
}
}
public string Id { get; set; }
@@ -63,14 +74,19 @@ namespace Bit.App.Models
public CipherString Name { get; set; }
public CipherString Notes { get; set; }
public IEnumerable<Field> Fields { get; set; }
public IEnumerable<PasswordHistory> PasswordHistory { get; set; }
public bool Favorite { get; set; }
public bool Edit { get; set; }
public bool OrganizationUseTotp { get; set; }
public IEnumerable<Attachment> Attachments { get; set; }
public System.DateTime RevisionDate { get; set; }
public Login Login { get; set; }
public Identity Identity { get; set; }
public Card Card { get; set; }
public SecureNote SecureNote { get; set; }
public System.DateTime? PasswordRevisionDisplayDate =>
Login?.Password == null ? null : Login.PasswordRevisionDate;
}
}

View File

@@ -1,10 +1,11 @@
using System;
using SQLite;
using Bit.App.Abstractions;
using Bit.App.Models.Api;
using Newtonsoft.Json;
using System.Linq;
using Bit.App.Enums;
using Bit.App.Models.Api;
using Newtonsoft.Json.Linq;
namespace Bit.App.Models.Data
{
@@ -26,46 +27,50 @@ namespace Bit.App.Models.Data
OrganizationUseTotp = cipher.OrganizationUseTotp;
RevisionDateTime = cipher.RevisionDate;
Type = cipher.Type;
Data = JsonConvert.SerializeObject(cipher.Data);
Data = null;
CipherDataModel cipherData = null;
switch(cipher.Type)
{
case CipherType.Login:
var loginData = cipher.Data.ToObject<LoginDataModel>();
cipherData = loginData;
Uri = loginData.Uri;
Username = loginData.Username;
Password = loginData.Password;
Totp = loginData.Totp;
var loginObj = JObject.FromObject(new LoginDataModel(cipher),
new JsonSerializer { NullValueHandling = NullValueHandling.Ignore });
loginObj[nameof(LoginDataModel.Uri)]?.Parent?.Remove();
Login = loginObj.ToString(Formatting.None);
break;
case CipherType.SecureNote:
var noteData = cipher.Data.ToObject<SecureNoteDataModel>();
cipherData = noteData;
SecureNoteType = noteData.Type;
var noteData = new SecureNoteDataModel(cipher);
SecureNote = JsonConvert.SerializeObject(noteData);
break;
case CipherType.Card:
var cardData = cipher.Data.ToObject<CardDataModel>();
cipherData = cardData;
var cardData = new CardDataModel(cipher);
Card = JsonConvert.SerializeObject(cardData);
break;
case CipherType.Identity:
var idData = cipher.Data.ToObject<IdentityDataModel>();
cipherData = idData;
var idData = new IdentityDataModel(cipher);
Identity = JsonConvert.SerializeObject(idData);
break;
default:
throw new ArgumentException(nameof(cipher.Type));
}
Name = cipherData.Name;
Notes = cipherData.Notes;
Name = cipher.Name;
Notes = cipher.Notes;
if(cipherData.Fields != null && cipherData.Fields.Any())
if(cipher.Fields != null && cipher.Fields.Any())
{
try
{
Fields = JsonConvert.SerializeObject(cipherData.Fields);
Fields = JsonConvert.SerializeObject(cipher.Fields.Select(f => new FieldDataModel(f)));
}
catch(JsonSerializationException) { }
}
if(cipher.PasswordHistory != null && cipher.PasswordHistory.Any())
{
try
{
PasswordHistory = JsonConvert.SerializeObject(
cipher.PasswordHistory.Select(h => new PasswordHistoryDataModel(h)));
}
catch(JsonSerializationException) { }
}
@@ -80,21 +85,18 @@ namespace Bit.App.Models.Data
public string Name { get; set; }
public string Notes { get; set; }
public string Fields { get; set; }
public string PasswordHistory { get; set; }
public string Login { get; set; }
public string Card { get; set; }
public string Identity { get; set; }
public string SecureNote { get; set; }
public bool Favorite { get; set; }
public bool Edit { get; set; }
public bool OrganizationUseTotp { get; set; }
public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow;
[Indexed]
public CipherType Type { get; set; } = CipherType.Login;
[Obsolete]
public string Data { get; set; }
// Login metadata
public string Uri { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Totp { get; set; }
// Secure Note metadata
public SecureNoteType? SecureNoteType { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
using Bit.App.Models.Api;
using System;
namespace Bit.App.Models.Data
{
public class CardDataModel : CipherDataModel
{
public CardDataModel() { }
public CardDataModel(CipherResponse response)
: base(response)
{
if(response?.Card == null)
{
throw new ArgumentNullException(nameof(response.Card));
}
CardholderName = response.Card.CardholderName;
Brand = response.Card.Brand;
Number = response.Card.Number;
ExpMonth = response.Card.ExpMonth;
ExpYear = response.Card.ExpYear;
Code = response.Card.Code;
}
public string CardholderName { get; set; }
public string Brand { get; set; }
public string Number { get; set; }
public string ExpMonth { get; set; }
public string ExpYear { get; set; }
public string Code { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using Bit.App.Models.Api;
using System.Collections.Generic;
using System.Linq;
namespace Bit.App.Models.Data
{
public abstract class CipherDataModel
{
public CipherDataModel() { }
public CipherDataModel(CipherResponse cipher)
{
Name = cipher.Name;
Notes = cipher.Notes;
Fields = cipher.Fields?.Select(f => new FieldDataModel(f));
PasswordHistory = cipher.PasswordHistory?.Select(h => new PasswordHistoryDataModel(h));
}
public string Name { get; set; }
public string Notes { get; set; }
public IEnumerable<FieldDataModel> Fields { get; set; }
public IEnumerable<PasswordHistoryDataModel> PasswordHistory { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More