Compare commits
179 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b732b2ffa7 | ||
|
|
617a7be4f3 | ||
|
|
5c5e368d6b | ||
|
|
ff9f49416a | ||
|
|
93cae0e9cc | ||
|
|
61e75ce747 | ||
|
|
50affe26c5 | ||
|
|
8566362607 | ||
|
|
36925770d0 | ||
|
|
d17ca1686e | ||
|
|
2ad709dae4 | ||
|
|
5a3d86a12a | ||
|
|
1a4ba36820 | ||
|
|
ddeae3b5ba | ||
|
|
10df9e7cd5 | ||
|
|
be11933c60 | ||
|
|
d2db68b781 | ||
|
|
da6e271584 | ||
|
|
5103c80e1e | ||
|
|
b5c80ea267 | ||
|
|
b5747fbb44 | ||
|
|
215ded8a77 | ||
|
|
e7ab6da068 | ||
|
|
ee881f67ee | ||
|
|
f33248aa4f | ||
|
|
c6a40bac03 | ||
|
|
aa38e79d08 | ||
|
|
9cac10e559 | ||
|
|
efbd418f56 | ||
|
|
4ff3464abd | ||
|
|
907ddbf903 | ||
|
|
7041991d5a | ||
|
|
b26067e5da | ||
|
|
e519b13533 | ||
|
|
30bc3867bf | ||
|
|
5326c3aecc | ||
|
|
c95251c903 | ||
|
|
e08a0a0938 | ||
|
|
fcb072c37d | ||
|
|
262c19b194 | ||
|
|
1031ddcd83 | ||
|
|
aaee0212f0 | ||
|
|
8fc95759ba | ||
|
|
b6a3a0a54f | ||
|
|
e3091be314 | ||
|
|
045d0678b3 | ||
|
|
e3eeaddb3e | ||
|
|
f2b202c714 | ||
|
|
e6f3ad60ef | ||
|
|
fb6e0c9eb8 | ||
|
|
fb6e488339 | ||
|
|
0bccc8f0d5 | ||
|
|
560d831e92 | ||
|
|
7c8f6a1cc7 | ||
|
|
deb1ead4ea | ||
|
|
005b2a4fb6 | ||
|
|
4c8204f29a | ||
|
|
83fd19784a | ||
|
|
1f21a2ecc7 | ||
|
|
c3f4d56d1e | ||
|
|
7e4f79bacb | ||
|
|
b8267d4329 | ||
|
|
205ca693b3 | ||
|
|
23159c2201 | ||
|
|
884521ced0 | ||
|
|
aeb01ba292 | ||
|
|
2b1a556e9e | ||
|
|
d5c3ae3d19 | ||
|
|
7654bb7088 | ||
|
|
64c301caeb | ||
|
|
e875b530b1 | ||
|
|
ee8c2b5272 | ||
|
|
9b8bdb0639 | ||
|
|
1a99bbb040 | ||
|
|
0982b45473 | ||
|
|
bcd210d504 | ||
|
|
c71608824b | ||
|
|
170876ac16 | ||
|
|
a6b172c445 | ||
|
|
e625450100 | ||
|
|
fca5447094 | ||
|
|
89f32beec5 | ||
|
|
65eb7662ad | ||
|
|
ea090dbe18 | ||
|
|
5750817620 | ||
|
|
93386d0e8b | ||
|
|
e9dd7b8f98 | ||
|
|
5010e7cb7a | ||
|
|
fb35f4fbca | ||
|
|
00c0a93a6b | ||
|
|
cd9a312e0b | ||
|
|
8cdb27fe43 | ||
|
|
d84d11d064 | ||
|
|
5d646a6112 | ||
|
|
dd334858ff | ||
|
|
dfd39ebc95 | ||
|
|
9dbb1f15a4 | ||
|
|
32fd04a7d9 | ||
|
|
3a33ff375d | ||
|
|
8877e71bd2 | ||
|
|
5b5385c01d | ||
|
|
9c365ecc48 | ||
|
|
99d1a6d043 | ||
|
|
854ef7e645 | ||
|
|
a8eeb12325 | ||
|
|
86a3f516b1 | ||
|
|
d6818939b3 | ||
|
|
c51449e607 | ||
|
|
333894ddeb | ||
|
|
052e227b65 | ||
|
|
4dd6df5bbe | ||
|
|
8847991bba | ||
|
|
0ffc6e4a1a | ||
|
|
9a399e06f3 | ||
|
|
6afccc2aea | ||
|
|
8cd3a21468 | ||
|
|
8b6d2d2b83 | ||
|
|
a39f4d5987 | ||
|
|
e236d045b0 | ||
|
|
592c7951df | ||
|
|
41efa96291 | ||
|
|
53f406a267 | ||
|
|
1390df48b6 | ||
|
|
01878ef00c | ||
|
|
6f119f25f4 | ||
|
|
3f31d78db1 | ||
|
|
014bf7777b | ||
|
|
7191969e9c | ||
|
|
0950510526 | ||
|
|
9eba3064a7 | ||
|
|
a4d785258e | ||
|
|
efef49f976 | ||
|
|
32a7b5bafb | ||
|
|
5fa080063c | ||
|
|
b3573f9482 | ||
|
|
916b7ee46b | ||
|
|
bfe8ad2034 | ||
|
|
bb9db7bf9d | ||
|
|
d7f7c8c568 | ||
|
|
10839588dd | ||
|
|
12cd2b67cd | ||
|
|
9a13036f4e | ||
|
|
2f025d51ff | ||
|
|
6cb6d3a358 | ||
|
|
0bb01d14bd | ||
|
|
2229c4e4d1 | ||
|
|
5c90c62378 | ||
|
|
b7ed0a29fe | ||
|
|
796c2ed58c | ||
|
|
39bd573d9d | ||
|
|
d4aaa547a7 | ||
|
|
f7e2382847 | ||
|
|
4bb16e7d93 | ||
|
|
e7e00e4ebf | ||
|
|
55d050fca7 | ||
|
|
98d4fef0ee | ||
|
|
5521892736 | ||
|
|
8f0fd0dfef | ||
|
|
514eab0b98 | ||
|
|
e35c84245d | ||
|
|
4a2391eb1b | ||
|
|
04eb497e10 | ||
|
|
a9a5da6dc6 | ||
|
|
3f1aab27d6 | ||
|
|
8f77df4ebb | ||
|
|
65a8b3fcd4 | ||
|
|
71dd4e512e | ||
|
|
ca03a5ecf4 | ||
|
|
694efb9508 | ||
|
|
c60a112039 | ||
|
|
c3570dd07a | ||
|
|
b680b190d4 | ||
|
|
310d51d859 | ||
|
|
cf9e820227 | ||
|
|
b91d2f4fb1 | ||
|
|
9456f5dc31 | ||
|
|
fa9e22730a | ||
|
|
7261fd7ed9 | ||
|
|
ad9e5fbf07 |
@@ -6,7 +6,7 @@ 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).
|
||||
|
||||
|
||||
5
ISSUE_TEMPLATE.md
Normal 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
|
||||
-->
|
||||
12
README.md
@@ -2,24 +2,28 @@
|
||||
[](https://crowdin.com/project/bitwarden-mobile)
|
||||
[](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, 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/Ty8wkSO.png" alt="" width="300" height="533" /> <img src="https://i.imgur.com/BYb4gVc.png" alt="" width="300" height="533" />
|
||||
<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" />
|
||||
|
||||
# Build/Run
|
||||
|
||||
**Requirements**
|
||||
|
||||
- [Visual Studio w/ Xamarin -or- Xamarin Studio](https://store.xamarin.com/)
|
||||
- [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
|
||||
|
||||
16
SECURITY.md
@@ -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!
|
||||
|
||||
15
appveyor.yml
@@ -1,21 +1,22 @@
|
||||
install:
|
||||
- appveyor DownloadFile https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
|
||||
#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"
|
||||
before_build:
|
||||
- nuget restore
|
||||
- IF DEFINED keystore_dec_secret nuget install secure-file -ExcludeVersion
|
||||
- IF DEFINED google_services_dec_secret secure-file\tools\secure-file -decrypt src\Android\google-services.json.enc -secret %google_services_dec_secret%
|
||||
after_build:
|
||||
- ps: IF($env:keystore_dec_secret) { .\src\Android\increment-version.ps1 $($env:APPVEYOR_BUILD_FOLDER) $($env:APPVEYOR_BUILD_NUMBER) }
|
||||
- IF DEFINED keystore_dec_secret secure-file\tools\secure-file -decrypt src\Android\8bit.keystore.enc -secret %keystore_dec_secret%
|
||||
- IF DEFINED keystore_password msbuild "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=%keystore_password%" "/p:AndroidSigningKeyStore=8bit.keystore" "/p:AndroidSigningStorePass=%keystore_password%" "src\Android\Android.csproj"
|
||||
- ps: IF($env:keystore_dec_secret) { copy-item src\Android\bin\Release\com.x8bit.bitwarden-Signed.apk .\com.x8bit.bitwarden-$($env:APPVEYOR_BUILD_NUMBER).apk }
|
||||
- ps: IF($env:keystore_dec_secret) { .\src\Android\ci-build-apks.ps1 }
|
||||
on_success:
|
||||
- IF DEFINED play_dec_secret secure-file\tools\secure-file -decrypt store\google\Publisher\play_creds.json.enc -secret %play_dec_secret%
|
||||
- IF DEFINED play_dec_secret dotnet store\google\Publisher\bin\Debug\netcoreapp2.0\Publisher.dll %APPVEYOR_BUILD_FOLDER%\store\google\Publisher\play_creds.json %APPVEYOR_BUILD_FOLDER%\src\Android\bin\Release\com.x8bit.bitwarden-Signed.apk alpha
|
||||
- IF DEFINED play_dec_secret dotnet store\google\Publisher\bin\Release\netcoreapp2.0\Publisher.dll %APPVEYOR_BUILD_FOLDER%\store\google\Publisher\play_creds.json %APPVEYOR_BUILD_FOLDER%\com.x8bit.bitwarden-%APPVEYOR_BUILD_NUMBER%.apk alpha
|
||||
artifacts:
|
||||
- path: com.x8bit.bitwarden-%APPVEYOR_BUILD_NUMBER%.apk
|
||||
- path: com.x8bit.bitwarden-fdroid-%APPVEYOR_BUILD_NUMBER%.apk
|
||||
branches:
|
||||
except:
|
||||
- l10n_master
|
||||
skip_tags: true
|
||||
configuration: Release
|
||||
image: Visual Studio 2017
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2003
|
||||
VisualStudioVersion = 15.0.27130.2010
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android", "src\Android\Android.csproj", "{04B18ED2-B76D-4947-8474-191F8FD2B5E0}"
|
||||
EndProject
|
||||
@@ -21,13 +21,9 @@ 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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Publisher", "store\google\Publisher\Publisher.csproj", "{D5D91152-CB01-4F24-A503-304D3A94408B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Publisher", "store\google\Publisher\Publisher.csproj", "{D5D91152-CB01-4F24-A503-304D3A94408B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F0E2E596-C3DB-474A-9C88-7824662894FA}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
@@ -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
|
||||
@@ -62,6 +54,12 @@ Global
|
||||
Debug|iPhoneSimulator = Debug|iPhoneSimulator
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
FDroid|Any CPU = FDroid|Any CPU
|
||||
FDroid|ARM = FDroid|ARM
|
||||
FDroid|iPhone = FDroid|iPhone
|
||||
FDroid|iPhoneSimulator = FDroid|iPhoneSimulator
|
||||
FDroid|x64 = FDroid|x64
|
||||
FDroid|x86 = FDroid|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|iPhone = Release|iPhone
|
||||
@@ -110,6 +108,24 @@ Global
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|Any CPU.Deploy.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|ARM.ActiveCfg = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|ARM.Build.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|ARM.Deploy.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|iPhone.Build.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|iPhone.Deploy.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|iPhoneSimulator.Deploy.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|x64.ActiveCfg = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|x64.Build.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|x64.Deploy.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|x86.ActiveCfg = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|x86.Build.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.FDroid|x86.Deploy.0 = FDroid|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
@@ -149,6 +165,18 @@ Global
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x64.ActiveCfg = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x86.ActiveCfg = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x86.Build.0 = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|Any CPU.ActiveCfg = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|Any CPU.Build.0 = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|ARM.ActiveCfg = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|ARM.Build.0 = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|iPhone.ActiveCfg = Release|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|iPhone.Build.0 = Release|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|x64.ActiveCfg = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|x64.Build.0 = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|x86.ActiveCfg = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.FDroid|x86.Build.0 = Release|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Release|Any CPU.ActiveCfg = Release|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Release|ARM.ActiveCfg = Release|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
@@ -186,6 +214,18 @@ Global
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|ARM.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|ARM.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|iPhone.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|x64.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|x64.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|x86.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.FDroid|x86.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
@@ -221,6 +261,18 @@ Global
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x64.ActiveCfg = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x86.ActiveCfg = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x86.Build.0 = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|Any CPU.ActiveCfg = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|Any CPU.Build.0 = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|ARM.ActiveCfg = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|ARM.Build.0 = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|iPhone.ActiveCfg = Release|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|iPhone.Build.0 = Release|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|x64.ActiveCfg = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|x64.Build.0 = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|x86.ActiveCfg = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.FDroid|x86.Build.0 = Release|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Release|Any CPU.ActiveCfg = Release|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Release|ARM.ActiveCfg = Release|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
@@ -262,6 +314,18 @@ Global
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|ARM.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|ARM.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|iPhone.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|x64.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|x64.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|x86.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.FDroid|x86.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|iPhone.ActiveCfg = Release|Any CPU
|
||||
@@ -272,66 +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}.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
|
||||
@@ -368,6 +372,18 @@ Global
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|ARM.ActiveCfg = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|ARM.Build.0 = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|iPhone.Build.0 = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|x64.ActiveCfg = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|x64.Build.0 = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|x86.ActiveCfg = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.FDroid|x86.Build.0 = FDroid|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8A279EE4-4537-4656-9C93-44945E594556}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
@@ -416,6 +432,18 @@ Global
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|ARM.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|ARM.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|iPhone.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|iPhone.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|x64.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|x64.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|x86.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.FDroid|x86.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5D91152-CB01-4F24-A503-304D3A94408B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
@@ -439,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<AotAssemblies>False</AotAssemblies>
|
||||
<EnableLLVM>False</EnableLLVM>
|
||||
<EnableProguard>False</EnableProguard>
|
||||
<AndroidTlsProvider>btls</AndroidTlsProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -69,6 +70,26 @@
|
||||
<AndroidLinkSkip>PushNotification.Plugin;PushNotification.Plugin.Abstractions;Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;SQLite-net;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
||||
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||
<AndroidTlsProvider>btls</AndroidTlsProvider>
|
||||
<AndroidApkSigningAlgorithm>SHA1withRSA</AndroidApkSigningAlgorithm>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'FDroid|AnyCPU'">
|
||||
<OutputPath>bin\FDroid\</OutputPath>
|
||||
<DefineConstants>TRACE;FDROID</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
<AndroidLinkMode>Full</AndroidLinkMode>
|
||||
<AndroidLinkSkip>BitwardenAndroid;BitwardenApp;SQLite-net;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidTlsProvider>btls</AndroidTlsProvider>
|
||||
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
|
||||
<AndroidApkSigningAlgorithm>SHA1withRSA</AndroidApkSigningAlgorithm>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
@@ -125,8 +146,6 @@
|
||||
<Compile Include="MainActivity.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\LogService.cs" />
|
||||
<Compile Include="Services\MemoryService.cs" />
|
||||
<Compile Include="Services\ReflectionService.cs" />
|
||||
<Compile Include="Services\SqlService.cs" />
|
||||
<Compile Include="SplashActivity.cs" />
|
||||
<Compile Include="PackageReplacedReceiver.cs" />
|
||||
@@ -136,8 +155,8 @@
|
||||
<ItemGroup>
|
||||
<None Include="8bit.keystore.enc" />
|
||||
<GoogleServicesJson Include="google-services.json" />
|
||||
<None Include="ci-build-apks.ps1" />
|
||||
<None Include="google-services.json.enc" />
|
||||
<None Include="increment-version.ps1" />
|
||||
<None Include="Resources\AboutResources.txt" />
|
||||
<None Include="Assets\AboutAssets.txt" />
|
||||
<AndroidResource Include="Resources\drawable\slider_thumb.xml">
|
||||
@@ -453,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>
|
||||
@@ -853,15 +857,18 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SimpleInjector">
|
||||
<Version>4.0.12</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Firebase.Messaging">
|
||||
<Version>42.1021.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.GooglePlayServices.Analytics">
|
||||
<Version>42.1021.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SimpleInjector">
|
||||
<Version>4.0.12</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat">
|
||||
<Version>25.4.0.2</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" />
|
||||
@@ -884,5 +891,104 @@
|
||||
<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>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -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")]
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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" };
|
||||
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,31 @@ 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);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,12 @@ 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"
|
||||
"com.amazon.cloud9","org.mozilla.klar", "com.duckduckgo.mobile.android"
|
||||
};
|
||||
|
||||
public static HashSet<string> ExcludedPackageIds = new HashSet<string>
|
||||
{
|
||||
"android"
|
||||
};
|
||||
|
||||
private readonly AssistStructure _structure;
|
||||
@@ -87,32 +92,24 @@ namespace Bit.Android.Autofill
|
||||
var node = _structure.GetWindowNodeAt(i);
|
||||
ParseNode(node.RootViewNode);
|
||||
}
|
||||
|
||||
if(!TrustedBrowsers.Contains(PackageName))
|
||||
{
|
||||
WebDomain = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseNode(ViewNode node)
|
||||
{
|
||||
SetPackageAndDomain(node);
|
||||
var hints = node.GetAutofillHints();
|
||||
var isEditText = node.ClassName == "android.widget.EditText" || node?.HtmlInfo?.Tag == "input";
|
||||
if(isEditText || (hints?.Length ?? 0) > 0)
|
||||
{
|
||||
if(PackageName == null)
|
||||
{
|
||||
PackageName = node.IdPackage;
|
||||
}
|
||||
if(WebDomain == null && TrustedBrowsers.Contains(node.IdPackage))
|
||||
{
|
||||
WebDomain = node.WebDomain;
|
||||
}
|
||||
|
||||
FieldCollection.Add(new Field(node));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(WebDomain == null && TrustedBrowsers.Contains(node.IdPackage))
|
||||
{
|
||||
WebDomain = node.WebDomain;
|
||||
}
|
||||
|
||||
FieldCollection.IgnoreAutofillIds.Add(node.AutofillId);
|
||||
}
|
||||
|
||||
@@ -121,5 +118,18 @@ namespace Bit.Android.Autofill
|
||||
ParseNode(node.GetChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPackageAndDomain(ViewNode node)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(PackageName) && !string.IsNullOrWhiteSpace(node.IdPackage) &&
|
||||
!ExcludedPackageIds.Contains(node.IdPackage))
|
||||
{
|
||||
PackageName = node.IdPackage;
|
||||
}
|
||||
if(string.IsNullOrWhiteSpace(WebDomain) && !string.IsNullOrWhiteSpace(node.WebDomain))
|
||||
{
|
||||
WebDomain = node.WebDomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,7 @@ using Android.Views;
|
||||
|
||||
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 string _lastQueriedUri;
|
||||
|
||||
@@ -12,17 +12,18 @@ 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
|
||||
{
|
||||
private NotificationChannel _notificationChannel;
|
||||
|
||||
private const string BitwardenTag = "bw_access";
|
||||
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>
|
||||
{
|
||||
@@ -42,10 +43,11 @@ namespace Bit.Android
|
||||
new Browser("com.sec.android.app.sbrowser", "location_bar_edit_text"),
|
||||
new Browser("com.sec.android.app.sbrowser.beta", "location_bar_edit_text"),
|
||||
new Browser("com.yandex.browser", "bro_omnibar_address_title_text",
|
||||
(s) => s.Split(' ').FirstOrDefault()),
|
||||
(s) => s.Split(new char[]{' ', '<27>'}).FirstOrDefault()), // 0 = Regular Space, 1 = No-break space (00A0)
|
||||
new Browser("org.mozilla.firefox", "url_bar_title"),
|
||||
new Browser("org.mozilla.firefox_beta", "url_bar_title"),
|
||||
new Browser("org.mozilla.focus", "display_url"),
|
||||
new Browser("org.mozilla.klar", "display_url"),
|
||||
new Browser("com.ghostery.android.ghostery", "search_field"),
|
||||
new Browser("org.adblockplus.browser", "url_bar_title"),
|
||||
new Browser("com.htc.sense.browser", "title"),
|
||||
@@ -59,12 +61,37 @@ namespace Bit.Android
|
||||
new Browser("com.ksmobile.cb", "address_bar_edit_text"),
|
||||
new Browser("acr.browser.lightning", "search"),
|
||||
new Browser("acr.browser.barebones", "search"),
|
||||
new Browser("com.microsoft.emmx", "url_bar")
|
||||
new Browser("com.microsoft.emmx", "url_bar"),
|
||||
new Browser("com.duckduckgo.mobile.android", "omnibarTextInput"),
|
||||
new Browser("mark.via.gp", "aw")
|
||||
}.ToDictionary(n => n.PackageName);
|
||||
|
||||
// Known packages to skip
|
||||
private static HashSet<string> FilteredPackageNames => new HashSet<string>
|
||||
{
|
||||
SystemUiPackage,
|
||||
"com.google.android.googlequicksearchbox",
|
||||
"com.google.android.apps.nexuslauncher",
|
||||
"com.google.android.launcher",
|
||||
"com.computer.desktop.ui.launcher",
|
||||
"com.launcher.notelauncher",
|
||||
"com.anddoes.launcher",
|
||||
"com.actionlauncher.playstore",
|
||||
"ch.deletescape.lawnchair.plah",
|
||||
"com.microsoft.launcher",
|
||||
"com.teslacoilsw.launcher",
|
||||
"com.teslacoilsw.launcher.prime",
|
||||
"is.shortcut",
|
||||
"me.craftsapp.nlauncher",
|
||||
"com.ss.squarehome2"
|
||||
};
|
||||
|
||||
private readonly IAppSettingsService _appSettings;
|
||||
private long _lastNotificationTime = 0;
|
||||
private string _lastNotificationUri = null;
|
||||
private HashSet<string> _launcherPackageNames = null;
|
||||
private DateTime? _lastLauncherSetBuilt = null;
|
||||
private TimeSpan _rebuildLauncherSpan = TimeSpan.FromHours(1);
|
||||
|
||||
public AutofillService()
|
||||
{
|
||||
@@ -85,17 +112,20 @@ namespace Bit.Android
|
||||
|
||||
try
|
||||
{
|
||||
var root = RootInActiveWindow;
|
||||
if(e == null || root == null || string.IsNullOrWhiteSpace(e.PackageName) ||
|
||||
e.PackageName == SystemUiPackage || e.PackageName.Contains("launcher") ||
|
||||
root.PackageName != e.PackageName)
|
||||
if(SkipPackage(e?.PackageName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//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 root = RootInActiveWindow;
|
||||
if(root == null || root.PackageName != e.PackageName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -103,7 +133,7 @@ namespace Bit.Android
|
||||
switch(e.EventType)
|
||||
{
|
||||
case EventTypes.ViewFocused:
|
||||
if(!e.Source.Password || !_appSettings.AutofillPasswordField)
|
||||
if(e.Source == null || !e.Source.Password || !_appSettings.AutofillPasswordField)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -410,16 +440,17 @@ namespace Bit.Android
|
||||
}
|
||||
|
||||
private NodeList GetWindowNodes(AccessibilityNodeInfo n, AccessibilityEvent e,
|
||||
Func<AccessibilityNodeInfo, bool> condition, bool disposeIfUnused, NodeList nodes = null)
|
||||
Func<AccessibilityNodeInfo, bool> condition, bool disposeIfUnused, NodeList nodes = null,
|
||||
int recursionDepth = 0)
|
||||
{
|
||||
if(nodes == null)
|
||||
{
|
||||
nodes = new NodeList();
|
||||
}
|
||||
|
||||
if(n != null)
|
||||
var dispose = disposeIfUnused;
|
||||
if(n != null && recursionDepth < 50)
|
||||
{
|
||||
var dispose = disposeIfUnused;
|
||||
if(n.WindowId == e.WindowId && !(n.ViewIdResourceName?.StartsWith(SystemUiPackage) ?? false) && condition(n))
|
||||
{
|
||||
dispose = false;
|
||||
@@ -428,18 +459,54 @@ namespace Bit.Android
|
||||
|
||||
for(var i = 0; i < n.ChildCount; i++)
|
||||
{
|
||||
GetWindowNodes(n.GetChild(i), e, condition, true, nodes);
|
||||
}
|
||||
|
||||
if(dispose)
|
||||
{
|
||||
n.Dispose();
|
||||
var childNode = n.GetChild(i);
|
||||
if(i > 100)
|
||||
{
|
||||
global::Android.Util.Log.Info(BitwardenTag, "Too many child iterations.");
|
||||
break;
|
||||
}
|
||||
else if(childNode.GetHashCode() == n.GetHashCode())
|
||||
{
|
||||
global::Android.Util.Log.Info(BitwardenTag,
|
||||
"Child node is the same as parent for some reason.");
|
||||
}
|
||||
else
|
||||
{
|
||||
GetWindowNodes(childNode, e, condition, true, nodes, recursionDepth++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(dispose)
|
||||
{
|
||||
n?.Dispose();
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private bool SkipPackage(string eventPackageName)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(eventPackageName) || FilteredPackageNames.Contains(eventPackageName)
|
||||
|| eventPackageName.Contains("launcher"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(_launcherPackageNames == null || _lastLauncherSetBuilt == null ||
|
||||
(DateTime.Now - _lastLauncherSetBuilt.Value) > _rebuildLauncherSpan)
|
||||
{
|
||||
// refresh launcher list every now and then
|
||||
_lastLauncherSetBuilt = DateTime.Now;
|
||||
var intent = new Intent(Intent.ActionMain);
|
||||
intent.AddCategory(Intent.CategoryHome);
|
||||
var resolveInfo = PackageManager.QueryIntentActivities(intent, 0);
|
||||
_launcherPackageNames = resolveInfo.Select(ri => ri.ActivityInfo.PackageName).ToHashSet();
|
||||
}
|
||||
|
||||
return _launcherPackageNames.Contains(eventPackageName);
|
||||
}
|
||||
|
||||
public class Browser
|
||||
{
|
||||
public Browser(string packageName, string uriViewId)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !FDROID
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
@@ -21,3 +22,4 @@ namespace Bit.Android
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !FDROID
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
@@ -40,3 +41,4 @@ namespace Bit.Android
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#if !FDROID
|
||||
using HockeyApp.Android;
|
||||
using Bit.App.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
@@ -51,4 +52,5 @@ namespace Bit.Android
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,10 +21,7 @@ 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";
|
||||
@@ -61,8 +58,10 @@ namespace Bit.Android
|
||||
var appIdService = Resolver.Resolve<IAppIdService>();
|
||||
var authService = Resolver.Resolve<IAuthService>();
|
||||
|
||||
#if !FDROID
|
||||
HockeyApp.Android.CrashManager.Register(this, HockeyAppId,
|
||||
new HockeyAppCrashManagerListener(appIdService, authService));
|
||||
#endif
|
||||
|
||||
Forms.Init(this, bundle);
|
||||
|
||||
@@ -137,7 +136,14 @@ namespace Bit.Android
|
||||
|
||||
if(Utilities.NfcEnabled())
|
||||
{
|
||||
MessagingCenter.Send(Xamarin.Forms.Application.Current, "ResumeYubiKey");
|
||||
try
|
||||
{
|
||||
MessagingCenter.Send(Xamarin.Forms.Application.Current, "ResumeYubiKey");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ using Plugin.Fingerprint;
|
||||
using Plugin.Settings;
|
||||
using XLabs.Ioc;
|
||||
using System.Threading.Tasks;
|
||||
using Plugin.Settings.Abstractions;
|
||||
using FFImageLoading.Forms.Droid;
|
||||
using XLabs.Ioc.SimpleInjectorContainer;
|
||||
using SimpleInjector;
|
||||
@@ -102,7 +101,7 @@ namespace Bit.Android
|
||||
public static void SetIoc(Application application)
|
||||
{
|
||||
Refractored.FabControl.Droid.FloatingActionButtonViewRenderer.Init();
|
||||
CachedImageRenderer.Init();
|
||||
CachedImageRenderer.Init(true);
|
||||
ZXing.Net.Mobile.Forms.Android.Platform.Init();
|
||||
CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity);
|
||||
|
||||
@@ -127,17 +126,19 @@ namespace Bit.Android
|
||||
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
||||
container.RegisterSingleton<IAppIdService, AppIdService>();
|
||||
container.RegisterSingleton<IPasswordGenerationService, PasswordGenerationService>();
|
||||
container.RegisterSingleton<IReflectionService, ReflectionService>();
|
||||
container.RegisterSingleton<ILockService, LockService>();
|
||||
container.RegisterSingleton<IAppInfoService, AppInfoService>();
|
||||
#if FDROID
|
||||
container.RegisterSingleton<IGoogleAnalyticsService, NoopGoogleAnalyticsService>();
|
||||
#else
|
||||
container.RegisterSingleton<IGoogleAnalyticsService, GoogleAnalyticsService>();
|
||||
#endif
|
||||
container.RegisterSingleton<IDeviceInfoService, DeviceInfoService>();
|
||||
container.RegisterSingleton<ILocalizeService, LocalizeService>();
|
||||
container.RegisterSingleton<ILogService, LogService>();
|
||||
container.RegisterSingleton<IHttpService, HttpService>();
|
||||
container.RegisterSingleton<ITokenService, TokenService>();
|
||||
container.RegisterSingleton<ISettingsService, SettingsService>();
|
||||
container.RegisterSingleton<IMemoryService, MemoryService>();
|
||||
container.RegisterSingleton<IAppSettingsService, AppSettingsService>();
|
||||
|
||||
// Repositories
|
||||
@@ -162,8 +163,13 @@ namespace Bit.Android
|
||||
container.RegisterSingleton(CrossFingerprint.Current);
|
||||
|
||||
// Push
|
||||
#if FDROID
|
||||
container.RegisterSingleton<IPushNotificationListener, NoopPushNotificationListener>();
|
||||
container.RegisterSingleton<IPushNotificationService, NoopPushNotificationService>();
|
||||
#else
|
||||
container.RegisterSingleton<IPushNotificationListener, PushNotificationListener>();
|
||||
container.RegisterSingleton<IPushNotificationService, AndroidPushNotificationService>();
|
||||
#endif
|
||||
|
||||
container.Verify();
|
||||
Resolver.SetResolver(new SimpleInjectorResolver(container));
|
||||
|
||||
@@ -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.0" 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.16.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"
|
||||
@@ -34,6 +35,6 @@
|
||||
</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" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -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("")]
|
||||
|
||||
5369
src/Android/Resources/Resource.Designer.cs
generated
BIN
src/Android/Resources/drawable-hdpi/cog_alt.png
Normal file
|
After Width: | Height: | Size: 738 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
src/Android/Resources/drawable-hdpi/refresh_alt.png
Normal file
|
After Width: | Height: | Size: 804 B |
BIN
src/Android/Resources/drawable-xhdpi/cog_alt.png
Normal file
|
After Width: | Height: | Size: 1005 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
src/Android/Resources/drawable-xhdpi/refresh_alt.png
Normal file
|
After Width: | Height: | Size: 1017 B |
BIN
src/Android/Resources/drawable-xxhdpi/cog_alt.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
src/Android/Resources/drawable-xxhdpi/refresh_alt.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Android/Resources/drawable-xxxhdpi/cog_alt.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.6 KiB |
BIN
src/Android/Resources/drawable-xxxhdpi/refresh_alt.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/Android/Resources/drawable/cog_alt.png
Normal file
|
After Width: | Height: | Size: 590 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 941 B |
BIN
src/Android/Resources/drawable/refresh_alt.png
Normal file
|
After Width: | Height: | Size: 583 B |
@@ -7,9 +7,5 @@
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:tabIndicatorColor="@android:color/white"
|
||||
app:tabMaxWidth="0dp"
|
||||
app:tabGravity="fill"
|
||||
app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget"
|
||||
app:tabTextColor="@color/tabtext"
|
||||
app:tabSelectedTextColor="@android:color/white"
|
||||
app:tabMode="fixed" />
|
||||
@@ -1,11 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
app:layout_scrollFlags="scroll|enterAlways" />
|
||||
android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
|
||||
5
src/Android/Resources/mipmap-anydpi-v26/ic_launcher.xml
Normal 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>
|
||||
@@ -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>
|
||||
BIN
src/Android/Resources/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Android/Resources/mipmap-hdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 941 B |
BIN
src/Android/Resources/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/Android/Resources/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 896 B |
BIN
src/Android/Resources/mipmap-mdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 608 B |
BIN
src/Android/Resources/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/Android/Resources/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src/Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/Android/Resources/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
src/Android/Resources/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/Android/Resources/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/Android/Resources/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/Android/Resources/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
4
src/Android/Resources/values/ic_launcher_background.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#3C8DBC</color>
|
||||
</resources>
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#if !FDROID
|
||||
using System;
|
||||
using Bit.App;
|
||||
using Bit.App.Abstractions;
|
||||
using Plugin.Settings.Abstractions;
|
||||
@@ -40,3 +41,4 @@ namespace Bit.Android.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -302,9 +303,9 @@ namespace Bit.Android.Services
|
||||
|
||||
public void DismissKeyboard()
|
||||
{
|
||||
var activity = (MainActivity)CurrentContext;
|
||||
try
|
||||
{
|
||||
var activity = (MainActivity)CurrentContext;
|
||||
var imm = (InputMethodManager)activity.GetSystemService(Context.InputMethodService);
|
||||
imm.HideSoftInputFromWindow(activity.CurrentFocus.WindowToken, 0);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
#if !FDROID
|
||||
using System;
|
||||
using Bit.App;
|
||||
using Bit.App.Abstractions;
|
||||
using Plugin.Settings.Abstractions;
|
||||
@@ -80,3 +81,4 @@ namespace Bit.Android.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using Android.Content;
|
||||
using Bit.App.Abstractions;
|
||||
using Plugin.CurrentActivity;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.Android.Services
|
||||
{
|
||||
public class MemoryService : IMemoryService
|
||||
{
|
||||
public MemoryInfo GetInfo()
|
||||
{
|
||||
return MemoryHelper.GetMemoryInfo(CrossCurrentActivity.Current.Activity);
|
||||
}
|
||||
|
||||
public void Check()
|
||||
{
|
||||
MemoryHelper.MemoryCheck(CrossCurrentActivity.Current.Activity);
|
||||
}
|
||||
|
||||
public static class MemoryHelper
|
||||
{
|
||||
public static void MemoryCheck(Context context)
|
||||
{
|
||||
Console.WriteLine("MemoryHelper.MemoryCheck.{0} - {1}", "Start", context.ToString());
|
||||
var maxMemory = Java.Lang.Runtime.GetRuntime().MaxMemory();
|
||||
var freeMemory = Java.Lang.Runtime.GetRuntime().FreeMemory();
|
||||
var percentUsed = (maxMemory - freeMemory) / (double)maxMemory;
|
||||
Console.WriteLine("Free memory: {0:N}", freeMemory);
|
||||
Console.WriteLine("Max memory: {0:N}", maxMemory);
|
||||
Console.WriteLine("% used: {0:P}", percentUsed);
|
||||
Console.WriteLine("MemoryHelper.MemoryCheck.{0} {3:P} {1} out of {2}", "End", freeMemory, maxMemory, percentUsed);
|
||||
}
|
||||
|
||||
public static MemoryInfo GetMemoryInfo(Context context)
|
||||
{
|
||||
var retVal = new MemoryInfo();
|
||||
retVal.MaxMemory = Java.Lang.Runtime.GetRuntime().MaxMemory();
|
||||
retVal.FreeMemory = Java.Lang.Runtime.GetRuntime().FreeMemory();
|
||||
retVal.TotalMemory = Java.Lang.Runtime.GetRuntime().TotalMemory();
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Controls;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.Android.Services
|
||||
{
|
||||
public class ReflectionService : IReflectionService
|
||||
{
|
||||
public Func<double, double, SizeRequest> GetVisualElementOnSizeRequest(ExtendedTableView tableView)
|
||||
{
|
||||
var handle = typeof(VisualElement).GetMethod(
|
||||
"OnSizeRequest",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic,
|
||||
null,
|
||||
new Type[] { typeof(double), typeof(double) },
|
||||
null)?.MethodHandle;
|
||||
|
||||
if(!handle.HasValue)
|
||||
{
|
||||
throw new ArgumentNullException("handle could not be found.");
|
||||
}
|
||||
|
||||
var pointer = handle.Value.GetFunctionPointer();
|
||||
if(pointer == null)
|
||||
{
|
||||
throw new ArgumentNullException("pointer could not be found.");
|
||||
}
|
||||
|
||||
return (Func<double, double, SizeRequest>)Activator.CreateInstance(typeof(Func<double, double, SizeRequest>), tableView, pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,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 +50,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 +68,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;
|
||||
|
||||
90
src/Android/ci-build-apks.ps1
Normal file
@@ -0,0 +1,90 @@
|
||||
$rootPath = $env:APPVEYOR_BUILD_FOLDER;
|
||||
|
||||
$androidPath = $($rootPath + "\src\Android\Android.csproj");
|
||||
$appPath = $($rootPath + "\src\App\App.csproj");
|
||||
|
||||
echo "##### Increment Version"
|
||||
|
||||
$androidManifest = $($rootPath + "\src\Android\Properties\AndroidManifest.xml");
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($androidManifest);
|
||||
|
||||
$node=$xml.SelectNodes("/manifest");
|
||||
$node.SetAttribute("android:versionCode", $env:APPVEYOR_BUILD_NUMBER);
|
||||
|
||||
$xml.Save($androidManifest);
|
||||
|
||||
echo "##### Decrypt Keystore"
|
||||
|
||||
$encKeystorePath = $($rootPath + "\src\Android\8bit.keystore.enc");
|
||||
$secureFilePath = $($rootPath + "\secure-file\tools\secure-file.exe");
|
||||
|
||||
Invoke-Expression "& `"$secureFilePath`" -decrypt $($encKeystorePath) -secret $($env:keystore_dec_secret)"
|
||||
|
||||
echo "##### Sign Release Configuration"
|
||||
|
||||
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:keystore_password)" "/p:AndroidSigningKeyStore=8bit.keystore" "/p:AndroidSigningStorePass=$($env:keystore_password)" "/v:quiet"
|
||||
|
||||
echo "##### Copy Release apk to project root"
|
||||
|
||||
$signedApkPath = $($rootPath + "\src\Android\bin\Release\com.x8bit.bitwarden-Signed.apk");
|
||||
$signedApkDestPath = $($rootPath + "\com.x8bit.bitwarden-" + $env:APPVEYOR_BUILD_NUMBER + ".apk");
|
||||
|
||||
Copy-Item $signedApkPath $signedApkDestPath
|
||||
|
||||
echo "##### Clean Android and App"
|
||||
|
||||
msbuild "$($androidPath)" "/t:Clean" "/p:Configuration=FDroid"
|
||||
msbuild "$($appPath)" "/t:Clean" "/p:Configuration=FDroid"
|
||||
|
||||
echo "##### Backup project files"
|
||||
|
||||
Copy-Item $androidPath $($androidPath + ".original");
|
||||
Copy-Item $appPath $($appPath + ".original");
|
||||
|
||||
echo "##### Uninstall from Android.csproj"
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($androidPath);
|
||||
|
||||
$ns=New-Object System.Xml.XmlNamespaceManager($xml.NameTable);
|
||||
$ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI);
|
||||
|
||||
$firebaseNode=$xml.SelectSingleNode("/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Firebase.Messaging']", $ns);
|
||||
$firebaseNode.ParentNode.RemoveChild($firebaseNode);
|
||||
|
||||
$playServiceNode=$xml.SelectSingleNode("/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.GooglePlayServices.Analytics']", $ns);
|
||||
$playServiceNode.ParentNode.RemoveChild($playServiceNode);
|
||||
|
||||
$xml.Save($androidPath);
|
||||
|
||||
echo "##### Uninstall from App.csproj"
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($appPath);
|
||||
|
||||
$hockeyNode=$xml.SelectSingleNode("/Project/ItemGroup/PackageReference[@Include='HockeySDK.Xamarin']");
|
||||
$hockeyNode.ParentNode.RemoveChild($hockeyNode);
|
||||
|
||||
$xml.Save($appPath);
|
||||
|
||||
echo "##### Restore NuGet"
|
||||
|
||||
$nugetPath = $($rootPath + "\nuget.exe");
|
||||
|
||||
Invoke-Expression "& `"$nugetPath`" restore"
|
||||
|
||||
echo "##### Build and Sign FDroid Configuration"
|
||||
|
||||
msbuild "$($androidPath)" "/logger:C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" "/p:Configuration=FDroid"
|
||||
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=FDroid" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:keystore_password)" "/p:AndroidSigningKeyStore=8bit.keystore" "/p:AndroidSigningStorePass=$($env:keystore_password)" "/v:quiet"
|
||||
|
||||
echo "##### Copy FDroid apk to project root"
|
||||
|
||||
$signedApkPath = $($rootPath + "\src\Android\bin\FDroid\com.x8bit.bitwarden-Signed.apk");
|
||||
$signedApkDestPath = $($rootPath + "\com.x8bit.bitwarden-fdroid-" + $env:APPVEYOR_BUILD_NUMBER + ".apk");
|
||||
|
||||
Copy-Item $signedApkPath $signedApkDestPath
|
||||
|
||||
echo "##### Done"
|
||||
@@ -1,8 +0,0 @@
|
||||
$rootPath = $args[0];
|
||||
$newVersionCode = $args[1];
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($rootPath + "\src\Android\Properties\AndroidManifest.xml");
|
||||
$node=$xml.SelectNodes("/manifest");
|
||||
$node.SetAttribute("android:versionCode", $newVersionCode);
|
||||
$xml.Save($rootPath + "\src\Android\Properties\AndroidManifest.xml");
|
||||
@@ -5,6 +5,7 @@ namespace Bit.App.Abstractions
|
||||
public interface IAppSettingsService
|
||||
{
|
||||
bool Locked { get; set; }
|
||||
int FailedPinAttempts { get; set; }
|
||||
DateTime LastActivity { get; set; }
|
||||
DateTime LastCacheClear { get; set; }
|
||||
bool AutofillPersistNotification { get; set; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IMemoryService
|
||||
{
|
||||
MemoryInfo GetInfo();
|
||||
void Check();
|
||||
}
|
||||
|
||||
public class MemoryInfo
|
||||
{
|
||||
public long FreeMemory { get; set; }
|
||||
public long MaxMemory { get; set; }
|
||||
public long TotalMemory { get; set; }
|
||||
public long UsedMemory => TotalMemory - FreeMemory;
|
||||
|
||||
public double HeapUsage()
|
||||
{
|
||||
return UsedMemory / (double)TotalMemory;
|
||||
}
|
||||
|
||||
public double Usage()
|
||||
{
|
||||
return UsedMemory / (double)MaxMemory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using Bit.App.Controls;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IReflectionService
|
||||
{
|
||||
Func<double, double, SizeRequest> GetVisualElementOnSizeRequest(ExtendedTableView tableView);
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,21 @@
|
||||
<RootNamespace>Bit.App</RootNamespace>
|
||||
<AssemblyName>BitwardenApp</AssemblyName>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Configurations>Debug;Release;FDroid</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)' == 'FDroid|netstandard2.0|AnyCPU'">
|
||||
<DefineConstants>TRACE;FDROID;NETSTANDARD2_0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)' == 'FDroid|net471|AnyCPU'">
|
||||
<DefineConstants>TRACE;FDROID;NET471</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Remove="Resources\AppResources.fa.resx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\public_suffix_list.dat" />
|
||||
</ItemGroup>
|
||||
@@ -25,8 +38,8 @@
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.3" />
|
||||
<PackageReference Include="Xam.Plugin.Connectivity" Version="3.0.3" />
|
||||
<PackageReference Include="Xam.Plugins.Settings" Version="3.1.1" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.2.9" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="2.5.0.121934" />
|
||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.3.4" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="2.5.0.122203" />
|
||||
<PackageReference Include="XLabs.IoC" Version="2.0.5782" />
|
||||
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.1.47" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
public const string ApiUrl = "other:apiUrl";
|
||||
public const string IdentityUrl = "other:identityUrl";
|
||||
public const string IconsUrl = "other:iconsUrl";
|
||||
public const string FailedPinAttempts = "other:failedPinAttempts";
|
||||
|
||||
public const int SelectFileRequestCode = 42;
|
||||
public const int SelectFilePermissionRequestCode = 43;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Pages;
|
||||
using Xamarin.Forms;
|
||||
using XLabs.Ioc;
|
||||
|
||||
@@ -10,23 +11,33 @@ namespace Bit.App.Controls
|
||||
private IGoogleAnalyticsService _googleAnalyticsService;
|
||||
private ILockService _lockService;
|
||||
private IDeviceActionService _deviceActionService;
|
||||
private IAuthService _authService;
|
||||
private bool _syncIndicator;
|
||||
private bool _updateActivity;
|
||||
private bool _requireAuth;
|
||||
|
||||
public ExtendedContentPage(bool syncIndicator = false, bool updateActivity = true)
|
||||
public ExtendedContentPage(bool syncIndicator = false, bool updateActivity = true, bool requireAuth = true)
|
||||
{
|
||||
_syncIndicator = syncIndicator;
|
||||
_updateActivity = updateActivity;
|
||||
_requireAuth = requireAuth;
|
||||
_syncService = Resolver.Resolve<ISyncService>();
|
||||
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||
_lockService = Resolver.Resolve<ILockService>();
|
||||
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
|
||||
_authService = Resolver.Resolve<IAuthService>();
|
||||
|
||||
BackgroundColor = Color.FromHex("efeff4");
|
||||
}
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
if(_requireAuth && !_authService.IsAuthenticated)
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(
|
||||
() => Application.Current.MainPage = new ExtendedNavigationPage(new HomePage()));
|
||||
}
|
||||
|
||||
if(_syncIndicator)
|
||||
{
|
||||
MessagingCenter.Subscribe<Application, bool>(Application.Current, "SyncCompleted",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Xamarin.Forms;
|
||||
using XLabs.Ioc;
|
||||
using Bit.App.Abstractions;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
@@ -40,17 +40,41 @@ namespace Bit.App.Controls
|
||||
public bool NoHeader { get; set; }
|
||||
public bool NoFooter { get; set; }
|
||||
public int BottomPadding { get; set; }
|
||||
public Func<RedrawableStackLayout> WrappingStackLayout { get; set; }
|
||||
|
||||
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if(!VerticalOptions.Expands && Device.RuntimePlatform != Device.UWP)
|
||||
{
|
||||
var reflectionService = Resolver.Resolve<IReflectionService>();
|
||||
var baseBaseOnSizeRequest = reflectionService.GetVisualElementOnSizeRequest(this);
|
||||
return baseBaseOnSizeRequest(widthConstraint, heightConstraint);
|
||||
var baseOnSizeRequest = GetVisualElementOnSizeRequest();
|
||||
return baseOnSizeRequest(widthConstraint, heightConstraint);
|
||||
}
|
||||
|
||||
return base.OnSizeRequest(widthConstraint, heightConstraint);
|
||||
}
|
||||
|
||||
private Func<double, double, SizeRequest> GetVisualElementOnSizeRequest()
|
||||
{
|
||||
var handle = typeof(VisualElement).GetMethod(
|
||||
"OnSizeRequest",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic,
|
||||
null,
|
||||
new Type[] { typeof(double), typeof(double) },
|
||||
null)?.MethodHandle;
|
||||
|
||||
if(!handle.HasValue)
|
||||
{
|
||||
throw new ArgumentNullException("handle could not be found.");
|
||||
}
|
||||
|
||||
var pointer = handle.Value.GetFunctionPointer();
|
||||
if(pointer == null)
|
||||
{
|
||||
throw new ArgumentNullException("pointer could not be found.");
|
||||
}
|
||||
|
||||
return (Func<double, double, SizeRequest>)Activator.CreateInstance(
|
||||
typeof(Func<double, double, SizeRequest>), this, pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
@@ -150,6 +179,7 @@ namespace Bit.App.Controls
|
||||
}
|
||||
}
|
||||
}
|
||||
public Dictionary<string, object> MetaData { get; set; }
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
|
||||
47
src/App/Controls/FormSwitchCell.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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,22 +104,20 @@ namespace Bit.App.Controls
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
buttonStackLayout.Spacing = 5;
|
||||
containerStackLayout.AdjustPaddingForDevice();
|
||||
}
|
||||
else if(Device.RuntimePlatform == Device.UWP)
|
||||
{
|
||||
buttonStackLayout.Spacing = 0;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if(Sub != null && Button1 != null)
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
using Bit.App.Abstractions;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
using XLabs.Ioc;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class MemoryContentView : ContentView
|
||||
{
|
||||
private readonly IMemoryService _memoryService;
|
||||
|
||||
public MemoryContentView()
|
||||
{
|
||||
_memoryService = Resolver.Resolve<IMemoryService>();
|
||||
|
||||
var grid = new Grid
|
||||
{
|
||||
Padding = 5,
|
||||
BackgroundColor = Color.White,
|
||||
RowDefinitions = new RowDefinitionCollection
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions = new ColumnDefinitionCollection
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
|
||||
grid.Children.Add(new Label { Text = "Used Memory:" }, 0, 0);
|
||||
grid.Children.Add(new Label { Text = "Free Memory:" }, 0, 1);
|
||||
grid.Children.Add(new Label { Text = "Heap Memory:" }, 0, 2);
|
||||
grid.Children.Add(new Label { Text = "Max Memory:" }, 0, 3);
|
||||
grid.Children.Add(new Label { Text = "% Used Heap:" }, 0, 4);
|
||||
grid.Children.Add(new Label { Text = "% Used Max:" }, 0, 5);
|
||||
|
||||
UsedMemory = new Label { Text = "Used Memory:", HorizontalTextAlignment = TextAlignment.End };
|
||||
FreeMemory = new Label { Text = "Free Memory:", HorizontalTextAlignment = TextAlignment.End };
|
||||
HeapMemory = new Label { Text = "Heap Memory:", HorizontalTextAlignment = TextAlignment.End };
|
||||
MaxMemory = new Label { Text = "Max Memory:", HorizontalTextAlignment = TextAlignment.End };
|
||||
HeapUsage = new Label { Text = "% Used Heap:", HorizontalTextAlignment = TextAlignment.End };
|
||||
TotalUsage = new Label { Text = "% Used Max:", HorizontalTextAlignment = TextAlignment.End };
|
||||
|
||||
grid.Children.Add(UsedMemory, 1, 0);
|
||||
grid.Children.Add(FreeMemory, 1, 1);
|
||||
grid.Children.Add(HeapMemory, 1, 2);
|
||||
grid.Children.Add(MaxMemory, 1, 3);
|
||||
grid.Children.Add(HeapUsage, 1, 4);
|
||||
grid.Children.Add(TotalUsage, 1, 5);
|
||||
|
||||
var button = new ExtendedButton { Text = "Refresh", BackgroundColor = Color.Transparent };
|
||||
button.Clicked += Button_Clicked;
|
||||
grid.Children.Add(button, 0, 6);
|
||||
Grid.SetColumnSpan(button, 2);
|
||||
|
||||
Content = grid;
|
||||
|
||||
RefreshScreen();
|
||||
}
|
||||
|
||||
private void Button_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
RefreshScreen();
|
||||
}
|
||||
|
||||
public Label UsedMemory { get; set; }
|
||||
public Label FreeMemory { get; set; }
|
||||
public Label HeapMemory { get; set; }
|
||||
public Label MaxMemory { get; set; }
|
||||
public Label HeapUsage { get; set; }
|
||||
public Label TotalUsage { get; set; }
|
||||
|
||||
void RefreshScreen()
|
||||
{
|
||||
UsedMemory.Text = FreeMemory.Text = HeapMemory.Text = MaxMemory.Text =
|
||||
HeapUsage.Text = TotalUsage.Text = string.Empty;
|
||||
|
||||
UsedMemory.TextColor = FreeMemory.TextColor = HeapMemory.TextColor =
|
||||
MaxMemory.TextColor = HeapUsage.TextColor = TotalUsage.TextColor = Color.Black;
|
||||
|
||||
if(_memoryService != null)
|
||||
{
|
||||
var info = _memoryService.GetInfo();
|
||||
if(info != null)
|
||||
{
|
||||
UsedMemory.Text = string.Format("{0:N} mb", Math.Round(info.UsedMemory / 1024 / 1024D, 2));
|
||||
FreeMemory.Text = string.Format("{0:N} mb", Math.Round(info.FreeMemory / 1024 / 1024D, 2));
|
||||
HeapMemory.Text = string.Format("{0:N} mb", Math.Round(info.TotalMemory / 1024 / 1024D, 2));
|
||||
MaxMemory.Text = string.Format("{0:N} mb", Math.Round(info.MaxMemory / 1024 / 1024D, 2));
|
||||
HeapUsage.Text = string.Format("{0:P}", info.HeapUsage());
|
||||
TotalUsage.Text = string.Format("{0:P}", info.Usage());
|
||||
|
||||
if(info.Usage() > 0.8)
|
||||
{
|
||||
FreeMemory.TextColor = UsedMemory.TextColor = TotalUsage.TextColor = Color.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/App/Controls/RedrawableStackLayout.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class RedrawableStackLayout : StackLayout
|
||||
{
|
||||
private DateTime _lastRedraw = DateTime.MinValue;
|
||||
private TimeSpan _redrawThreshold = TimeSpan.FromMilliseconds(1000);
|
||||
|
||||
public async Task RedrawIfNeededAsync(int delay = 0, bool force = false)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if(Device.RuntimePlatform == Device.iOS && (force || (now - _lastRedraw) > _redrawThreshold))
|
||||
{
|
||||
_lastRedraw = now;
|
||||
if(delay > 0)
|
||||
{
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
|
||||
InvalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
Duo = 2,
|
||||
YubiKey = 3,
|
||||
U2f = 4,
|
||||
Remember = 5
|
||||
Remember = 5,
|
||||
OrganizationDuo = 6
|
||||
}
|
||||
}
|
||||
|
||||
12
src/App/Enums/UriMatchType.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
24
src/App/Models/Api/CardType.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
18
src/App/Models/Api/FieldType.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
48
src/App/Models/Api/IdentityType.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
24
src/App/Models/Api/LoginType.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
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;
|
||||
Totp = cipher.Login.Totp?.EncryptedString;
|
||||
}
|
||||
|
||||
public IEnumerable<LoginUriType> Uris { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Totp { get; set; }
|
||||
}
|
||||
}
|
||||
18
src/App/Models/Api/LoginUriType.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,7 @@ 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));
|
||||
}
|
||||
|
||||
switch(Type)
|
||||
@@ -50,101 +45,11 @@ 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 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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Bit.App.Enums;
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
@@ -15,7 +14,13 @@ 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<string> CollectionIds { get; set; }
|
||||
public DateTime RevisionDate { get; set; }
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using Bit.App.Enums;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class SecureNoteDataModel : CipherDataModel
|
||||
{
|
||||
public SecureNoteType Type { get; set; }
|
||||
}
|
||||
}
|
||||
14
src/App/Models/Api/SecureNoteType.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||