1
0
mirror of https://github.com/bitwarden/mobile synced 2026-02-20 03:13:40 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Federico Maccaroni
f24b13502f PR labeler test to see how labels behave on App 2023-05-05 18:29:06 +02:00
85 changed files with 1020 additions and 1352 deletions

10
.github/labeler.yml vendored
View File

@@ -8,11 +8,11 @@ iOS:
- src/Core/*
- lib/ios/*
- src/iOS/*
- 'src/iOS.Autofill/*'
- 'src/iOS.Core/*'
- 'src/iOS.Extension/*'
- 'src/iOS.ShareExtension/*'
- 'src/iOS.Widget/*'
- src/iOS.Autofill/*
- src/iOS.Core/*
- src/iOS.Extension/*
- src/iOS.ShareExtension/*
- src/iOS.Widget/*
- src/watchOS/*
watchOS:

View File

@@ -14,7 +14,7 @@ jobs:
# Feature request
- if: github.event.label.name == 'feature-request'
name: Feature request
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with:
comment: |
We use GitHub issues as a place to track bugs and other development related issues. The [Bitwarden Community Forums](https://community.bitwarden.com/) has a [Feature Requests](https://community.bitwarden.com/c/feature-requests) section for submitting, voting for, and discussing requests like this one.
@@ -25,7 +25,7 @@ jobs:
# Intended behavior
- if: github.event.label.name == 'intended-behavior'
name: Intended behaviour
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with:
comment: |
Your issue appears to be describing the intended behavior of the software. If you want this to be changed, it would be a feature request.
@@ -38,7 +38,7 @@ jobs:
# Customer support request
- if: github.event.label.name == 'customer-support'
name: Customer Support request
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with:
comment: |
We use GitHub issues as a place to track bugs and other development related issues. Your issue appears to be a support request, or would otherwise be better handled by our dedicated Customer Success team.
@@ -49,14 +49,14 @@ jobs:
# Resolved
- if: github.event.label.name == 'resolved'
name: Resolved
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with:
comment: |
Weve closed this issue, as it appears the original problem has been resolved. If this happens again or continues to be an problem, please respond to this issue with any additional detail to assist with reproduction and root cause analysis.
# Stale
- if: github.event.label.name == 'stale'
name: Stale
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1
uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with:
comment: |
As we havent heard from you about this problem in some time, this issue will now be closed.

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Set up CLOC
run: |
@@ -36,7 +36,7 @@ jobs:
hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }}
steps:
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
with:
submodules: 'true'
@@ -67,12 +67,12 @@ jobs:
variant: ["prod", "qa"]
steps:
- name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
with:
nuget-version: 5.9.0
- name: Set up MSBuild
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
- name: Setup Windows builder
run: choco install checksum --no-progress
@@ -105,7 +105,7 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
with:
fetch-depth: 0
- name: Decrypt secrets
@@ -157,7 +157,7 @@ jobs:
shell: pwsh
- name: Report test results
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 # v1.6.0
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226
if: always()
with:
name: Test Results
@@ -232,7 +232,7 @@ jobs:
shell: pwsh
- name: Upload Prod .aab artifact
if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab
@@ -240,7 +240,7 @@ jobs:
- name: Upload Prod .apk artifact
if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk
@@ -248,7 +248,7 @@ jobs:
- name: Upload Other .apk artifact
if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
@@ -268,7 +268,7 @@ jobs:
- name: Upload .apk sha file for prod
if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: bw-android-apk-sha256.txt
path: ./bw-android-apk-sha256.txt
@@ -276,7 +276,7 @@ jobs:
- name: Upload .apk sha file for other
if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: bw-android-${{ matrix.variant }}-apk-sha256.txt
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
@@ -303,12 +303,12 @@ jobs:
runs-on: windows-2022
steps:
- name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
with:
nuget-version: 5.9.0
- name: Set up MSBuild
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
- name: Setup Windows builder
run: choco install checksum --no-progress
@@ -342,7 +342,7 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Decrypt secrets
env:
@@ -477,7 +477,7 @@ jobs:
shell: pwsh
- name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk
@@ -489,7 +489,7 @@ jobs:
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
- name: Upload F-Droid sha file
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: bw-fdroid-apk-sha256.txt
path: ./bw-fdroid-apk-sha256.txt
@@ -502,7 +502,7 @@ jobs:
needs: setup
steps:
- name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
with:
nuget-version: 5.9.0
@@ -515,12 +515,12 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
with:
submodules: 'true'
- name: Login to Azure - CI Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -698,7 +698,7 @@ jobs:
shell: bash
- name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: Bitwarden iOS
path: |
@@ -771,10 +771,10 @@ jobs:
_CROWDIN_PROJECT_ID: "269690"
steps:
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Login to Azure - CI Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -793,7 +793,7 @@ jobs:
done
- name: Upload Sources
uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9
uses: crowdin/github-action@9237b4cb361788dfce63feb2e2f15c09e2fe7415
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
@@ -840,7 +840,7 @@ jobs:
fi
- name: Login to Azure - CI Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
if: failure()
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -861,7 +861,7 @@ jobs:
done
- name: Notify Slack on failure
uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0
uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}

View File

@@ -15,22 +15,22 @@ jobs:
_CROWDIN_PROJECT_ID: "269690"
steps:
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Login to Azure - CI Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af
with:
keyvault: "bitwarden-ci"
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations
uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9
uses: crowdin/github-action@12143a68c213f3c6d9913c9e5023224f7231face
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Enforce Label
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # v2.2.2
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
with:
BANNED_LABELS: "hold,needs-qa"
BANNED_LABELS_DESCRIPTION: "PRs with the hold or needs-qa labels cannot be merged"

View File

@@ -38,11 +38,11 @@ jobs:
fi
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/release-version-check@8f055ef543c7433c967a1b9b04a0f230923233bb
with:
release-type: ${{ github.event.inputs.release_type }}
project-type: xamarin
@@ -56,7 +56,7 @@ jobs:
- name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5
uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48
id: deployment
with:
token: '${{ secrets.GITHUB_TOKEN }}'
@@ -104,7 +104,7 @@ jobs:
- name: Update deployment status to Success
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with:
token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success'
@@ -112,7 +112,7 @@ jobs:
- name: Update deployment status to Failure
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with:
token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure'
@@ -126,7 +126,7 @@ jobs:
if: inputs.fdroid_publish
steps:
- name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
- name: Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }}

View File

@@ -14,7 +14,7 @@ jobs:
version_number: ${{ steps.version.outputs.new-version }}
steps:
- name: Checkout Branch
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Calculate bumped version
id: version

View File

@@ -22,22 +22,22 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout Branch
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Login to Azure - CI Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af
with:
keyvault: "bitwarden-ci"
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@111c56156bcc6918c056dbef52164cfa583dc549 # v5.2.0
uses: crazy-max/ghaction-import-gpg@c8bb57c57e8df1be8c73ff3d59deab1dbc00e0d1
with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
@@ -48,31 +48,31 @@ jobs:
run: git switch -c version_bump_${{ github.event.inputs.version_number }}
- name: Bump Version - Android XML
uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/Android/Properties/AndroidManifest.xml"
- name: Bump Version - iOS.Autofill
uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS.Autofill/Info.plist"
- name: Bump Version - iOS.Extension
uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS.Extension/Info.plist"
- name: Bump Version - iOS.ShareExtension
uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS.ShareExtension/Info.plist"
- name: Bump Version - iOS
uses: bitwarden/gh-actions/version-bump@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS/Info.plist"

View File

@@ -8,4 +8,4 @@ on:
jobs:
call-workflow:
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@34ecb67b2a357795dc893549df0795e7383ff50f
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@master

View File

@@ -78,20 +78,21 @@
<Version>1.9.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.5.1.1" />
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.16" />
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.19" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.10.0" />
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.14" />
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.17" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.9.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.15" />
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.3.1.1" />
<PackageReference Include="Xamarin.Essentials">
<Version>1.7.5</Version>
<Version>1.7.3</Version>
</PackageReference>
<PackageReference Include="Xamarin.Firebase.Messaging">
<Version>123.1.1.1</Version>
<Version>123.0.8</Version>
</PackageReference>
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.8.0" />
<PackageReference Include="Xamarin.Google.Dagger" Version="2.44.2.1" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.6.1.1" />
<PackageReference Include="Xamarin.Google.Dagger" Version="2.41.0.2" />
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet">
<Version>118.0.1.3</Version>
<Version>118.0.1.2</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>

View File

@@ -83,7 +83,7 @@ namespace Bit.Droid.Services
return launchIntentSender != null;
}
public async Task ShowLoadingAsync(string text, System.Threading.CancellationTokenSource cts = null, string cancelButtonText = null)
public async Task ShowLoadingAsync(string text)
{
if (_progressDialog != null)
{
@@ -98,16 +98,10 @@ namespace Bit.Droid.Services
txtLoading.Text = text;
txtLoading.SetTextColor(ThemeHelpers.TextColor);
var progressDialogBuilder = new AlertDialog.Builder(activity)
_progressDialog = new AlertDialog.Builder(activity)
.SetView(dialogView)
.SetCancelable(cts != null);
if (cts != null)
{
progressDialogBuilder.SetNegativeButton(cancelButtonText ?? AppResources.Cancel, (sender, args) => cts?.Cancel());
}
_progressDialog = progressDialogBuilder.Create();
.SetCancelable(false)
.Create();
_progressDialog.Show();
}

View File

@@ -1,5 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models;
@@ -14,7 +13,7 @@ namespace Bit.App.Abstractions
string GetBuildNumber();
void Toast(string text, bool longDuration = false);
Task ShowLoadingAsync(string text, CancellationTokenSource cts = null, string cancelButtonText = null);
Task ShowLoadingAsync(string text);
Task HideLoadingAsync();
Task<string> DisplayPromptAync(string title = null, string description = null, string text = null,
string okButtonText = null, string cancelButtonText = null, bool numericKeyboard = false,

View File

@@ -14,11 +14,11 @@
<ItemGroup>
<PackageReference Include="Plugin.Fingerprint" Version="2.1.5" />
<PackageReference Include="SkiaSharp.Views.Forms" Version="2.88.3" />
<PackageReference Include="Xamarin.CommunityToolkit" Version="2.0.6" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.5" />
<PackageReference Include="SkiaSharp.Views.Forms" Version="2.88.2" />
<PackageReference Include="Xamarin.CommunityToolkit" Version="2.0.5" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.3" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.11.982" />
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2578" />
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2515" />
<PackageReference Include="ZXing.Net.Mobile" Version="2.4.1" />
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.4.1" />
<PackageReference Include="MessagePack" Version="2.4.59" />

View File

@@ -18,6 +18,12 @@ using Bit.Core.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Bit.App
{
@@ -38,7 +44,6 @@ namespace Bit.App
private readonly IFileService _fileService;
private readonly IAccountsManager _accountsManager;
private readonly IPushNotificationService _pushNotificationService;
private readonly IConfigService _configService;
private static bool _isResumed;
// these variables are static because the app is launching new activities on notification click, creating new instances of App.
private static bool _pendingCheckPasswordlessLoginRequests;
@@ -62,7 +67,6 @@ namespace Bit.App
_fileService = ServiceContainer.Resolve<IFileService>();
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
_configService = ServiceContainer.Resolve<IConfigService>();
_accountsManager.Init(() => Options, this);
@@ -171,10 +175,6 @@ namespace Bit.App
new NavigationPage(new UpdateTempPasswordPage()));
});
}
else if (message.Command == "syncCompleted")
{
await _configService.GetAsync(true);
}
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
@@ -299,8 +299,6 @@ namespace Bit.App
// Reset delay on every start
_vaultTimeoutService.DelayLockAndLogoutMs = null;
}
await _configService.GetAsync();
_messagingService.Send("startEventTimer");
}

View File

@@ -3,7 +3,6 @@ using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
@@ -19,8 +18,7 @@ namespace Bit.App.Pages
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
PageTitle = AppResources.Settings;
BaseUrl = _environmentService.BaseUrl == EnvironmentUrlData.DefaultEU.Base || EnvironmentUrlData.DefaultUS.Base == _environmentService.BaseUrl ?
string.Empty : _environmentService.BaseUrl;
BaseUrl = _environmentService.BaseUrl;
WebVaultUrl = _environmentService.WebVaultUrl;
ApiUrl = _environmentService.ApiUrl;
IdentityUrl = _environmentService.IdentityUrl;

View File

@@ -25,6 +25,10 @@
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Account}" />
<ToolbarItem x:Name="_closeButton" Text="{u:I18n Close}" Command="{Binding CloseCommand}" Order="Primary" Priority="-1"/>
<ToolbarItem
Icon="cog_environment.png" Clicked="Environment_Clicked" Order="Primary"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Options}" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
@@ -62,27 +66,7 @@
</Entry>
<StackLayout
Orientation="Horizontal"
Margin="0, 6, 0 ,0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding ShowEnvironmentPickerCommand}" />
</StackLayout.GestureRecognizers>
<Label
Text="{Binding RegionText}"
FontSize="13"
TextColor="{DynamicResource MutedColor}"
VerticalOptions="Center"
VerticalTextAlignment="Center"/>
<controls:IconLabel
Text="{Binding SelectedEnvironmentName}"
FontSize="13"
TextColor="{DynamicResource PrimaryColor}"
VerticalOptions="Center"
VerticalTextAlignment="Center"/>
</StackLayout>
<StackLayout
Orientation="Horizontal"
Margin="0, 20, 0 ,0">
Margin="0, 16, 0 ,0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding RememberEmailCommand}" />

View File

@@ -15,8 +15,6 @@ namespace Bit.App.Pages
private readonly AppOptions _appOptions;
private IBroadcasterService _broadcasterService;
readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
public HomePage(AppOptions appOptions = null)
{
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
@@ -72,14 +70,6 @@ namespace Bit.App.Pages
});
}
});
try
{
await _vm.UpdateEnvironment();
}
catch (Exception ex)
{
_logger.Value?.Exception(ex);
}
}
protected override bool OnBackButtonPressed()
@@ -138,6 +128,14 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new NavigationPage(page));
}
private void Environment_Clicked(object sender, EventArgs e)
{
if (DoOnce())
{
_vm.StartEnvironmentAction();
}
}
private async Task StartEnvironmentAsync()
{
await _accountListOverlay.HideAsync();

View File

@@ -4,10 +4,7 @@ using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Models.Data;
using Bit.Core.Models.Response;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
@@ -20,19 +17,16 @@ namespace Bit.App.Pages
{
private readonly IStateService _stateService;
private readonly IMessagingService _messagingService;
private readonly IPlatformUtilsService _platformUtilsService;
private readonly ILogger _logger;
private readonly IEnvironmentService _environmentService;
private readonly IAccountsManager _accountManager;
private readonly IConfigService _configService;
private bool _showCancelButton;
private bool _rememberEmail;
private string _email;
private string _selectedEnvironmentName;
private bool _isEmailEnabled;
private bool _canLogin;
private bool _displayEuEnvironment;
private IPlatformUtilsService _platformUtilsService;
private ILogger _logger;
private IEnvironmentService _environmentService;
private IAccountsManager _accountManager;
public HomeViewModel()
{
@@ -42,7 +36,6 @@ namespace Bit.App.Pages
_logger = ServiceContainer.Resolve<ILogger>();
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
_accountManager = ServiceContainer.Resolve<IAccountsManager>();
_configService = ServiceContainer.Resolve<IConfigService>();
PageTitle = AppResources.Bitwarden;
@@ -56,8 +49,6 @@ namespace Bit.App.Pages
onException: _logger.Exception, allowsMultipleExecutions: false);
CloseCommand = new AsyncCommand(async () => await Device.InvokeOnMainThreadAsync(CloseAction),
onException: _logger.Exception, allowsMultipleExecutions: false);
ShowEnvironmentPickerCommand = new AsyncCommand(ShowEnvironmentPickerAsync,
onException: _logger.Exception, allowsMultipleExecutions: false);
InitAsync().FireAndForget();
}
@@ -80,13 +71,6 @@ namespace Bit.App.Pages
additionalPropertyNames: new[] { nameof(CanContinue) });
}
public string SelectedEnvironmentName
{
get => $"{_selectedEnvironmentName} {BitwardenIcons.AngleDown}";
set => SetProperty(ref _selectedEnvironmentName, value);
}
public string RegionText => $"{AppResources.Region}:";
public bool CanContinue => !string.IsNullOrEmpty(Email);
public FormattedString CreateAccountText
@@ -117,13 +101,11 @@ namespace Bit.App.Pages
public AsyncCommand ContinueCommand { get; }
public AsyncCommand CloseCommand { get; }
public AsyncCommand CreateAccountCommand { get; }
public AsyncCommand ShowEnvironmentPickerCommand { get; }
public async Task InitAsync()
{
Email = await _stateService.GetRememberedEmailAsync();
RememberEmail = !string.IsNullOrEmpty(Email);
_displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag, forceRefresh: true);
}
public async Task ContinueToLoginStepAsync()
@@ -162,56 +144,5 @@ namespace Bit.App.Pages
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage, AppResources.AnErrorHasOccurred, AppResources.Ok);
}
}
public async Task ShowEnvironmentPickerAsync()
{
var options = _displayEuEnvironment
? new string[] { AppResources.US, AppResources.EU, AppResources.SelfHosted }
: new string[] { AppResources.US, AppResources.SelfHosted };
await Device.InvokeOnMainThreadAsync(async () =>
{
var result = await Page.DisplayActionSheet(AppResources.DataRegion, AppResources.Cancel, null, options);
if (result is null || result == AppResources.Cancel)
{
return;
}
if (result == AppResources.SelfHosted)
{
StartEnvironmentAction?.Invoke();
return;
}
await _environmentService.SetUrlsAsync(result == AppResources.EU ? EnvironmentUrlData.DefaultEU : EnvironmentUrlData.DefaultUS);
SelectedEnvironmentName = result;
});
}
public async Task UpdateEnvironment()
{
var environmentsSaved = await _stateService.GetPreAuthEnvironmentUrlsAsync();
if (environmentsSaved == null || environmentsSaved.IsEmpty)
{
await _environmentService.SetUrlsAsync(EnvironmentUrlData.DefaultUS);
environmentsSaved = EnvironmentUrlData.DefaultUS;
SelectedEnvironmentName = AppResources.US;
return;
}
if (environmentsSaved.Base == EnvironmentUrlData.DefaultUS.Base)
{
SelectedEnvironmentName = AppResources.US;
}
else if (environmentsSaved.Base == EnvironmentUrlData.DefaultEU.Base)
{
SelectedEnvironmentName = AppResources.EU;
}
else
{
SelectedEnvironmentName = AppResources.SelfHosted;
}
}
}
}

View File

@@ -41,7 +41,6 @@ namespace Bit.App.Pages
private bool _isEmailEnabled;
private bool _isKnownDevice;
private bool _isExecutingLogin;
private string _environmentHostName;
public LoginPageViewModel()
{
@@ -116,16 +115,6 @@ namespace Bit.App.Pages
set => SetProperty(ref _isKnownDevice, value);
}
public string EnvironmentDomainName
{
get => _environmentHostName;
set => SetProperty(ref _environmentHostName, value,
additionalPropertyNames: new string[]
{
nameof(LoggingInAsText)
});
}
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
public Command LogInCommand { get; }
public Command TogglePasswordCommand { get; }
@@ -133,7 +122,7 @@ namespace Bit.App.Pages
public ICommand LogInWithDeviceCommand { get; }
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public string LoggingInAsText => string.Format(AppResources.LoggingInAsXOnY, Email, EnvironmentDomainName);
public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email);
public bool IsIosExtension { get; set; }
public bool CanRemoveAccount { get; set; }
public Action StartTwoFactorAction { get; set; }
@@ -162,7 +151,6 @@ namespace Bit.App.Pages
Email = await _stateService.GetRememberedEmailAsync();
}
CanRemoveAccount = await _stateService.GetActiveUserEmailAsync() != Email;
EnvironmentDomainName = CoreHelpers.GetDomain((await _stateService.GetPreAuthEnvironmentUrlsAsync())?.Base);
IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, await _appIdService.GetAppIdAsync());
}
catch (ApiException apiEx) when (apiEx.Error.StatusCode == System.Net.HttpStatusCode.Unauthorized)

View File

@@ -121,8 +121,9 @@ namespace Bit.App.Pages
var ssoToken = response.Token;
var passwordOptions = PasswordGenerationOptions.CreateDefault
.WithLength(64);
var passwordOptions = new PasswordGenerationOptions(true);
passwordOptions.Length = 64;
var codeVerifier = await _passwordGenerationService.GeneratePasswordAsync(passwordOptions);
var codeVerifierHash = await _cryptoFunctionService.HashAsync(codeVerifier, CryptoHashAlgorithm.Sha256);

View File

@@ -827,7 +827,7 @@ namespace Bit.App.Pages
private void SetOptions()
{
_options.AllowAmbiguousChar = AllowAmbiguousChars;
_options.Type = PasswordTypeSelectedIndex == 1 ? PasswordGenerationOptions.TYPE_PASSPHRASE : PasswordGenerationOptions.TYPE_PASSWORD;
_options.Type = PasswordTypeSelectedIndex == 1 ? "passphrase" : "password";
_options.MinNumber = MinNumber;
_options.MinSpecial = MinSpecial;
_options.Special = Special;

View File

@@ -131,7 +131,7 @@ namespace Bit.App.Pages
{
// if we have a vault timeout policy, we need to filter the timeout options
_vaultTimeoutPolicy = (await _policyService.GetAll(PolicyType.MaximumVaultTimeout)).First();
var policyMinutes = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY);
var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES);
_vaultTimeoutOptions = _vaultTimeoutOptions.Where(t =>
t.Value <= policyMinutes &&
(t.Value > 0 || t.Value == CustomVaultTimeoutValue) &&
@@ -302,7 +302,7 @@ namespace Bit.App.Pages
if (_vaultTimeoutPolicy != null)
{
var maximumTimeout = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY);
var maximumTimeout = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES);
if (newTimeout > maximumTimeout)
{
@@ -382,7 +382,7 @@ namespace Bit.App.Pages
public async Task VaultTimeoutActionAsync()
{
if (_vaultTimeoutPolicy != null &&
!string.IsNullOrEmpty(_vaultTimeoutPolicy.GetString(Policy.ACTION_KEY)))
!string.IsNullOrEmpty(_policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION)))
{
// do nothing if we have a policy set
return;
@@ -610,8 +610,8 @@ namespace Bit.App.Pages
}
if (_vaultTimeoutPolicy != null)
{
var policyMinutes = _vaultTimeoutPolicy.GetInt(Policy.MINUTES_KEY);
var policyAction = _vaultTimeoutPolicy.GetString(Policy.ACTION_KEY);
var policyMinutes = _policyService.GetPolicyInt(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_MINUTES);
var policyAction = _policyService.GetPolicyString(_vaultTimeoutPolicy, PolicyService.TIMEOUT_POLICY_ACTION);
if (policyMinutes.HasValue || !string.IsNullOrWhiteSpace(policyAction))
{
@@ -625,14 +625,14 @@ namespace Bit.App.Pages
else if (!policyMinutes.HasValue && !string.IsNullOrWhiteSpace(policyAction))
{
policyAlert = string.Format(AppResources.VaultTimeoutActionPolicyInEffect,
policyAction == Policy.ACTION_LOCK ? AppResources.Lock : AppResources.LogOut);
policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut);
}
else
{
policyAlert = string.Format(AppResources.VaultTimeoutPolicyWithActionInEffect,
Math.Floor((float)policyMinutes / 60),
policyMinutes % 60,
policyAction == Policy.ACTION_LOCK ? AppResources.Lock : AppResources.LogOut);
policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? AppResources.Lock : AppResources.LogOut);
}
securityItems.Insert(0, new SettingsPageListItem
{

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions;
@@ -32,7 +31,6 @@ namespace Bit.App.Pages
private bool _hasUpdatedKey;
private bool _canAccessAttachments;
private string _fileName;
private CancellationTokenSource _uploadCts;
public AttachmentsPageViewModel()
{
@@ -121,15 +119,11 @@ namespace Bit.App.Pages
AppResources.AnErrorHasOccurred);
return false;
}
_uploadCts = new CancellationTokenSource();
var uploadCts = _uploadCts;
try
{
await _deviceActionService.ShowLoadingAsync(AppResources.Saving, uploadCts);
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
_cipherDomain = await _cipherService.SaveAttachmentRawWithServerAsync(
_cipherDomain, FileName, FileData, uploadCts.Token);
_cipherDomain, FileName, FileData);
Cipher = await _cipherDomain.DecryptAsync();
await _deviceActionService.HideLoadingAsync();
_platformUtilsService.ShowToast("success", null, AppResources.AttachementAdded);
@@ -138,11 +132,6 @@ namespace Bit.App.Pages
FileName = null;
return true;
}
catch (OperationCanceledException)
{
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.UploadHasBeenCanceled, AppResources.Attachments);
}
catch (ApiException e)
{
_logger.Exception(e);

View File

@@ -202,24 +202,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Biometric unlock for this account is disabled pending verification of master password..
/// </summary>
public static string AccountBiometricInvalidated {
get {
return ResourceManager.GetString("AccountBiometricInvalidated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Autofill biometric unlock for this account is disabled pending verification of master password..
/// </summary>
public static string AccountBiometricInvalidatedExtension {
get {
return ResourceManager.GetString("AccountBiometricInvalidatedExtension", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Your new account has been created! You may now log in..
/// </summary>
@@ -985,6 +967,24 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Biometric unlock disabled pending verification of master password..
/// </summary>
public static string AccountBiometricInvalidated {
get {
return ResourceManager.GetString("AccountBiometricInvalidated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Biometric unlock for autofill disabled pending verification of master password..
/// </summary>
public static string AccountBiometricInvalidatedExtension {
get {
return ResourceManager.GetString("AccountBiometricInvalidatedExtension", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Biometrics.
/// </summary>
@@ -1750,15 +1750,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Data region.
/// </summary>
public static string DataRegion {
get {
return ResourceManager.GetString("DataRegion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Password updated.
/// </summary>
@@ -2335,15 +2326,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to EU.
/// </summary>
public static string EU {
get {
return ResourceManager.GetString("EU", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exact.
/// </summary>
@@ -3587,11 +3569,11 @@ namespace Bit.App.Resources {
}
/// <summary>
/// Looks up a localized string similar to Logging in as {0} on {1}.
/// Looks up a localized string similar to Logging in as {0}.
/// </summary>
public static string LoggingInAsXOnY {
public static string LoggingInAsX {
get {
return ResourceManager.GetString("LoggingInAsXOnY", resourceCulture);
return ResourceManager.GetString("LoggingInAsX", resourceCulture);
}
}
@@ -5147,15 +5129,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Region.
/// </summary>
public static string Region {
get {
return ResourceManager.GetString("Region", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remember me.
/// </summary>
@@ -5489,15 +5462,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Self-hosted.
/// </summary>
public static string SelfHosted {
get {
return ResourceManager.GetString("SelfHosted", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Self-hosted environment.
/// </summary>
@@ -6515,15 +6479,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Upload has been canceled.
/// </summary>
public static string UploadHasBeenCanceled {
get {
return ResourceManager.GetString("UploadHasBeenCanceled", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uppercase (A to Z).
/// </summary>
@@ -6569,15 +6524,6 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to US.
/// </summary>
public static string US {
get {
return ResourceManager.GetString("US", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use another two-step login method.
/// </summary>

View File

@@ -160,7 +160,7 @@
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data>
<data name="Credits" xml:space="preserve">
<value>কৃতিত্ব</value>
<value>Credits</value>
<comment>Title for page that we use to give credit to resources that we use.</comment>
</data>
<data name="Delete" xml:space="preserve">
@@ -168,11 +168,11 @@
<comment>Delete an entity (verb).</comment>
</data>
<data name="Deleting" xml:space="preserve">
<value>মোছা হচ্ছে...</value>
<value>Deleting...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>আপনি কি সত্যিই মুছে ফেলতে চান? এটিকে পূর্বের মত করা যাবে না।.</value>
<value>Do you really want to delete? This cannot be undone.</value>
<comment>Confirmation alert message when deleteing something.</comment>
</data>
<data name="Edit" xml:space="preserve">
@@ -190,16 +190,16 @@
<comment>Full label for a email address.</comment>
</data>
<data name="EmailUs" xml:space="preserve">
<value>আমাদের ইমেইল করুন</value>
<value>Email us</value>
</data>
<data name="EmailUsDescription" xml:space="preserve">
<value>সাহায্য পেতে বা মতামত দিতে সরাসরি আমাদের ইমেল করুন।</value>
<value>Email us directly to get help or leave feedback.</value>
</data>
<data name="EnterPIN" xml:space="preserve">
<value>আপনার পিন কোডটি প্রবেশ করান</value>
<value>Enter your PIN code.</value>
</data>
<data name="Favorites" xml:space="preserve">
<value>পছন্দসমূহ</value>
<value>Favorites</value>
<comment>Title for your favorite items in the vault.</comment>
</data>
<data name="FileBugReport" xml:space="preserve">
@@ -216,7 +216,7 @@
<comment>Label for a folder.</comment>
</data>
<data name="FolderCreated" xml:space="preserve">
<value>নতুন ফোল্ডার তৈরি হয়েছে।</value>
<value>New folder created.</value>
</data>
<data name="FolderDeleted" xml:space="preserve">
<value>Folder deleted.</value>
@@ -276,7 +276,7 @@
<value>আপনি লগ আউট করতে চান?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>অ্যাকাউন্ট অপসারণ করুন</value>
<value>Remove account</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>Are you sure you want to remove this account?</value>
@@ -315,30 +315,30 @@
<comment>Label for notes.</comment>
</data>
<data name="Ok" xml:space="preserve">
<value>ঠিক আছে</value>
<value>Ok</value>
<comment>Acknowledgement.</comment>
</data>
<data name="Password" xml:space="preserve">
<value>পাসওয়ার্ড</value>
<value>Password</value>
<comment>Label for a password.</comment>
</data>
<data name="Save" xml:space="preserve">
<value>সংরক্ষণ করুন</value>
<value>Save</value>
<comment>Button text for a save operation (verb).</comment>
</data>
<data name="Move" xml:space="preserve">
<value>স্থানান্তর করুন</value>
<value>Move</value>
</data>
<data name="Saving" xml:space="preserve">
<value>Saving...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Settings" xml:space="preserve">
<value>সেটিংস</value>
<value>Settings</value>
<comment>The title for the settings page.</comment>
</data>
<data name="Show" xml:space="preserve">
<value>দেখান</value>
<value>Show</value>
<comment>Reveal a hidden value (password).</comment>
</data>
<data name="ItemDeleted" xml:space="preserve">
@@ -346,17 +346,17 @@
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
<value>জমা দিন</value>
<value>Submit</value>
</data>
<data name="Sync" xml:space="preserve">
<value>Sync</value>
<comment>The title for the sync page.</comment>
</data>
<data name="ThankYou" xml:space="preserve">
<value>ধন্যবাদ</value>
<value>Thank you</value>
</data>
<data name="Tools" xml:space="preserve">
<value>টুলস</value>
<value>Tools</value>
<comment>The title for the tools page.</comment>
</data>
<data name="URI" xml:space="preserve">
@@ -379,7 +379,7 @@
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data>
<data name="VerifyFingerprint" xml:space="preserve">
<value>আঙ্গুলের ছাপ যাচাই করুন</value>
<value>Verify fingerprint</value>
</data>
<data name="VerifyMasterPassword" xml:space="preserve">
<value>প্রধান পাসওয়ার্ড যাচাইকরণ</value>
@@ -388,32 +388,32 @@
<value>Verify PIN</value>
</data>
<data name="Version" xml:space="preserve">
<value>সংস্করণ</value>
<value>Version</value>
</data>
<data name="View" xml:space="preserve">
<value>View</value>
</data>
<data name="VisitOurWebsite" xml:space="preserve">
<value>আমাদের ওয়েবসাইটে ঢু মেরে আসুন</value>
<value>Visit our website</value>
</data>
<data name="VisitOurWebsiteDescription" xml:space="preserve">
<value>সাহায্য পেতে, খবর পেতে, আমাদের ইমেল করতে এবং/অথবা বিটওয়ার্ডেন কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও জানতে আমাদের ওয়েবসাইট দেখুন।</value>
<value>Visit our website to get help, news, email us, and/or learn more about how to use Bitwarden.</value>
</data>
<data name="Website" xml:space="preserve">
<value>ওয়েবসাইট</value>
<value>Website</value>
<comment>Label for a website.</comment>
</data>
<data name="Yes" xml:space="preserve">
<value>হ্যাঁ</value>
<value>Yes</value>
</data>
<data name="Account" xml:space="preserve">
<value>অ্যাকাউন্ট</value>
<value>Account</value>
</data>
<data name="AccountCreated" xml:space="preserve">
<value>আপনার নতুন অ্যাকাউন্ট তৈরি করা হয়েছে! আপনি এখন লগইন করতে পারবেন।</value>
<value>Your new account has been created! You may now log in.</value>
</data>
<data name="AddAnItem" xml:space="preserve">
<value>একটি আইটেম যোগ করুন</value>
<value>Add an Item</value>
</data>
<data name="AppExtension" xml:space="preserve">
<value>App extension</value>
@@ -425,7 +425,7 @@
<value>Auto-fill service</value>
</data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>অস্পষ্ট বর্ণগুলি বাদ দিয়ে যান</value>
<value>Avoid ambiguous characters</value>
</data>
<data name="BitwardenAppExtension" xml:space="preserve">
<value>Bitwarden app extension</value>
@@ -440,13 +440,13 @@
<value>Bitwarden Auto-fill Service</value>
</data>
<data name="BitwardenAutofillAccessibilityServiceDescription" xml:space="preserve">
<value>আপনার লগইনগুলি স্বয়ংক্রিয়ভাবে পূরণ করতে বিটওয়ার্ডেন অ্যাক্সেসিবিলিটি পরিষেবা ব্যবহার করুন৷</value>
<value>Use the Bitwarden accessibility service to auto-fill your logins.</value>
</data>
<data name="ChangeEmail" xml:space="preserve">
<value>ইমেইল পরিবর্তন করুন</value>
<value>Change email</value>
</data>
<data name="ChangeEmailConfirmation" xml:space="preserve">
<value>আপনি bitwarden.com ওয়েব ভল্টে আপনার ইমেল ঠিকানা পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইট ভিজিট করতে চান?</value>
<value>You can change your email address on the bitwarden.com web vault. Do you want to visit the website now?</value>
</data>
<data name="ChangeMasterPassword" xml:space="preserve">
<value>প্রধান পাসওয়ার্ড পরিবর্তন</value>
@@ -455,7 +455,7 @@
<value>আপনি bitwarden.com ওয়েব ভল্ট থেকে প্রধান পাসওয়ার্ডটি পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?</value>
</data>
<data name="Close" xml:space="preserve">
<value>বন্ধ করুন</value>
<value>Close</value>
</data>
<data name="Continue" xml:space="preserve">
<value>অবিরত</value>
@@ -480,7 +480,7 @@
<value>Reactivate app extension</value>
</data>
<data name="ExtensionAlmostDone" xml:space="preserve">
<value>প্রায় হয়ে গেছে!</value>
<value>Almost done!</value>
</data>
<data name="ExtensionEnable" xml:space="preserve">
<value>Activate app extension</value>
@@ -493,7 +493,7 @@
<value>Get instant access to your passwords!</value>
</data>
<data name="ExtensionReady" xml:space="preserve">
<value>আপনি লগইন করার জন্য একদম তৈরি!</value>
<value>You're ready to log in!</value>
</data>
<data name="ExtensionSetup" xml:space="preserve">
<value>Your logins are now easily accessible from Safari, Chrome, and other supported apps.</value>
@@ -511,7 +511,7 @@
<value>প্রিয়</value>
</data>
<data name="Fingerprint" xml:space="preserve">
<value>আঙুলের ছাপ</value>
<value>Fingerprint</value>
</data>
<data name="GeneratePassword" xml:space="preserve">
<value>পাসওয়ার্ড তৈরি করুন</value>
@@ -584,7 +584,7 @@
<value>যদি আপনি আপনার পাসওয়ার্ড ভুলে যান তাহলে একটি প্রধান পাসওয়ার্ডের ইঙ্গিতটি আপনাকে মনে করাতে সাহায্য করতে পারে।</value>
</data>
<data name="MasterPasswordLengthValMessageX" xml:space="preserve">
<value>মাস্টার পাসওয়ার্ড কমপক্ষে {0} অক্ষরের হতে হবে।</value>
<value>Master password must be at least {0} characters long.</value>
</data>
<data name="MinNumbers" xml:space="preserve">
<value>সর্বনিম্ন সংখ্যা</value>
@@ -595,7 +595,7 @@
<comment>Minimum special characters for password generator settings</comment>
</data>
<data name="MoreSettings" xml:space="preserve">
<value>আরও সেটিংস</value>
<value>More settings</value>
</data>
<data name="MustLogInMainApp" xml:space="preserve">
<value>You must log into the main Bitwarden app before you can use the extension.</value>
@@ -651,7 +651,7 @@
<comment>Push notifications for apple products</comment>
</data>
<data name="RateTheApp" xml:space="preserve">
<value>অ্যাপ্লিকেশনটকে রেট দিন</value>
<value>Rate the app</value>
</data>
<data name="RateTheAppDescription" xml:space="preserve">
<value>দয়া করে একটি ভাল পর্যালোচনার মাধ্যমে সাহায্য করতে আমাদের বিবেচনা করুন!</value>
@@ -684,7 +684,7 @@
<value>Item saved</value>
</data>
<data name="Submitting" xml:space="preserve">
<value>জমা দেওয়া হচ্ছে...</value>
<value>Submitting...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Syncing" xml:space="preserve">
@@ -701,7 +701,7 @@
<value>Sync vault now</value>
</data>
<data name="TouchID" xml:space="preserve">
<value>টাচ আইডি</value>
<value>Touch ID</value>
<comment>What Apple calls their fingerprint reader.</comment>
</data>
<data name="TwoStepLogin" xml:space="preserve">
@@ -717,17 +717,17 @@
<value>Unlock with PIN code</value>
</data>
<data name="Validating" xml:space="preserve">
<value>কার্যকর করা হচ্ছে</value>
<value>Validating</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="VerificationCode" xml:space="preserve">
<value>যাচাইকরণ কোড</value>
<value>Verification code</value>
</data>
<data name="ViewItem" xml:space="preserve">
<value>View item</value>
</data>
<data name="WebVault" xml:space="preserve">
<value>বিটওয়ার্ডেন ওয়েব ভল্ট</value>
<value>Bitwarden web vault</value>
</data>
<data name="Lost2FAApp" xml:space="preserve">
<value>Lost authenticator app?</value>
@@ -740,10 +740,10 @@
<value>Extension activated!</value>
</data>
<data name="Icons" xml:space="preserve">
<value>আইকন</value>
<value>Icons</value>
</data>
<data name="Translations" xml:space="preserve">
<value>অনুবাদসমূহ</value>
<value>Translations</value>
</data>
<data name="ItemsForUri" xml:space="preserve">
<value>Items for {0}</value>
@@ -769,19 +769,19 @@
<value>2. Switch on the toggle and press OK to accept.</value>
</data>
<data name="Disabled" xml:space="preserve">
<value>নিষ্ক্রিয়</value>
<value>Disabled</value>
</data>
<data name="Enabled" xml:space="preserve">
<value>সক্রিয়</value>
<value>Enabled</value>
</data>
<data name="Off" xml:space="preserve">
<value>বন্ধ</value>
<value>Off</value>
</data>
<data name="On" xml:space="preserve">
<value>চালু</value>
<value>On</value>
</data>
<data name="Status" xml:space="preserve">
<value>অবস্থা</value>
<value>Status</value>
</data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden Auto-fill Service. Learn more about using the Bitwarden Auto-fill Service by navigating to the "Settings" screen.</value>
@@ -876,7 +876,7 @@
<value>Unable to download file.</value>
</data>
<data name="UnableToOpenFile" xml:space="preserve">
<value>আপনার ডিভাইস এই ধরনের ফাইল খুলতে পারে না।</value>
<value>Your device cannot open this type of file.</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>ডাউনলোড হচ্ছে...</value>
@@ -904,13 +904,13 @@
Scanning will happen automatically.</value>
</data>
<data name="ScanQrTitle" xml:space="preserve">
<value>QR কোড স্ক্যান করুন</value>
<value>Scan QR Code</value>
</data>
<data name="Camera" xml:space="preserve">
<value>ক্যামেরা</value>
<value>Camera</value>
</data>
<data name="Photos" xml:space="preserve">
<value>ছবিসমূহ</value>
<value>Photos</value>
</data>
<data name="CopyTotp" xml:space="preserve">
<value>Copy TOTP</value>
@@ -934,7 +934,7 @@ Scanning will happen automatically.</value>
<value>Choose file</value>
</data>
<data name="File" xml:space="preserve">
<value>ফাইল</value>
<value>File</value>
</data>
<data name="NoFileChosen" xml:space="preserve">
<value>No file chosen</value>
@@ -1080,7 +1080,7 @@ Scanning will happen automatically.</value>
<value>নামের শেষাংশ</value>
</data>
<data name="FullName" xml:space="preserve">
<value>পুরো নাম</value>
<value>Full name</value>
</data>
<data name="LicenseNumber" xml:space="preserve">
<value>লাইসেন্স নম্বর</value>
@@ -1107,34 +1107,34 @@ Scanning will happen automatically.</value>
<value>Mx</value>
</data>
<data name="November" xml:space="preserve">
<value>নভেম্বর</value>
<value>November</value>
</data>
<data name="October" xml:space="preserve">
<value>অক্টোবর</value>
<value>October</value>
</data>
<data name="PassportNumber" xml:space="preserve">
<value>পাসপোর্ট নম্বর</value>
<value>Passport number</value>
</data>
<data name="Phone" xml:space="preserve">
<value>ফোন</value>
<value>Phone</value>
</data>
<data name="September" xml:space="preserve">
<value>সেপ্টেম্বর</value>
<value>September</value>
</data>
<data name="SSN" xml:space="preserve">
<value>সামাজিক সুরক্ষা নম্বর</value>
<value>Social Security number</value>
</data>
<data name="StateProvince" xml:space="preserve">
<value>রাজ্য / প্রদেশ</value>
<value>State / Province</value>
</data>
<data name="Title" xml:space="preserve">
<value>শিরোনাম</value>
<value>Title</value>
</data>
<data name="ZipPostalCode" xml:space="preserve">
<value>জিপ / পোস্টকোড</value>
<value>Zip / Postal code</value>
</data>
<data name="Address" xml:space="preserve">
<value>ঠিকানা</value>
<value>Address</value>
</data>
<data name="Expiration" xml:space="preserve">
<value>Expiration</value>
@@ -1204,7 +1204,7 @@ Scanning will happen automatically.</value>
<value>Custom field name</value>
</data>
<data name="FieldTypeBoolean" xml:space="preserve">
<value>বুলিয়ান</value>
<value>Boolean</value>
</data>
<data name="FieldTypeHidden" xml:space="preserve">
<value>Hidden</value>
@@ -1225,7 +1225,7 @@ Scanning will happen automatically.</value>
<value>Remove</value>
</data>
<data name="NewUri" xml:space="preserve">
<value>নতুন URI</value>
<value>New URI</value>
</data>
<data name="URIPosition" xml:space="preserve">
<value>URI {0}</value>
@@ -1272,7 +1272,7 @@ Scanning will happen automatically.</value>
<value>Hold your Yubikey near the top of the device.</value>
</data>
<data name="TryAgain" xml:space="preserve">
<value>আবার চেষ্টা করুন</value>
<value>Try again</value>
</data>
<data name="YubiKeyInstructionIos" xml:space="preserve">
<value>To continue, hold your YubiKey NEO against the back of the device.</value>
@@ -1440,16 +1440,16 @@ Scanning will happen automatically.</value>
<value>Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved.</value>
</data>
<data name="NumberOfWords" xml:space="preserve">
<value>শব্দসংখ্যা</value>
<value>Number of words</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>গুপ্ত-বাক্যাংশ</value>
<value>Passphrase</value>
</data>
<data name="WordSeparator" xml:space="preserve">
<value>শব্দ বিভাজক</value>
<value>Word separator</value>
</data>
<data name="Clear" xml:space="preserve">
<value>পরিষ্কার করুন</value>
<value>Clear</value>
<comment>To clear something out. example: To clear browser history.</comment>
</data>
<data name="Generator" xml:space="preserve">
@@ -1474,42 +1474,42 @@ Scanning will happen automatically.</value>
<value>Export vault</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>এখনই লক করুন</value>
<value>Lock now</value>
</data>
<data name="PIN" xml:space="preserve">
<value>পিন</value>
<value>PIN</value>
</data>
<data name="Unlock" xml:space="preserve">
<value>আনলক করুন</value>
<value>Unlock</value>
</data>
<data name="UnlockVault" xml:space="preserve">
<value>Unlock vault</value>
</data>
<data name="ThirtyMinutes" xml:space="preserve">
<value>৩০ মিনিট</value>
<value>30 minutes</value>
</data>
<data name="SetPINDescription" xml:space="preserve">
<value>Bitwarden আনলক করার জন্য আপনার পিন কোডটি সেট করুন। আপনি যদি অ্যাপ্লিকেশনটি থেকে পুরোপুরি লগ আউট করেন তবে আপনার পিন সেটিংস রিসেট করা হবে।</value>
<value>Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>{1}-এ {0} হিসেবে লগইন করা হয়েছে।</value>
<value>Logged in as {0} on {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
<value>আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার প্রধান পাসওয়ার্ডটি যাচাই করান।</value>
</data>
<data name="VaultLockedPIN" xml:space="preserve">
<value>আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার পিন কোড যাচাই করান।</value>
<value>Your vault is locked. Verify your PIN code to continue.</value>
</data>
<data name="VaultLockedIdentity" xml:space="preserve">
<value>আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার পরিচয় যাচাই করান।</value>
<value>Your vault is locked. Verify your identity to continue.</value>
</data>
<data name="Dark" xml:space="preserve">
<value>গাঢ়</value>
<value>Dark</value>
<comment>A dark color</comment>
</data>
<data name="Light" xml:space="preserve">
<value>উজ্জ্বল</value>
<value>Light</value>
<comment>A light color</comment>
</data>
<data name="FiveMinutes" xml:space="preserve">
@@ -1887,10 +1887,10 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="Text" xml:space="preserve">
<value>লেখা</value>
<value>Text</value>
</data>
<data name="TypeText" xml:space="preserve">
<value>লেখা</value>
<value>Text</value>
</data>
<data name="TypeTextInfo" xml:space="preserve">
<value>The text you want to send.</value>
@@ -1900,7 +1900,7 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="TypeFile" xml:space="preserve">
<value>ফাইল</value>
<value>File</value>
</data>
<data name="TypeFileInfo" xml:space="preserve">
<value>The file you want to send.</value>
@@ -1918,7 +1918,7 @@ Scanning will happen automatically.</value>
<value>Text type is not selected, tap to select.</value>
</data>
<data name="DeletionDate" xml:space="preserve">
<value>মুছে ফেলার তারিখ</value>
<value>Deletion date</value>
</data>
<data name="DeletionTime" xml:space="preserve">
<value>Deletion time</value>
@@ -1957,7 +1957,7 @@ Scanning will happen automatically.</value>
<value>Current access count</value>
</data>
<data name="NewPassword" xml:space="preserve">
<value>নতুন পাসওয়ার্ড</value>
<value>New password</value>
</data>
<data name="PasswordInfo" xml:space="preserve">
<value>Optionally require a password for users to access this Send.</value>
@@ -2030,19 +2030,19 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="OneDay" xml:space="preserve">
<value>১ দিন</value>
<value>1 day</value>
</data>
<data name="TwoDays" xml:space="preserve">
<value>২ দিন</value>
<value>2 days</value>
</data>
<data name="ThreeDays" xml:space="preserve">
<value>3 days</value>
</data>
<data name="SevenDays" xml:space="preserve">
<value> দিন</value>
<value>7 days</value>
</data>
<data name="ThirtyDays" xml:space="preserve">
<value>৩০ দিন</value>
<value>30 days</value>
</data>
<data name="Custom" xml:space="preserve">
<value>Custom</value>
@@ -2240,16 +2240,16 @@ Scanning will happen automatically.</value>
<value>Options are collapsed, tap to expand.</value>
</data>
<data name="UppercaseAtoZ" xml:space="preserve">
<value>বড় হাতের অক্ষর (A-Z)</value>
<value>Uppercase (A to Z)</value>
</data>
<data name="LowercaseAtoZ" xml:space="preserve">
<value>Lowercase (A to Z)</value>
</data>
<data name="NumbersZeroToNine" xml:space="preserve">
<value>সংখ্যা (0-9)</value>
<value>Numbers (0 to 9)</value>
</data>
<data name="SpecialCharacters" xml:space="preserve">
<value>বিশেষ অক্ষর (!@#$%^&amp;*)</value>
<value>Special characters (!@#$%^&amp;*)</value>
</data>
<data name="TapToGoBack" xml:space="preserve">
<value>Tap to go back</value>
@@ -2352,10 +2352,10 @@ select Add TOTP to store the key safely</value>
<value>Deny login</value>
</data>
<data name="JustNow" xml:space="preserve">
<value>এইমাত্র</value>
<value>Just now</value>
</data>
<data name="XMinutesAgo" xml:space="preserve">
<value>{0} মিনিট আগে</value>
<value>{0} minutes ago</value>
</data>
<data name="LogInAccepted" xml:space="preserve">
<value>Login confirmed</value>
@@ -2548,7 +2548,7 @@ Do you want to switch to this account?</value>
<value>Enable camera permission to use the scanner</value>
</data>
<data name="Language" xml:space="preserve">
<value>ভাষা</value>
<value>Language</value>
</data>
<data name="LanguageChangeXDescription" xml:space="preserve">
<value>The language has been changed to {0}. Please restart the app to see the change</value>
@@ -2575,10 +2575,10 @@ Do you want to switch to this account?</value>
<value>Weak</value>
</data>
<data name="Good" xml:space="preserve">
<value>ভালো</value>
<value>Good</value>
</data>
<data name="Strong" xml:space="preserve">
<value>শক্তিশালী</value>
<value>Strong</value>
</data>
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
<value>Check known data breaches for this password</value>

View File

@@ -1753,7 +1753,7 @@ Das Scannen erfolgt automatisch.</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Das Entsperren über Biometrie ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde.</value>
<value>Biometrie zum Entsperren ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Das Entsperren von Auto-Ausfüllen über Biometrie ist für dieses Konto deaktiviert, bis das Master-Passwort verifiziert wurde.</value>

View File

@@ -1753,10 +1753,10 @@
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Το βιομετρικό ξεκλείδωμα για αυτόν τον λογαριασμό είναι απενεργοποιημένο εν αναμονή της επαλήθευσης του κύριου κωδικού πρόσβασης.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Το βιομετρικό ξεκλείδωμα αυτόματης συμπλήρωσης για αυτό το λογαριασμό είναι απενεργοποιημένο εν αναμονή της επαλήθευσης του κύριου κωδικού πρόσβασης.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Ενεργοποίηση συγχρονισμού κατά την ανανέωση</value>
@@ -2143,10 +2143,10 @@
<value>Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο vault σας. Το μέγιστο επιτρεπόμενο Χρονικό όριο Vault είναι {0} ώρα(ες) και {1} λεπτό(ά)</value>
</data>
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
<value>Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο του vault σας. Το μέγιστο επιτρεπόμενο χρονικό όριο vault είναι {0} ώρα(ες) και {1} λεπτό(ά). Το χρονικό όριο του vault σας έχει οριστεί σε {2}.</value>
<value>Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}.</value>
</data>
<data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve">
<value>Οι πολιτικές του οργανισμού σας έχουν ορίσει την ενέργεια χρονικού ορίου vault σε {0}.</value>
<value>Your organization policies have set your vault timeout action to {0}.</value>
</data>
<data name="VaultTimeoutToLarge" xml:space="preserve">
<value>Το χρονικό όριο του vault σας υπερβαίνει τους περιορισμούς που έχει ορίσει ο οργανισμός σας.</value>
@@ -2610,9 +2610,9 @@
<value>Δεν υπάρχουν στοιχεία που να ταιριάζουν με την αναζήτηση</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Ο κύριος κωδικός πρόσβασής σας δεν πληροί μία ή περισσότερες πολιτικές του οργανισμού σας. Για να αποκτήσετε πρόσβαση στο Vault σας, πρέπει να ενημερώσετε τον κύριο κωδικό πρόσβασής σας τώρα. Η διαδικασία θα σας αποσυνδέσει από την τρέχουσα συνεδρία σας, απαιτώντας από εσάς να συνδεθείτε ξανά. Οι ενεργές συνεδρίες σε άλλες συσκευές ενδέχεται να συνεχίσουν να είναι ενεργές εώς και μία ώρα.</value>
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>Τρέχων κύριος κωδικός</value>
<value>Current master password</value>
</data>
</root>

View File

@@ -1753,10 +1753,10 @@
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>باز کردن قفل بیومتریک برای این حساب کاربری در انتظار تأیید کلمه عبور اصلی غیرفعال است.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>باز کردن قفل پر کردن خودکار بیومتریک برای این حساب کاربری در انتظار تأیید کلمه عبور اصلی غیرفعال است.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>فعال کردن همگام‌سازی در نوسازی</value>
@@ -2144,10 +2144,10 @@
<value>سیاست‌های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می‌گذارد. حداکثر زمان مجاز گاوصندوق {0} ساعت و {1} دقیقه است</value>
</data>
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
<value>سیاست‌های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می‌گذارد. حداکثر زمان مجاز گاوصندوق {0} ساعت و {1} دقیقه است. عملگر مهلت زمانی گاوصندوق شما روی {2} تنظیم شده است.</value>
<value>Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}.</value>
</data>
<data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve">
<value>سباست‌های سازمان شما، عملگر زمان‌بندی گاوصندوق شما را روی {0} تنظیم کرده است.</value>
<value>Your organization policies have set your vault timeout action to {0}.</value>
</data>
<data name="VaultTimeoutToLarge" xml:space="preserve">
<value>مهلت زمانی شما بیش از محدودیت های تعیین شده توسط سازمانتان است.</value>
@@ -2611,9 +2611,9 @@
<value>هیچ موردی وجود ندارد که با جستجو مطابقت داشته باشد</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>کلمه عبور اصلی شما با یک یا چند سیاست سازمان‌تان مطابقت ندارد. برای دسترسی به گاوصندوق، باید همین حالا کلمه عبور اصلی خود را به‌روز کنید. در صورت ادامه، شما از نشست فعلی خود خارج می‌شوید و باید دوباره وارد سیستم شوید. نشست فعال در دستگاه های دیگر ممکن است تا یک ساعت همچنان فعال باقی بمانند.</value>
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>کلمه عبور اصلی فعلی</value>
<value>Current master password</value>
</data>
</root>

View File

@@ -1753,10 +1753,10 @@ Koodi luetaan automaattisesti.</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Biometrinen avaus on poistettu käytöstä tältä tililtä, kunnes pääsalasana on vahvistettu.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Automaattisen täytön biometrinen avaus on poistettu käytöstä tältä tililtä, kunnes pääsalasana on vahvistettu.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Synkronoi holvi päivityksen yhteydessä</value>
@@ -2602,7 +2602,7 @@ Haluatko vaihtaa tähän tiliin?</value>
<value>Lisää avain olemassa olevaan tai uuteen kohteeseen</value>
</data>
<data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve">
<value>Holvissasi ei ole kohdetta "{0}" vastavia tietoja</value>
<value>Holvissasi ei ole kohteita osoitteelle "{0}"</value>
</data>
<data name="SearchForAnItemOrAddANewItem" xml:space="preserve">
<value>Etsi kohdetta tai lisää uusi kohde</value>

View File

@@ -1753,10 +1753,10 @@ La numérisation se fera automatiquement.</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Le déverrouillage biométrique pour ce compte est désactivé en attente de vérification du mot de passe maître.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Le déverrouillage biométrique de saisie automatique pour ce compte est désactivé en attente de vérification du mot de passe maître.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Autoriser la synchronisation au rafraîchissement</value>

View File

@@ -118,14 +118,14 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="About" xml:space="preserve">
<value>हमारे बारे में</value>
<value>बारे में</value>
</data>
<data name="Add" xml:space="preserve">
<value>जोड़ें</value>
<comment>Add/create a new entity (verb).</comment>
</data>
<data name="AddFolder" xml:space="preserve">
<value>फोल्डर जोड़ें</value>
<value>नया फोल्डर जोड़ें</value>
</data>
<data name="AddItem" xml:space="preserve">
<value>चीज़ जोड़ें</value>
@@ -136,11 +136,11 @@
<comment>Alert title when something goes wrong.</comment>
</data>
<data name="Back" xml:space="preserve">
<value>पीछे जाएं</value>
<value>वापस जाएं</value>
<comment>Navigate back to the previous screen.</comment>
</data>
<data name="Bitwarden" xml:space="preserve">
<value>बिटवार्डन</value>
<value>bitwarden</value>
<comment>App name. Shouldn't ever change.</comment>
</data>
<data name="Cancel" xml:space="preserve">
@@ -156,105 +156,105 @@
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
</data>
<data name="CopyUsername" xml:space="preserve">
<value>यूज़रनाम कॉपी करें</value>
<value>उपयोगकर्ता नाम की प्रतिलिपि बनाएँ</value>
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data>
<data name="Credits" xml:space="preserve">
<value>क्रेडिट</value>
<value>क्रेडिट्स</value>
<comment>Title for page that we use to give credit to resources that we use.</comment>
</data>
<data name="Delete" xml:space="preserve">
<value>मिटाए</value>
<value>मिटाए</value>
<comment>Delete an entity (verb).</comment>
</data>
<data name="Deleting" xml:space="preserve">
<value>मिटाया जा रहा हैं...</value>
<value>मिटाया जा रहा हैं</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>क्मिटाएं? इसे अंडू नहीं किया जा सकता</value>
<value>क्आप वास्तव में हटाना चाहते हैं? इसे नष्ट नहीं किया जा सकता है</value>
<comment>Confirmation alert message when deleteing something.</comment>
</data>
<data name="Edit" xml:space="preserve">
<value>बदलाव करें</value>
<value>संशोधन करें</value>
</data>
<data name="EditFolder" xml:space="preserve">
<value>फोल्डर बदलाव करें</value>
<value>फोल्डर संपादित करें</value>
</data>
<data name="Email" xml:space="preserve">
<value>ईमेल</value>
<comment>Short label for an email address.</comment>
</data>
<data name="EmailAddress" xml:space="preserve">
<value>ईमेल पता</value>
<value>ई-मेल पता</value>
<comment>Full label for a email address.</comment>
</data>
<data name="EmailUs" xml:space="preserve">
<value>हमें ईमेल करें</value>
</data>
<data name="EmailUsDescription" xml:space="preserve">
<value>मदद लेने या फीडबैक देने के लिए हमें ईमेल करें।</value>
<value>सहायता प्राप्त करने या प्रतिक्रिया छोड़ने के लिए हमें ईमेल करें।</value>
</data>
<data name="EnterPIN" xml:space="preserve">
<value>अपना पिन कोड डालें</value>
<value>अपना पिन डालें</value>
</data>
<data name="Favorites" xml:space="preserve">
<value>मनपसंद</value>
<value>पसंदीदा</value>
<comment>Title for your favorite items in the vault.</comment>
</data>
<data name="FileBugReport" xml:space="preserve">
<value>बग रिपोर्ट भेजें</value>
<value>बग रिपोर्ट दर्ज करें</value>
</data>
<data name="FileBugReportDescription" xml:space="preserve">
<value>हमारे गिटहब रिपॉज़िटरी में समस्या बताएं।</value>
<value>हमारे GitHub भंडार में एक मुद्दे को बताएं।</value>
</data>
<data name="FingerprintDirection" xml:space="preserve">
<value>फिंगरप्रिंट से सत्यापन करें</value>
<value>फिंगरप्रिंट से सत्यापन करें</value>
</data>
<data name="Folder" xml:space="preserve">
<value>फोल्डर</value>
<value>फोल्डर</value>
<comment>Label for a folder.</comment>
</data>
<data name="FolderCreated" xml:space="preserve">
<value>नया फोल्डर बनाया गया</value>
<value>नया फोल्डर बनाया गया</value>
</data>
<data name="FolderDeleted" xml:space="preserve">
<value>फोल्डर मिटाया गया।</value>
<value>फोल्डर को हटाया</value>
</data>
<data name="FolderNone" xml:space="preserve">
<value>कोई फोल्डर नहीं है</value>
<value>कोई फोल्डर नहीं है</value>
<comment>Items that have no folder specified go in this special "catch-all" folder.</comment>
</data>
<data name="Folders" xml:space="preserve">
<value>फोल्डर</value>
<value>फोल्डर्स</value>
</data>
<data name="FolderUpdated" xml:space="preserve">
<value>फोल्डर सेव हुआ</value>
<value>फोल्डर अद्यतन हुआ</value>
</data>
<data name="GoToWebsite" xml:space="preserve">
<value>वेबसाइट पर जाए</value>
<value>वेबसाइट पर जाए</value>
<comment>The button text that allows user to launch the website to their web browser.</comment>
</data>
<data name="HelpAndFeedback" xml:space="preserve">
<value>मदद और फीडबैक</value>
<value>सहायता और सुझाव</value>
</data>
<data name="Hide" xml:space="preserve">
<value>छुपां</value>
<value>छुपायें</value>
<comment>Hide a secret value that is currently shown (password).</comment>
</data>
<data name="InternetConnectionRequiredMessage" xml:space="preserve">
<value>जारी रखने से पहले इंटरनेट से जुड़े।</value>
<value>जारी रखने से पहले कृपया इंटरनेट से जुड़े।</value>
<comment>Description message for the alert when internet connection is required to continue.</comment>
</data>
<data name="InternetConnectionRequiredTitle" xml:space="preserve">
<value>इंटरनेट कनेक्शन चाहिए</value>
<value>इंटरनेट से जुड़िए</value>
<comment>Title for the alert when internet connection is required to continue.</comment>
</data>
<data name="InvalidMasterPassword" xml:space="preserve">
<value>मुख्य पासवर्ड गलत है। वापस कोशिश करें।</value>
<value>मास्टर पासवर्ड गलत है। फिर कोशिश करें।</value>
</data>
<data name="InvalidPIN" xml:space="preserve">
<value>पिन गलत है। वापस कोशिश करें।</value>
<value>पिन गलत है। फिर कोशिश करें।</value>
</data>
<data name="Launch" xml:space="preserve">
<value>खोलें</value>
@@ -269,38 +269,38 @@
<comment>Title for login page. (noun)</comment>
</data>
<data name="LogOut" xml:space="preserve">
<value>लॉग आउट करें</value>
<value>लॉग आउट</value>
<comment>The log out button text (verb).</comment>
</data>
<data name="LogoutConfirmation" xml:space="preserve">
<value>क्का लॉग आउट करं?</value>
<value>क्या आप वाकई लॉग आउट करना चाहते हैं?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>खाता हटाएं</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>क्का खाता हटाएं?</value>
<value>क्या आप वाकई यह खाता हटाना चाहते हैं?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>खाता पहले से जोड़ा गया</value>
<value>Account already added</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>अभी खाता इस्तेमाल करें?</value>
<value>Would you like to switch to it now?</value>
</data>
<data name="MasterPassword" xml:space="preserve">
<value>मुख्य पासवर्ड</value>
<value>मास्टर / मुख्य पासवर्ड</value>
<comment>Label for a master password.</comment>
</data>
<data name="More" xml:space="preserve">
<value>और</value>
<value>अतिरिक्त</value>
<comment>Text to define that there are more options things to see.</comment>
</data>
<data name="MyVault" xml:space="preserve">
<value>मेर तिजोरी</value>
<value>मेर तिजोरी</value>
<comment>The title for the vault page.</comment>
</data>
<data name="Authenticator" xml:space="preserve">
<value>सत्यापन करनेवाला</value>
<value>Authenticator</value>
<comment>Authenticator TOTP feature</comment>
</data>
<data name="Name" xml:space="preserve">
@@ -311,11 +311,11 @@
<value>नहीं</value>
</data>
<data name="Notes" xml:space="preserve">
<value>नोट</value>
<value>टिप्पणियाँ</value>
<comment>Label for notes.</comment>
</data>
<data name="Ok" xml:space="preserve">
<value>ठीक है</value>
<value>ठीक</value>
<comment>Acknowledgement.</comment>
</data>
<data name="Password" xml:space="preserve">
@@ -323,69 +323,69 @@
<comment>Label for a password.</comment>
</data>
<data name="Save" xml:space="preserve">
<value>सेव करें</value>
<value>सहेजें</value>
<comment>Button text for a save operation (verb).</comment>
</data>
<data name="Move" xml:space="preserve">
<value>ले जाएं</value>
<value>Move</value>
</data>
<data name="Saving" xml:space="preserve">
<value>सेव हो रहा है...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Settings" xml:space="preserve">
<value>सेटिंग</value>
<value>सेटिंग्स</value>
<comment>The title for the settings page.</comment>
</data>
<data name="Show" xml:space="preserve">
<value>दिखाए</value>
<value>दिखाए</value>
<comment>Reveal a hidden value (password).</comment>
</data>
<data name="ItemDeleted" xml:space="preserve">
<value>चीज़ मिटाया गया।</value>
<value>आइटम हटा दिया गया है।</value>
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
<value>जमा करें</value>
</data>
<data name="Sync" xml:space="preserve">
<value>सिंक</value>
<value>संकालन</value>
<comment>The title for the sync page.</comment>
</data>
<data name="ThankYou" xml:space="preserve">
<value>शुक्रिया</value>
<value>धन्यवाद</value>
</data>
<data name="Tools" xml:space="preserve">
<value>औज़ार</value>
<value>उपकरण</value>
<comment>The title for the tools page.</comment>
</data>
<data name="URI" xml:space="preserve">
<value>यूआरआई</value>
<value>URI</value>
<comment>Label for a uri/url.</comment>
</data>
<data name="UseFingerprintToUnlock" xml:space="preserve">
<value>फिंगरप्रिंट से खोलें</value>
<value>अंगुलिछाप से खोलें</value>
</data>
<data name="Username" xml:space="preserve">
<value>यूज़रनाम</value>
<value>उपयोगकर्ता नाम:</value>
<comment>Label for a username.</comment>
</data>
<data name="ValidationFieldRequired" xml:space="preserve">
<value>{0} फील्ड चाहिए।</value>
<value>{0} की आश्यकता है।</value>
<comment>Validation message for when a form field is left blank and is required to be entered.</comment>
</data>
<data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} कॉपी किया</value>
<value>{0} कॉपी कर लिया गया है।</value>
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data>
<data name="VerifyFingerprint" xml:space="preserve">
<value>फिंगरप्रिंट सत्यापित करें</value>
<value>अंगुलिछाप दें</value>
</data>
<data name="VerifyMasterPassword" xml:space="preserve">
<value>मुख्य पासवर्ड सत्यापित करें</value>
<value>मास्टर पासवर्ड बताएं।</value>
</data>
<data name="VerifyPIN" xml:space="preserve">
<value>पिन सत्यापित करें।</value>
<value>पिन बताएं।</value>
</data>
<data name="Version" xml:space="preserve">
<value>संस्करण</value>
@@ -394,29 +394,29 @@
<value>देखें</value>
</data>
<data name="VisitOurWebsite" xml:space="preserve">
<value>हमारी वेबसाइट पर जाए</value>
<value>हमारी वेबसाइट पर जाए</value>
</data>
<data name="VisitOurWebsiteDescription" xml:space="preserve">
<value>मदद लेने, खबर लेने, हमें ईमेल करने, और/या बिटवार्डन के इस्तेमाल के बारे में ज़्यादा जानने के लिए हमारी वेबसाइट पर जाएं।</value>
<value>Visit our website to get help, news, email us, and/or learn more about how to use bitwarden.</value>
</data>
<data name="Website" xml:space="preserve">
<value>वेबसाइट</value>
<comment>Label for a website.</comment>
</data>
<data name="Yes" xml:space="preserve">
<value>हा</value>
<value>हा</value>
</data>
<data name="Account" xml:space="preserve">
<value>खाता</value>
</data>
<data name="AccountCreated" xml:space="preserve">
<value>आपका नया खाता बनाया गया! अब आप लॉग न कर सकते हैं।</value>
<value>अपना नया खाता बनाया गया है! अब आप लॉग न कर सकते हैं।</value>
</data>
<data name="AddAnItem" xml:space="preserve">
<value>चीज़ जोड़ें</value>
<value>आइटम जोड़ें</value>
</data>
<data name="AppExtension" xml:space="preserve">
<value>ऐप एक्सटेंशन</value>
<value>ऐप का विस्तारण</value>
</data>
<data name="AutofillAccessibilityDescription" xml:space="preserve">
<value>Use the bitwarden accessibility service to auto-fill your logins across apps and the web.</value>
@@ -776,10 +776,10 @@
<value>सक्षम</value>
</data>
<data name="Off" xml:space="preserve">
<value>बंद</value>
<value>Off</value>
</data>
<data name="On" xml:space="preserve">
<value>चालू</value>
<value>On</value>
</data>
<data name="Status" xml:space="preserve">
<value>स्थिति</value>
@@ -1096,16 +1096,16 @@ Scanning will happen automatically.</value>
<value>मध्य नाम</value>
</data>
<data name="Mr" xml:space="preserve">
<value>श्री</value>
<value>Mr</value>
</data>
<data name="Mrs" xml:space="preserve">
<value>श्रीमती</value>
<value>Mrs</value>
</data>
<data name="Ms" xml:space="preserve">
<value>श्रीमती</value>
<value>Ms</value>
</data>
<data name="Mx" xml:space="preserve">
<value>मैक्स</value>
<value>Mx</value>
</data>
<data name="November" xml:space="preserve">
<value>नवंबर</value>
@@ -2274,7 +2274,7 @@ Scanning will happen automatically.</value>
<value>Vault: {0}</value>
</data>
<data name="All" xml:space="preserve">
<value>सब</value>
<value>All</value>
</data>
<data name="Totp" xml:space="preserve">
<value>TOTP</value>
@@ -2365,13 +2365,13 @@ select Add TOTP to store the key safely</value>
<value>Login denied</value>
</data>
<data name="ApproveLoginRequests" xml:space="preserve">
<value>लॉगइन मांग माने</value>
<value>Approve login requests</value>
</data>
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
<value>Use this device to approve login requests made from other devices.</value>
</data>
<data name="AllowNotifications" xml:space="preserve">
<value>सूचना देने दें</value>
<value>Allow notifications</value>
</data>
<data name="ReceivePushNotificationsForNewLoginRequests" xml:space="preserve">
<value>Receive push notifications for new login requests</value>
@@ -2522,99 +2522,99 @@ Do you want to switch to this account?</value>
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>दूसरा ऑप्शन चाहिए?</value>
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>ऑप्शन में सारे लॉग देखें</value>
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>ये मांग अब मान्य नहीं है</value>
<value>This request is no longer valid</value>
</data>
<data name="PendingLogInRequests" xml:space="preserve">
<value>लंबित लॉगइन मांगे</value>
<value>Pending login requests</value>
</data>
<data name="DeclineAllRequests" xml:space="preserve">
<value>सारे मांग नकारे</value>
<value>Decline all requests</value>
</data>
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
<value>सारे लंबित लॉगइन मांग पक्का नकारें?</value>
<value>Are you sure you want to decline all pending login requests?</value>
</data>
<data name="RequestsDeclined" xml:space="preserve">
<value>मांग नकारे गए</value>
<value>Requests declined</value>
</data>
<data name="NoPendingRequests" xml:space="preserve">
<value>कोई लंबित मांग नहीं</value>
<value>No pending requests</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>स्कैनर इस्तेमाल करने के लिए कैमरा अनुमति दें</value>
<value>Enable camera permission to use the scanner</value>
</data>
<data name="Language" xml:space="preserve">
<value>भाषा</value>
<value>Language</value>
</data>
<data name="LanguageChangeXDescription" xml:space="preserve">
<value>भाषा {0} में बदली गई। बदलाव देखने के लिए ऐप बंद करके वापस खोलें।</value>
<value>The language has been changed to {0}. Please restart the app to see the change</value>
</data>
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
<value>भाषा बदलाव के लिए ऐप बंद करके खोलना पड़ेगा</value>
<value>Language change requires app restart</value>
</data>
<data name="DefaultSystem" xml:space="preserve">
<value>डिफॉल्ट (सिस्टम)</value>
<value>Default (System)</value>
</data>
<data name="Important" xml:space="preserve">
<value>ज़रूरी</value>
<value>Important</value>
</data>
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
<value>आप अपना मुख्य पासवर्ड भूलने के बाद वापस नहीं ले सकते। {0} अक्षर कम-से-कम।</value>
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
</data>
<data name="WeakMasterPassword" xml:space="preserve">
<value>कमज़ोर मुख्य पासवर्ड</value>
<value>Weak Master Password</value>
</data>
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
<value>पासवर्ड कमज़ोर है। अपना खाता महफूज़ रखने के लिए एक ताकतवर पासवर्ड इस्तेमाल करें। कमज़ोर पासवर्ड पक्का इस्तेमाल करें?</value>
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
</data>
<data name="Weak" xml:space="preserve">
<value>कमज़ोर</value>
<value>Weak</value>
</data>
<data name="Good" xml:space="preserve">
<value>अच्छा</value>
<value>Good</value>
</data>
<data name="Strong" xml:space="preserve">
<value>ताकतवर</value>
<value>Strong</value>
</data>
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
<value>पुराने डाटा लीक में इस पासवर्ड को खोजें</value>
<value>Check known data breaches for this password</value>
</data>
<data name="ExposedMasterPassword" xml:space="preserve">
<value>मुख्य पासवर्ड लीक हुआ था</value>
<value>Exposed Master Password</value>
</data>
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
<value>पासवर्ड एक डाटा लीक में मिला। अपना खाता महफूज़ रखने के लिए एक खास पासवर्ड इस्तेमाल करें। लीक हुआ पासवर्ड इस्तेमाल करें?</value>
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
</data>
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
<value>कमज़ोर और लीक हुआ मुख्य पासवर्ड</value>
<value>Weak and Exposed Master Password</value>
</data>
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
<value>पासवर्ड कमज़ोर है और एक डाटा लीक में मिला। अपना खाता महफूज़ रखने के लिए एक ताकतवर और खास पासवर्ड इस्तेमाल करें। ये पासवर्ड पक्का इस्तेमाल करें?</value>
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
</data>
<data name="OrganizationSsoIdentifierRequired" xml:space="preserve">
<value>संगठन एसएसओ पहचान चाहिए।</value>
<value>Organization SSO identifier required.</value>
</data>
<data name="AddTheKeyToAnExistingOrNewItem" xml:space="preserve">
<value>चाबी एक मौजूदा या नए चीज़ में जोड़ें</value>
<value>Add the key to an existing or new item</value>
</data>
<data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve">
<value>आपके तिजोरी में ऐसी कोई भी चीज़ नहीं है जो "{0}" से मेल खाती है</value>
<value>There are no items in your vault that match "{0}"</value>
</data>
<data name="SearchForAnItemOrAddANewItem" xml:space="preserve">
<value>चीज़ खोजें या नया चीज़ जोड़ें</value>
<value>Search for an item or add a new item</value>
</data>
<data name="ThereAreNoItemsThatMatchTheSearch" xml:space="preserve">
<value>कोई भी चीज़ खोज शब्द से मेल नहीं खाता</value>
<value>There are no items that match the search</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>आपका मुख्य पासवर्ड आपके संगठन के एक या उससे ज़्यादा नीति को नहीं मानता। तिजोरी एक्सेस करने के लिए आपको अपना मुख्य पासवर्ड अभी बदलना होगा। ये करने से आप अपने चालू सत्र से लॉग आउट हो जाएंगे, जिसके वजह से आपको वापस लॉग इन करना पड़ेगा। दूसरे डिवाइसों पर चालू सत्र एक घंटे तक सक्रिय रह सकते हैं।</value>
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>चालू मुख्य पासवर्ड</value>
<value>Current master password</value>
</data>
</root>

View File

@@ -2496,8 +2496,8 @@ Do you want to switch to this account?</value>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsXOnY" xml:space="preserve">
<value>Logging in as {0} on {1}</value>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
@@ -2610,28 +2610,10 @@ Do you want to switch to this account?</value>
<data name="ThereAreNoItemsThatMatchTheSearch" xml:space="preserve">
<value>There are no items that match the search</value>
</data>
<data name="US" xml:space="preserve">
<value>US</value>
</data>
<data name="EU" xml:space="preserve">
<value>EU</value>
</data>
<data name="SelfHosted" xml:space="preserve">
<value>Self-hosted</value>
</data>
<data name="DataRegion" xml:space="preserve">
<value>Data region</value>
</data>
<data name="Region" xml:space="preserve">
<value>Region</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>Current master password</value>
</data>
<data name="UploadHasBeenCanceled" xml:space="preserve">
<value>Upload has been canceled</value>
</data>
</root>

View File

@@ -1753,10 +1753,10 @@ Scanarea se va face automat.</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Deblocarea biometrică pentru acest cont este dezactivată în așteptarea verificării parolei principale.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Completarea automată a deblocării biometrice pentru acest cont este dezactivată în așteptarea verificării parolei principale.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Activare sincronizare la reîmprospătare</value>

View File

@@ -269,7 +269,7 @@
<comment>Title for login page. (noun)</comment>
</data>
<data name="LogOut" xml:space="preserve">
<value>Odjavi se</value>
<value>Izpiši se</value>
<comment>The log out button text (verb).</comment>
</data>
<data name="LogoutConfirmation" xml:space="preserve">
@@ -296,7 +296,7 @@
<comment>Text to define that there are more options things to see.</comment>
</data>
<data name="MyVault" xml:space="preserve">
<value>Moj trezor</value>
<value>Moj sef</value>
<comment>The title for the vault page.</comment>
</data>
<data name="Authenticator" xml:space="preserve">
@@ -342,7 +342,7 @@
<comment>Reveal a hidden value (password).</comment>
</data>
<data name="ItemDeleted" xml:space="preserve">
<value>Element je bil izbrisan.</value>
<value>Vnos je bil izbrisan.</value>
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
@@ -413,7 +413,7 @@
<value>Vas novi račun je bil ustvarjen! Lahko se vpišete. </value>
</data>
<data name="AddAnItem" xml:space="preserve">
<value>Dodaj Element</value>
<value>Dodaj vnos</value>
</data>
<data name="AppExtension" xml:space="preserve">
<value>Razširitev aplikacije</value>
@@ -425,7 +425,7 @@
<value>Storitev samodejnega izpolnjevanja</value>
</data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Brez dvoumnih znakov</value>
<value>Izogib dvoumnih znakov</value>
</data>
<data name="BitwardenAppExtension" xml:space="preserve">
<value>Razširitev aplikacije Bitwarden</value>
@@ -468,7 +468,7 @@
<comment>Message shown when interacting with the server</comment>
</data>
<data name="EditItem" xml:space="preserve">
<value>Uredi element</value>
<value>Uredi vnos</value>
</data>
<data name="EnableAutomaticSyncing" xml:space="preserve">
<value>Omogoči samodejno sinhronizacijo</value>
@@ -514,13 +514,13 @@
<value>Prstni odtis </value>
</data>
<data name="GeneratePassword" xml:space="preserve">
<value>Generiraj geslo</value>
<value>Ustvari geslo</value>
</data>
<data name="GetPasswordHint" xml:space="preserve">
<value>Pridobi namig za glavno geslo</value>
</data>
<data name="ImportItems" xml:space="preserve">
<value>Uvozi elemente</value>
<value>Uvozi zapise</value>
</data>
<data name="ImportItemsConfirmation" xml:space="preserve">
<value>You can bulk import items from the bitwarden.com web vault. Do you want to visit the website now?</value>
@@ -566,7 +566,7 @@
<comment>Message shown when interacting with the server</comment>
</data>
<data name="LoginOrCreateNewAccount" xml:space="preserve">
<value>Prijavite se ali ustvarite nov račun za dostop do trezorja.</value>
<value>Vpišite se ali ustvarite nov račun za dostop do sefa.</value>
</data>
<data name="Manage" xml:space="preserve">
<value>Upravljaj</value>
@@ -584,7 +584,7 @@
<value>Namig glavnega gesla se vam lahko pomaga spomniti geslo, v kolikor bi ga pozabili.</value>
</data>
<data name="MasterPasswordLengthValMessageX" xml:space="preserve">
<value>Glavno geslo mora vsebovati vsaj {0} znakov.</value>
<value>Master password must be at least {0} characters long.</value>
</data>
<data name="MinNumbers" xml:space="preserve">
<value>Minimalno števil</value>
@@ -604,13 +604,13 @@
<value>Nikoli</value>
</data>
<data name="NewItemCreated" xml:space="preserve">
<value>Nov element ustvarjen.</value>
<value>Nov vnos ustvarjen.</value>
</data>
<data name="NoFavorites" xml:space="preserve">
<value>V vašem trezorju ni priljubljenih elementov. </value>
<value>V vašem sefu ni priljubljenih vnosov. </value>
</data>
<data name="NoItems" xml:space="preserve">
<value>V vašem trezorju ni elementov. </value>
<value>V vašem sefu ni vnosov. </value>
</data>
<data name="NoItemsTap" xml:space="preserve">
<value>There are no items in your vault for this website/app. Tap to add one.</value>
@@ -632,7 +632,7 @@
<value>Drugo</value>
</data>
<data name="PasswordGenerated" xml:space="preserve">
<value>Geslo generirano.</value>
<value>Geslo ustvarjeno.</value>
</data>
<data name="PasswordGenerator" xml:space="preserve">
<value>Ustvarjalnik gesel</value>
@@ -678,24 +678,24 @@
<value>Vnesite 4 mestno PIN številko za odklep aplikacije.</value>
</data>
<data name="ItemInformation" xml:space="preserve">
<value>Informacije o elementu</value>
<value>Informacije o vnosu</value>
</data>
<data name="ItemUpdated" xml:space="preserve">
<value>Element shranjen.</value>
<value>Vnos je posodobljen.</value>
</data>
<data name="Submitting" xml:space="preserve">
<value>Pošiljanje...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Syncing" xml:space="preserve">
<value>Sinhroniziram...</value>
<value>Sinhronizacija...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="SyncingComplete" xml:space="preserve">
<value>Sinhronizacija končana.</value>
</data>
<data name="SyncingFailed" xml:space="preserve">
<value>Sinhronizacija spodletela.</value>
<value>Sinhronizacija neuspešna.</value>
</data>
<data name="SyncVaultNow" xml:space="preserve">
<value>Sinhroniziraj trezor zdaj</value>
@@ -714,7 +714,7 @@
<value>Odkleni z {0}</value>
</data>
<data name="UnlockWithPIN" xml:space="preserve">
<value>Odkleni s PIN kodo</value>
<value>Odklepanje s PIN kodo</value>
</data>
<data name="Validating" xml:space="preserve">
<value>Preverjanje veljavnosti</value>
@@ -724,16 +724,16 @@
<value>Verifikacijska koda</value>
</data>
<data name="ViewItem" xml:space="preserve">
<value>Prikaži element</value>
<value>Ogled vnosa</value>
</data>
<data name="WebVault" xml:space="preserve">
<value>Spletni trezor Bitwarden</value>
<value>Bitwarden spletni sef </value>
</data>
<data name="Lost2FAApp" xml:space="preserve">
<value>Izgubili aplikacijo za avtentikacijo? </value>
</data>
<data name="Items" xml:space="preserve">
<value>Elementi</value>
<value>Vnosi</value>
<comment>Screen title</comment>
</data>
<data name="ExtensionActivated" xml:space="preserve">
@@ -746,11 +746,11 @@
<value>Prevodi </value>
</data>
<data name="ItemsForUri" xml:space="preserve">
<value>Elementi za {0}</value>
<value>Vnosov za {0}</value>
<comment>This is used for the autofill service. ex. "Logins for twitter.com"</comment>
</data>
<data name="NoItemsForUri" xml:space="preserve">
<value>V vašem trezorju ni elementov za {0}.</value>
<value>V vašem sefu ni vnosov za {0}.</value>
<comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment>
</data>
<data name="BitwardenAutofillServiceOverlay" xml:space="preserve">
@@ -790,16 +790,16 @@
<value>Samodejno izpolnjevanje</value>
</data>
<data name="AutofillOrView" xml:space="preserve">
<value>Želite samodejno izpolniti ali prikazati ta element?</value>
<value>Želite samodejno izpolniti ali videti ta vnos?</value>
</data>
<data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve">
<value>Ali ste prepričani, da želite samodejno izpolniti ta element? Ujemanje ni popolno za "{0}".</value>
</data>
<data name="MatchingItems" xml:space="preserve">
<value>Ujemajoči elementi</value>
<value>Ujemajoči vnosi</value>
</data>
<data name="PossibleMatchingItems" xml:space="preserve">
<value>Možni ujemajoči elementi</value>
<value>Možni ujemajoči vnosi</value>
</data>
<data name="Search" xml:space="preserve">
<value>Iskanje</value>
@@ -1017,7 +1017,7 @@ Scanning will happen automatically.</value>
<value>Prijava</value>
</data>
<data name="TypeSecureNote" xml:space="preserve">
<value>Zavarovan zapisek</value>
<value>Varni zapisek</value>
</data>
<data name="Address1" xml:space="preserve">
<value>Naslov 1</value>
@@ -1140,10 +1140,10 @@ Scanning will happen automatically.</value>
<value>Datum poteka</value>
</data>
<data name="ShowWebsiteIcons" xml:space="preserve">
<value>Prikaži ikone spletnih strani</value>
<value>Show website icons</value>
</data>
<data name="ShowWebsiteIconsDescription" xml:space="preserve">
<value>Pri vsaki prijavi prikaži prepoznavno sliko.</value>
<value>Show a recognizable image next to each login.</value>
</data>
<data name="IconsUrl" xml:space="preserve">
<value>Ikone URL strežnikov</value>
@@ -1161,10 +1161,10 @@ Scanning will happen automatically.</value>
<value>Zbirke</value>
</data>
<data name="NoItemsCollection" xml:space="preserve">
<value>Ta zbirka še nima elementov.</value>
<value>Ta zbirka še nima zapisov.</value>
</data>
<data name="NoItemsFolder" xml:space="preserve">
<value>V tej mapi ni elementov.</value>
<value>V tej mapi ni zapisov.</value>
</data>
<data name="NoItemsTrash" xml:space="preserve">
<value>Koš je prazen.</value>
@@ -1182,7 +1182,7 @@ Scanning will happen automatically.</value>
<value>Nastavitve samodejnega izpolnjevanja</value>
</data>
<data name="FaceID" xml:space="preserve">
<value>obraznim ID</value>
<value>Obrazni ID</value>
<comment>What Apple calls their facial recognition reader.</comment>
</data>
<data name="FaceIDDirection" xml:space="preserve">
@@ -1322,7 +1322,7 @@ Scanning will happen automatically.</value>
<value>5. Select "Bitwarden"</value>
</data>
<data name="PasswordAutofill" xml:space="preserve">
<value>Samodejno izpolnjevanje gesel</value>
<value>Password auto-fill</value>
</data>
<data name="BitwardenAutofillAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen.</value>
@@ -1340,13 +1340,13 @@ Scanning will happen automatically.</value>
<value>Prijave</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>Zavarovani zapiski</value>
<value>Varni zapiski</value>
</data>
<data name="AllItems" xml:space="preserve">
<value>Vsi elementi</value>
</data>
<data name="URIs" xml:space="preserve">
<value>URI-ji</value>
<value>URIs</value>
<comment>Plural form of a URI</comment>
</data>
<data name="CheckingPassword" xml:space="preserve">
@@ -1369,7 +1369,7 @@ Scanning will happen automatically.</value>
<value>Vrednost</value>
</data>
<data name="PasswordHistory" xml:space="preserve">
<value>Zgodovina gesel</value>
<value>Zgodovina gesla</value>
</data>
<data name="Types" xml:space="preserve">
<value>Vrste</value>
@@ -1378,7 +1378,7 @@ Scanning will happen automatically.</value>
<value>Ni gesel za prikazat.</value>
</data>
<data name="NoItemsToList" xml:space="preserve">
<value>Ni elementov za prikaz.</value>
<value>Ni vnosov za prikazat.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Preišči zbirko</value>
@@ -1409,7 +1409,7 @@ Scanning will happen automatically.</value>
<value>Lastništvo</value>
</data>
<data name="WhoOwnsThisItem" xml:space="preserve">
<value>Kdo je lastnik tega elementa?</value>
<value>Kdo je lastnik tega vnosa?</value>
</data>
<data name="NoCollectionsToList" xml:space="preserve">
<value>Ni zbirk za prikazat.</value>
@@ -1419,7 +1419,7 @@ Scanning will happen automatically.</value>
<comment>ex: Item moved to Organization.</comment>
</data>
<data name="ItemShared" xml:space="preserve">
<value>Element je bil dan v skupno rabo.</value>
<value>Vnos je bil deljen.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>Izbrati moraš vsaj eno zbirko.</value>
@@ -1428,10 +1428,10 @@ Scanning will happen automatically.</value>
<value>Deli</value>
</data>
<data name="ShareItem" xml:space="preserve">
<value>Delite element</value>
<value>Delite vnos</value>
</data>
<data name="MoveToOrganization" xml:space="preserve">
<value>Premakni v organizacijo</value>
<value>Move to Organization</value>
</data>
<data name="NoOrgsToList" xml:space="preserve">
<value>Ni organizacij za prikazat.</value>
@@ -1562,7 +1562,7 @@ Scanning will happen automatically.</value>
<value>Kopiraj opombo</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Izhod</value>
<value>Zapri</value>
</data>
<data name="ExitConfirmation" xml:space="preserve">
<value>Ali res želite zapustiti Bitwarden?</value>
@@ -1583,16 +1583,16 @@ Scanning will happen automatically.</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data>
<data name="AutofillBlockedUris" xml:space="preserve">
<value>URI-ji brez samodejnega izpolnjevanja</value>
<value>Auto-fill blocked URIs</value>
</data>
<data name="AutofillBlockedUrisDescription" xml:space="preserve">
<value>Za te URI-je Bitwarden ne bo ponujal samodejnega izpolnjevanja. URI-je ločite z vejicami, n.pr.: "https://twitter.com, androidapp://com.twitter.android".</value>
<value>Auto-fill will not be offered for blocked URIs. Separate multiple URIs with a comma. For example: "https://twitter.com, androidapp://com.twitter.android".</value>
</data>
<data name="AskToAddLogin" xml:space="preserve">
<value>Ponudi shranjevanje prijav</value>
<value>Ask to add login</value>
</data>
<data name="AskToAddLoginDescription" xml:space="preserve">
<value>Ponudi, da se shrani nova prijava, če je v trezorju še ni.</value>
<value>Ask to add an item if one isn't found in your vault.</value>
</data>
<data name="OnRestart" xml:space="preserve">
<value>Ob ponovnem zagonu aplikacije</value>
@@ -1626,7 +1626,7 @@ Scanning will happen automatically.</value>
<value>Biometrična avtentikacija</value>
</data>
<data name="Biometrics" xml:space="preserve">
<value>biometričnim preverjanjem</value>
<value>Biometrično preverjanje</value>
</data>
<data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Uporabi biometrično preverjanje za odklep</value>
@@ -1729,7 +1729,7 @@ Scanning will happen automatically.</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="ItemRestored" xml:space="preserve">
<value>Element je bil obnovljen.</value>
<value>Vnos je bil obnovljen.</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data>
<data name="Trash" xml:space="preserve">
@@ -1745,7 +1745,7 @@ Scanning will happen automatically.</value>
<comment>Confirmation alert message when permanently deleteing a cipher.</comment>
</data>
<data name="DoYouReallyWantToRestoreCipher" xml:space="preserve">
<value>Ali res želite povrniti ta element?</value>
<value>Ali res želite povrniti ta vnos?</value>
<comment>Confirmation alert message when restoring a soft-deleted cipher.</comment>
</data>
<data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve">
@@ -1759,10 +1759,10 @@ Scanning will happen automatically.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Dovoli sihnronizacijo ob osvežitvi</value>
<value>Allow sync on refresh</value>
</data>
<data name="EnableSyncOnRefreshDescription" xml:space="preserve">
<value>Sinhroniziraj ob potegu navzdol</value>
<value>Syncing vault with pull down gesture.</value>
</data>
<data name="LogInSso" xml:space="preserve">
<value>Enterprise single sign-on</value>
@@ -1829,7 +1829,7 @@ Scanning will happen automatically.</value>
<value>Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings</value>
</data>
<data name="AutofillServices" xml:space="preserve">
<value>Storitve samodejnega izpolnjevanja</value>
<value>Auto-fill services</value>
</data>
<data name="InlineAutofill" xml:space="preserve">
<value>Use inline autofill</value>
@@ -1871,7 +1871,7 @@ Scanning will happen automatically.</value>
<value>An organization policy is affecting your ownership options.</value>
</data>
<data name="Send" xml:space="preserve">
<value>Pošiljke</value>
<value>Pošlji</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AllSends" xml:space="preserve">
@@ -1887,23 +1887,23 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="Text" xml:space="preserve">
<value>Besedilo</value>
<value>Text</value>
</data>
<data name="TypeText" xml:space="preserve">
<value>Besedilo</value>
<value>Text</value>
</data>
<data name="TypeTextInfo" xml:space="preserve">
<value>Besedilo, ki ga želite poslati</value>
<value>The text you want to send.</value>
</data>
<data name="HideTextByDefault" xml:space="preserve">
<value>When accessing the Send, hide the text by default</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="TypeFile" xml:space="preserve">
<value>Datoteka</value>
<value>File</value>
</data>
<data name="TypeFileInfo" xml:space="preserve">
<value>Datoteka, ki jo želite poslati</value>
<value>The file you want to send.</value>
</data>
<data name="FileTypeIsSelected" xml:space="preserve">
<value>File type is selected.</value>
@@ -1998,7 +1998,7 @@ Scanning will happen automatically.</value>
<value>Deli povezavo</value>
</data>
<data name="SendLink" xml:space="preserve">
<value>Povezava pošiljke</value>
<value>Pošlji povezavo</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SearchSends" xml:space="preserve">
@@ -2156,22 +2156,22 @@ Scanning will happen automatically.</value>
<value>One or more organization policies prevents your from exporting your individual vault.</value>
</data>
<data name="AddAccount" xml:space="preserve">
<value>Dodaj račun</value>
<value>Add account</value>
</data>
<data name="AccountUnlocked" xml:space="preserve">
<value>Odklenjen</value>
<value>Unlocked</value>
</data>
<data name="AccountLocked" xml:space="preserve">
<value>Zaklenjen</value>
<value>Locked</value>
</data>
<data name="AccountLoggedOut" xml:space="preserve">
<value>Odjavljen</value>
<value>Logged out</value>
</data>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Račun je zaklenjen</value>
<value>Account locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
@@ -2195,7 +2195,7 @@ Scanning will happen automatically.</value>
<value>Vaš račun je bil trajno izbrisan</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Neveljavna koda za preverjanje</value>
<value>Invalid verification code</value>
</data>
<data name="RequestOTP" xml:space="preserve">
<value>Request one-time password</value>
@@ -2228,7 +2228,7 @@ Scanning will happen automatically.</value>
<value>Enter the verification code that was sent to your email</value>
</data>
<data name="SubmitCrashLogs" xml:space="preserve">
<value>Pošlji zapisnike ob sesutju</value>
<value>Submit crash logs</value>
</data>
<data name="SubmitCrashLogsDescription" xml:space="preserve">
<value>Help Bitwarden improve app stability by submitting crash reports.</value>
@@ -2240,16 +2240,16 @@ Scanning will happen automatically.</value>
<value>Options are collapsed, tap to expand.</value>
</data>
<data name="UppercaseAtoZ" xml:space="preserve">
<value>Velike črke (A-Z)</value>
<value>Uppercase (A to Z)</value>
</data>
<data name="LowercaseAtoZ" xml:space="preserve">
<value>Male črke (a-z)</value>
<value>Lowercase (A to Z)</value>
</data>
<data name="NumbersZeroToNine" xml:space="preserve">
<value>Numbers (0 to 9)</value>
</data>
<data name="SpecialCharacters" xml:space="preserve">
<value>Posebni znaki (!@#$%^&amp;*)</value>
<value>Special characters (!@#$%^&amp;*)</value>
</data>
<data name="TapToGoBack" xml:space="preserve">
<value>Tap to go back</value>
@@ -2264,31 +2264,31 @@ Scanning will happen automatically.</value>
<value>Filter items by vault</value>
</data>
<data name="AllVaults" xml:space="preserve">
<value>Vsi trezorji</value>
<value>All vaults</value>
</data>
<data name="Vaults" xml:space="preserve">
<value>Trezorji</value>
<value>Vaults</value>
</data>
<data name="VaultFilterDescription" xml:space="preserve">
<value>Trezor: {0}</value>
<value>Vault: {0}</value>
</data>
<data name="All" xml:space="preserve">
<value>Vsi</value>
<value>All</value>
</data>
<data name="Totp" xml:space="preserve">
<value>TOTP</value>
</data>
<data name="VerificationCodes" xml:space="preserve">
<value>Kode za preverjanje</value>
<value>Verification codes</value>
</data>
<data name="PremiumSubscriptionRequired" xml:space="preserve">
<value>Potrebna je naročnina Premium.</value>
<value>Premium subscription required</value>
</data>
<data name="CannotAddAuthenticatorKey" xml:space="preserve">
<value>Cannot add authenticator key? </value>
</data>
<data name="ScanQRCode" xml:space="preserve">
<value>Skeniraj QR-kodo</value>
<value>Scan QR Code</value>
</data>
<data name="CannotScanQRCode" xml:space="preserve">
<value>Cannot scan QR Code? </value>
@@ -2319,10 +2319,10 @@ select Add TOTP to store the key safely</value>
<value>We were unable to process your request. Please try again or contact us.</value>
</data>
<data name="AllowScreenCapture" xml:space="preserve">
<value>Dovoli posnetke zaslona</value>
<value>Allow screen capture</value>
</data>
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
<value>Ste prepričani, da želite dovoliti zajemanje zaslona?</value>
<value>Are you sure you want to turn on screen capture?</value>
</data>
<data name="LogInRequested" xml:space="preserve">
<value>Login requested</value>
@@ -2337,46 +2337,46 @@ select Add TOTP to store the key safely</value>
<value>Device type</value>
</data>
<data name="IpAddress" xml:space="preserve">
<value>IP-naslov</value>
<value>IP address</value>
</data>
<data name="Time" xml:space="preserve">
<value>Čas</value>
<value>Time</value>
</data>
<data name="Near" xml:space="preserve">
<value>Blizu</value>
<value>Near</value>
</data>
<data name="ConfirmLogIn" xml:space="preserve">
<value>Potrdi prijavo</value>
<value>Confirm login</value>
</data>
<data name="DenyLogIn" xml:space="preserve">
<value>Zavrni prijavo</value>
<value>Deny login</value>
</data>
<data name="JustNow" xml:space="preserve">
<value>Pravkar</value>
<value>Just now</value>
</data>
<data name="XMinutesAgo" xml:space="preserve">
<value>Pred {0} minutami</value>
<value>{0} minutes ago</value>
</data>
<data name="LogInAccepted" xml:space="preserve">
<value>Prijava potrjena</value>
<value>Login confirmed</value>
</data>
<data name="LogInDenied" xml:space="preserve">
<value>Prijava zavrnjena</value>
<value>Login denied</value>
</data>
<data name="ApproveLoginRequests" xml:space="preserve">
<value>Odobri zahtevke za prijavo</value>
<value>Approve login requests</value>
</data>
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
<value>S to napravo odobri zahtevke za prijavo, ki pridejo z drugih naprav.</value>
<value>Use this device to approve login requests made from other devices.</value>
</data>
<data name="AllowNotifications" xml:space="preserve">
<value>Dovoli obvestila</value>
<value>Allow notifications</value>
</data>
<data name="ReceivePushNotificationsForNewLoginRequests" xml:space="preserve">
<value>Receive push notifications for new login requests</value>
</data>
<data name="NoThanks" xml:space="preserve">
<value>Ne, hvala</value>
<value>No thanks</value>
</data>
<data name="ConfimLogInAttempForX" xml:space="preserve">
<value>Confirm login attempt for {0}</value>
@@ -2385,10 +2385,10 @@ select Add TOTP to store the key safely</value>
<value>All notifications</value>
</data>
<data name="PasswordType" xml:space="preserve">
<value>Vrsta gesla</value>
<value>Password type</value>
</data>
<data name="WhatWouldYouLikeToGenerate" xml:space="preserve">
<value>Kaj želite generirati?</value>
<value>What would you like to generate?</value>
</data>
<data name="UsernameType" xml:space="preserve">
<value>Username type</value>
@@ -2444,7 +2444,7 @@ select Add TOTP to store the key safely</value>
<value>Are you sure you want to overwrite the current username?</value>
</data>
<data name="GenerateUsername" xml:space="preserve">
<value>Generiraj uporabniško ime</value>
<value>Generate username</value>
</data>
<data name="EmailType" xml:space="preserve">
<value>Email Type</value>
@@ -2477,13 +2477,13 @@ select Add TOTP to store the key safely</value>
<value>Bitwarden uses the Accessibility Service to search for login fields in apps and websites, then establish the appropriate field IDs for entering a username &amp; password when a match for the app or site is found. We do not store any of the information presented to us by the service, nor do we make any attempt to control any on-screen elements beyond text entry of credentials.</value>
</data>
<data name="Accept" xml:space="preserve">
<value>Sprejmi</value>
<value>Accept</value>
</data>
<data name="Decline" xml:space="preserve">
<value>Zavrni</value>
<value>Decline</value>
</data>
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
<value>Zahtevek za prijavo je že potekel.</value>
<value>Login request has already expired.</value>
</data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from:
@@ -2491,109 +2491,109 @@ select Add TOTP to store the key safely</value>
Do you want to switch to this account?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>Ste novi tukaj?</value>
<value>New around here?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Pridobi namig za glavno geslo</value>
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Prijavljate se kot {0}</value>
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>To niste vi?</value>
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Prijava z glavnim geslom</value>
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Prijava z napravo</value>
<value>Log in with device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Prijava sprožena</value>
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Na vašo napravo smo poslali obvestilo.</value>
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Prosimo, preverite, da je vaš trezor odklenjem in da se identifikacijski gesli na tej in drugi napravi ujemata.</value>
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Ponovno pošlji obvestilo</value>
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Potrebujete drugačno možnost?</value>
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Prikaži vse možnosti prijave</value>
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Ta zahtevek ni več veljaven</value>
<value>This request is no longer valid</value>
</data>
<data name="PendingLogInRequests" xml:space="preserve">
<value>Čakajoči zahtevki za prijavo</value>
<value>Pending login requests</value>
</data>
<data name="DeclineAllRequests" xml:space="preserve">
<value>Zavrni vse zahtevke</value>
<value>Decline all requests</value>
</data>
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
<value>Ste prepričani, da želite zavrniti vse čakajoče zahtevke za prijavo?</value>
<value>Are you sure you want to decline all pending login requests?</value>
</data>
<data name="RequestsDeclined" xml:space="preserve">
<value>Zahtevki zavrnjeni</value>
<value>Requests declined</value>
</data>
<data name="NoPendingRequests" xml:space="preserve">
<value>Ni zahtevkov</value>
<value>No pending requests</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Za uporabo skenerja dovolite uporabo kamere</value>
<value>Enable camera permission to use the scanner</value>
</data>
<data name="Language" xml:space="preserve">
<value>Jezik</value>
<value>Language</value>
</data>
<data name="LanguageChangeXDescription" xml:space="preserve">
<value>Spremenjeno v jezik {0}. Prosimo, ponovno zaženite aplikacijo za prikaz sprememb.</value>
<value>The language has been changed to {0}. Please restart the app to see the change</value>
</data>
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
<value>Za spremembo jezika je potrebno ponovno zagnati aplikacijo.</value>
<value>Language change requires app restart</value>
</data>
<data name="DefaultSystem" xml:space="preserve">
<value>Privzet (sistemski)</value>
<value>Default (System)</value>
</data>
<data name="Important" xml:space="preserve">
<value>Pomembno</value>
<value>Important</value>
</data>
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
<value>Če pozabite glavno geslo, ga ne bo mogoče obnoviti! Vsaj {0} znakov.</value>
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
</data>
<data name="WeakMasterPassword" xml:space="preserve">
<value>Šibko glavno geslo</value>
<value>Weak Master Password</value>
</data>
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
<value>Vaše geslo je šibko. Za zaščito svojega računa potrebujete močno geslo. Ste prepričani, da želite uporabiti šibko geslo?</value>
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
</data>
<data name="Weak" xml:space="preserve">
<value>Šibko</value>
<value>Weak</value>
</data>
<data name="Good" xml:space="preserve">
<value>Dobro</value>
<value>Good</value>
</data>
<data name="Strong" xml:space="preserve">
<value>Močno</value>
<value>Strong</value>
</data>
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
<value>Preveri, ali je bilo geslo izpostavljeno v krajah podatkov</value>
<value>Check known data breaches for this password</value>
</data>
<data name="ExposedMasterPassword" xml:space="preserve">
<value>Izpostavljeno glavno geslo</value>
<value>Exposed Master Password</value>
</data>
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
<value>To geslo smo našli med ukradenimi gesli. Za zaščito svojega računa uporabite edinstveno geslo. Ste prepričani, da želite uporabiti izpostavljeno geslo?</value>
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
</data>
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
<value>Šibko in izpostavljeno glavno geslo</value>
<value>Weak and Exposed Master Password</value>
</data>
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
<value>Vaše geslo je šibko, poleg tega smo ga našli med ukradenimi gesli. Za zaščito svojega računa potrebujete močno in edinstveno geslo. Ste prepričani, da želite uporabiti to šibko geslo?</value>
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
</data>
<data name="OrganizationSsoIdentifierRequired" xml:space="preserve">
<value>Organization SSO identifier required.</value>
@@ -2602,18 +2602,18 @@ Do you want to switch to this account?</value>
<value>Add the key to an existing or new item</value>
</data>
<data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve">
<value>V vašem trezorju ni elementov, ki bi ustrezali "{0}"</value>
<value>There are no items in your vault that match "{0}"</value>
</data>
<data name="SearchForAnItemOrAddANewItem" xml:space="preserve">
<value>Poišči element ali dodaj novega</value>
<value>Search for an item or add a new item</value>
</data>
<data name="ThereAreNoItemsThatMatchTheSearch" xml:space="preserve">
<value>Ni elementov, ki bi ustrezali iskanju</value>
<value>There are no items that match the search</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>Trenutno glavno geslo</value>
<value>Current master password</value>
</data>
</root>

View File

@@ -1753,10 +1753,10 @@
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Биометријско откључавање је онемогућено до верификације главне лозинке.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Биометријско откључавање аутоматског попуњавања за овај налог је онемогућено до верификације главне лозинке.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Омогући синхронизацију при освежавању</value>

View File

@@ -1753,10 +1753,10 @@
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Біометричне розблокування для цього облікового запису вимкнено. Очікується перевірка головного пароля.</value>
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Біометричне розблокування під час автозаповнення для цього облікового запису вимкнено. Очікується перевірка головного пароля.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Дозволити синхронізацію жестом</value>

View File

@@ -2610,7 +2610,7 @@
<value>没有匹配搜索条件的项目</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>您的主密码不符合某一项或多项组织策略要求。要访问密码库,必须立即更新您的主密码。继续操作将使您退出当前会话,要求您重新登录。其他设备上的活动会话可能会继续保持活动状态长达一小时。</value>
<value>您的主密码不符合您的组织策略要求。要访问密码库,必须立即更新您的主密码。继续操作将使您退出当前会话,要求您重新登录。其他设备上的活动会话可能会继续保持活动状态长达一小时。</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>当前主密码</value>

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
@@ -48,16 +47,16 @@ namespace Bit.Core.Abstractions
Task RefreshIdentityTokenAsync();
Task<SsoPrevalidateResponse> PreValidateSso(string identifier);
Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path,
TRequest body, bool authed, bool hasResponse, Action<HttpRequestMessage> alterRequest, bool logoutOnUnauthorized = true, CancellationToken cancellationToken = default);
TRequest body, bool authed, bool hasResponse, Action<HttpRequestMessage> alterRequest, bool logoutOnUnauthorized = true);
void SetUrls(EnvironmentUrls urls);
[Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
Task<CipherResponse> PostCipherAttachmentLegacyAsync(string id, MultipartFormDataContent data);
Task<AttachmentUploadDataResponse> PostCipherAttachmentAsync(string id, AttachmentRequest request, CancellationToken cancellationToken);
Task<AttachmentUploadDataResponse> PostCipherAttachmentAsync(string id, AttachmentRequest request);
Task<AttachmentResponse> GetAttachmentData(string cipherId, string attachmentId);
Task PostShareCipherAttachmentAsync(string id, string attachmentId, MultipartFormDataContent data,
string organizationId);
Task<AttachmentUploadDataResponse> RenewAttachmentUploadUrlAsync(string id, string attachmentId, CancellationToken cancellationToken);
Task PostAttachmentFileAsync(string id, string attachmentId, MultipartFormDataContent data, CancellationToken cancellationToken);
Task<AttachmentUploadDataResponse> RenewAttachmentUploadUrlAsync(string id, string attachmentId);
Task PostAttachmentFileAsync(string id, string attachmentId, MultipartFormDataContent data);
Task<List<BreachAccountResponse>> GetHibpBreachAsync(string username);
Task PostTwoFactorEmailAsync(TwoFactorEmailRequest request);
Task PutDeviceTokenAsync(string identifier, DeviceTokenRequest request);
@@ -93,6 +92,5 @@ namespace Bit.Core.Abstractions
Task<string> GetUsernameFromAsync(ForwardedEmailServiceType service, UsernameGeneratorConfig config);
Task<bool> GetKnownDeviceAsync(string email, string deviceIdentifier);
Task<OrganizationDomainSsoDetailsResponse> GetOrgDomainSsoDetailsAsync(string email);
Task<ConfigResponse> GetConfigsAsync();
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Models.Domain;
@@ -7,6 +6,6 @@ namespace Bit.Core.Abstractions
{
public interface IAzureFileUploadService
{
Task Upload(string uri, EncByteArray data, Func<CancellationToken, Task<string>> renewalCallback, CancellationToken cancellationToken);
Task Upload(string uri, EncByteArray data, Func<Task<string>> renewalCallback);
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
@@ -28,7 +27,7 @@ namespace Bit.Core.Abstractions
Task<Cipher> GetAsync(string id);
Task<CipherView> GetLastUsedForUrlAsync(string url);
Task ReplaceAsync(Dictionary<string, CipherData> ciphers);
Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data, CancellationToken cancellationToken);
Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data);
Task SaveCollectionsWithServerAsync(Cipher cipher);
Task SaveNeverDomainAsync(string domain);
Task SaveWithServerAsync(Cipher cipher);

View File

@@ -1,15 +0,0 @@
using System;
using System.Threading.Tasks;
using Bit.Core.Models.Response;
namespace Bit.Core.Abstractions
{
public interface IConfigService
{
Task<ConfigResponse> GetAsync(bool forceRefresh = false);
Task<bool> GetFeatureFlagBoolAsync(string key, bool forceRefresh = false, bool defaultValue = false);
Task<string> GetFeatureFlagStringAsync(string key, bool forceRefresh = false, string defaultValue = null);
Task<int> GetFeatureFlagIntAsync(string key, bool forceRefresh = false, int defaultValue = 0);
}
}

View File

@@ -1,5 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Response;
@@ -7,7 +6,7 @@ namespace Bit.Core.Abstractions
{
public interface IFileUploadService
{
Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData, EncString fileName, EncByteArray encryptedFileData, CancellationToken cancellationToken);
Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData, EncString fileName, EncByteArray encryptedFileData);
Task UploadSendFileAsync(SendFileUploadDataResponse uploadData, EncString fileName, EncByteArray encryptedFileData);
}
}

View File

@@ -15,6 +15,8 @@ namespace Bit.Core.Abstractions
Task<string> GeneratePasswordAsync(PasswordGenerationOptions options);
Task<List<GeneratedPasswordHistory>> GetHistoryAsync();
Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)> GetOptionsAsync();
Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)>
EnforcePasswordGeneratorPoliciesOnOptionsAsync(PasswordGenerationOptions options);
Result PasswordStrength(string password, List<string> userInputs = null);
Task SaveOptionsAsync(PasswordGenerationOptions options);
void NormalizeOptions(PasswordGenerationOptions options, PasswordGeneratorPolicyOptions enforcedPolicyOptions);

View File

@@ -19,7 +19,8 @@ namespace Bit.Core.Abstractions
Tuple<ResetPasswordPolicyOptions, bool> GetResetPasswordPolicyOptions(IEnumerable<Policy> policies,
string orgId);
Task<bool> PolicyAppliesToUser(PolicyType policyType, Func<Policy, bool> policyFilter = null, string userId = null);
int? GetPolicyInt(Policy policy, string key);
string GetPolicyString(Policy policy, string key);
Task<bool> ShouldShowVaultFilterAsync();
Task<PasswordGeneratorPolicyOptions> GetPasswordGeneratorPolicyOptionsAsync();
}
}

View File

@@ -174,7 +174,5 @@ namespace Bit.Core.Abstractions
Task SetPreLoginEmailAsync(string value);
string GetLocale();
void SetLocale(string locale);
ConfigResponse GetConfigs();
void SetConfigs(ConfigResponse value);
}
}

View File

@@ -41,9 +41,6 @@
public const string NotificationDataType = "Type";
public const string PasswordlessLoginRequestKey = "passwordlessLoginRequest";
public const string PreLoginEmailKey = "preLoginEmailKey";
public const string ConfigsKey = "configsKey";
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
/// <summary>
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in
/// which is used to handle Apple Watch state logic

View File

@@ -28,12 +28,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="LiteDB" Version="5.0.16" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="CsvHelper" Version="28.0.1" />
<PackageReference Include="LiteDB" Version="5.0.12" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="zxcvbn-core" Version="7.0.92" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.1" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.5.3" />
<PackageReference Include="MessagePack" Version="2.4.59" />
<PackageReference Include="MessagePack.MSBuild.Tasks" Version="2.4.59">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -2,9 +2,6 @@
{
public class EnvironmentUrlData
{
public static EnvironmentUrlData DefaultUS = new EnvironmentUrlData { Base = "https://vault.bitwarden.com" };
public static EnvironmentUrlData DefaultEU = new EnvironmentUrlData { Base = "https://vault.bitwarden.eu" };
public string Base { get; set; }
public string Api { get; set; }
public string Identity { get; set; }
@@ -12,13 +9,5 @@
public string Notifications { get; set; }
public string WebVault { get; set; }
public string Events { get; set; }
public bool IsEmpty => string.IsNullOrEmpty(Base)
&& string.IsNullOrEmpty(Api)
&& string.IsNullOrEmpty(Identity)
&& string.IsNullOrEmpty(Icons)
&& string.IsNullOrEmpty(Notifications)
&& string.IsNullOrEmpty(WebVault)
&& string.IsNullOrEmpty(Events);
}
}

View File

@@ -2,30 +2,30 @@
{
public class PasswordGenerationOptions
{
public const string TYPE_PASSWORD = "password";
public const string TYPE_PASSPHRASE = "passphrase";
public static PasswordGenerationOptions CreateDefault => new PasswordGenerationOptions
{
Length = 14,
AllowAmbiguousChar = true,
Number = true,
MinNumber = 1,
Uppercase = true,
MinUppercase = 0,
Lowercase = true,
MinLowercase = 0,
Special = false,
MinSpecial = 1,
Type = TYPE_PASSWORD,
NumWords = 3,
WordSeparator = "-",
Capitalize = false,
IncludeNumber = false
};
public PasswordGenerationOptions() { }
public PasswordGenerationOptions(bool defaultOptions)
{
if (defaultOptions)
{
Length = 14;
AllowAmbiguousChar = true;
Number = true;
MinNumber = 1;
Uppercase = true;
MinUppercase = 0;
Lowercase = true;
MinLowercase = 0;
Special = false;
MinSpecial = 1;
Type = "password";
NumWords = 3;
WordSeparator = "-";
Capitalize = false;
IncludeNumber = false;
}
}
public int? Length { get; set; }
public bool? AllowAmbiguousChar { get; set; }
public bool? Number { get; set; }
@@ -42,12 +42,6 @@
public bool? Capitalize { get; set; }
public bool? IncludeNumber { get; set; }
public PasswordGenerationOptions WithLength(int? length)
{
Length = length;
return this;
}
public void Merge(PasswordGenerationOptions defaults)
{
Length = Length ?? defaults.Length;
@@ -66,75 +60,5 @@
Capitalize = Capitalize ?? defaults.Capitalize;
IncludeNumber = IncludeNumber ?? defaults.IncludeNumber;
}
public void EnforcePolicy(PasswordGeneratorPolicyOptions enforcedPolicyOptions)
{
if (enforcedPolicyOptions is null)
{
return;
}
if (Length < enforcedPolicyOptions.MinLength)
{
Length = enforcedPolicyOptions.MinLength;
}
if (enforcedPolicyOptions.UseUppercase)
{
Uppercase = true;
}
if (enforcedPolicyOptions.UseLowercase)
{
Lowercase = true;
}
if (enforcedPolicyOptions.UseNumbers)
{
Number = true;
}
if (MinNumber < enforcedPolicyOptions.NumberCount)
{
MinNumber = enforcedPolicyOptions.NumberCount;
}
if (enforcedPolicyOptions.UseSpecial)
{
Special = true;
}
if (MinSpecial < enforcedPolicyOptions.SpecialCount)
{
MinSpecial = enforcedPolicyOptions.SpecialCount;
}
// Must normalize these fields because the receiving call expects all options to pass the current rules
if (MinSpecial + MinNumber > Length)
{
MinSpecial = Length - MinNumber;
}
if (NumWords < enforcedPolicyOptions.MinNumberOfWords)
{
NumWords = enforcedPolicyOptions.MinNumberOfWords;
}
if (enforcedPolicyOptions.Capitalize)
{
Capitalize = true;
}
if (enforcedPolicyOptions.IncludeNumber)
{
IncludeNumber = true;
}
// Force default type if password/passphrase selected via policy
if (enforcedPolicyOptions.DefaultType == TYPE_PASSWORD || enforcedPolicyOptions.DefaultType == TYPE_PASSPHRASE)
{
Type = enforcedPolicyOptions.DefaultType;
}
}
}
}

View File

@@ -6,11 +6,6 @@ namespace Bit.Core.Models.Domain
{
public class Policy : Domain
{
public const string MINUTES_KEY = "minutes";
public const string ACTION_KEY = "action";
public const string ACTION_LOCK = "lock";
public const string ACTION_LOGOUT = "logOut";
public Policy() { }
public Policy(PolicyData obj)
@@ -27,32 +22,5 @@ namespace Bit.Core.Models.Domain
public PolicyType Type { get; set; }
public Dictionary<string, object> Data { get; set; }
public bool Enabled { get; set; }
public int? GetInt(string key)
{
if (Data.TryGetValue(key, out var val) && val != null)
{
return (int)(long)val;
}
return null;
}
public bool? GetBool(string key)
{
if (Data.TryGetValue(key, out var val) && val != null)
{
return (bool)val;
}
return null;
}
public string GetString(string key)
{
if (Data.TryGetValue(key, out var val))
{
return (string)val;
}
return null;
}
}
}

View File

@@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
namespace Bit.Core.Models.Response
{
public class ConfigResponse
{
public string Version { get; set; }
public string GitHash { get; set; }
public ServerConfigResponse Server { get; set; }
public EnvironmentConfigResponse Environment { get; set; }
public IDictionary<string, object> FeatureStates { get; set; }
public DateTime ExpiresOn { get; set; }
}
public class ServerConfigResponse
{
public string Name { get; set; }
public string Url { get; set; }
}
public class EnvironmentConfigResponse
{
public string Vault { get; set; }
public string Api { get; set; }
public string Identity { get; set; }
public string Notifications { get; set; }
public string Sso { get; set; }
}
}

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
@@ -343,10 +342,10 @@ namespace Bit.Core.Services
string.Concat("/ciphers/", id, "/attachment"), data, true, true);
}
public Task<AttachmentUploadDataResponse> PostCipherAttachmentAsync(string id, AttachmentRequest request, CancellationToken cancellationToken)
public Task<AttachmentUploadDataResponse> PostCipherAttachmentAsync(string id, AttachmentRequest request)
{
return SendAsync<AttachmentRequest, AttachmentUploadDataResponse>(HttpMethod.Post,
$"/ciphers/{id}/attachment/v2", request, true, true, cancellationToken: cancellationToken);
$"/ciphers/{id}/attachment/v2", request, true, true);
}
public Task<AttachmentResponse> GetAttachmentData(string cipherId, string attachmentId) =>
@@ -366,12 +365,12 @@ namespace Bit.Core.Services
data, true, false);
}
public Task<AttachmentUploadDataResponse> RenewAttachmentUploadUrlAsync(string cipherId, string attachmentId, CancellationToken cancellationToken) =>
SendAsync<AttachmentUploadDataResponse>(HttpMethod.Get, $"/ciphers/{cipherId}/attachment/{attachmentId}/renew", true, cancellationToken);
public Task<AttachmentUploadDataResponse> RenewAttachmentUploadUrlAsync(string cipherId, string attachmentId) =>
SendAsync<AttachmentUploadDataResponse>(HttpMethod.Get, $"/ciphers/{cipherId}/attachment/{attachmentId}/renew", true);
public Task PostAttachmentFileAsync(string cipherId, string attachmentId, MultipartFormDataContent data, CancellationToken cancellationToken) =>
public Task PostAttachmentFileAsync(string cipherId, string attachmentId, MultipartFormDataContent data) =>
SendAsync(HttpMethod.Post,
$"/ciphers/{cipherId}/attachment/{attachmentId}", data, true, cancellationToken);
$"/ciphers/{cipherId}/attachment/{attachmentId}", data, true);
#endregion
@@ -586,16 +585,6 @@ namespace Bit.Core.Services
#endregion
#region Configs
public async Task<ConfigResponse> GetConfigsAsync()
{
var accessToken = await _tokenService.GetTokenAsync();
return await SendAsync<object, ConfigResponse>(HttpMethod.Get, "/config/", null, !string.IsNullOrEmpty(accessToken), true);
}
#endregion
#region Helpers
public async Task<string> GetActiveBearerTokenAsync()
@@ -640,12 +629,12 @@ namespace Bit.Core.Services
public Task SendAsync(HttpMethod method, string path, bool authed) =>
SendAsync<object, object>(method, path, null, authed, false);
public Task SendAsync<TRequest>(HttpMethod method, string path, TRequest body, bool authed, CancellationToken cancellationToken = default) =>
SendAsync<TRequest, object>(method, path, body, authed, false, cancellationToken: cancellationToken);
public Task<TResponse> SendAsync<TResponse>(HttpMethod method, string path, bool authed, CancellationToken cancellationToken = default) =>
SendAsync<object, TResponse>(method, path, null, authed, true, cancellationToken: cancellationToken);
public Task SendAsync<TRequest>(HttpMethod method, string path, TRequest body, bool authed) =>
SendAsync<TRequest, object>(method, path, body, authed, false);
public Task<TResponse> SendAsync<TResponse>(HttpMethod method, string path, bool authed) =>
SendAsync<object, TResponse>(method, path, null, authed, true);
public async Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path, TRequest body,
bool authed, bool hasResponse, Action<HttpRequestMessage> alterRequest = null, bool logoutOnUnauthorized = true, CancellationToken cancellationToken = default)
bool authed, bool hasResponse, Action<HttpRequestMessage> alterRequest = null, bool logoutOnUnauthorized = true)
{
using (var requestMessage = new HttpRequestMessage())
{
@@ -697,15 +686,7 @@ namespace Bit.Core.Services
HttpResponseMessage response;
try
{
response = await _httpClient.SendAsync(requestMessage, cancellationToken);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex) when (ex.Message?.Contains("Socket closed") == true)
{
throw new OperationCanceledException();
response = await _httpClient.SendAsync(requestMessage);
}
catch (Exception e)
{

View File

@@ -605,7 +605,7 @@ namespace Bit.Core.Services
var generatedFingerprintPhrase = await _cryptoService.GetFingerprintAsync(email, keyPair.Item1);
var fingerprintPhrase = string.Join("-", generatedFingerprintPhrase);
var publicB64 = Convert.ToBase64String(keyPair.Item1);
var accessCode = await _passwordGenerationService.GeneratePasswordAsync(PasswordGenerationOptions.CreateDefault.WithLength(25));
var accessCode = await _passwordGenerationService.GeneratePasswordAsync(new PasswordGenerationOptions(true) { Length = 25 });
var passwordlessCreateLoginRequest = new PasswordlessCreateLoginRequest(email, publicB64, deviceId, accessCode, AuthRequestType.AuthenticateAndUnlock, fingerprintPhrase);
var response = await _apiService.PostCreateRequestAsync(passwordlessCreateLoginRequest);

View File

@@ -5,7 +5,6 @@ using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Bit.Core.Abstractions;
@@ -30,19 +29,19 @@ namespace Bit.Core.Services
};
}
public async Task Upload(string uri, EncByteArray data, Func<CancellationToken, Task<string>> renewalCallback, CancellationToken cancellationToken)
public async Task Upload(string uri, EncByteArray data, Func<Task<string>> renewalCallback)
{
if (data?.Buffer?.Length <= MAX_SINGLE_BLOB_UPLOAD_SIZE)
{
await AzureUploadBlob(uri, data, cancellationToken);
await AzureUploadBlob(uri, data);
}
else
{
await AzureUploadBlocks(uri, data, renewalCallback, cancellationToken);
await AzureUploadBlocks(uri, data, renewalCallback);
}
}
private async Task AzureUploadBlob(string uri, EncByteArray data, CancellationToken cancellationToken)
private async Task AzureUploadBlob(string uri, EncByteArray data)
{
using (var requestMessage = new HttpRequestMessage())
{
@@ -58,7 +57,7 @@ namespace Bit.Core.Services
requestMessage.Method = HttpMethod.Put;
requestMessage.RequestUri = uriBuilder.Uri;
var blobResponse = await _httpClient.SendAsync(requestMessage, cancellationToken);
var blobResponse = await _httpClient.SendAsync(requestMessage);
if (blobResponse.StatusCode != HttpStatusCode.Created)
{
@@ -67,7 +66,7 @@ namespace Bit.Core.Services
}
}
private async Task AzureUploadBlocks(string uri, EncByteArray data, Func<CancellationToken, Task<string>> renewalFunc, CancellationToken cancellationToken)
private async Task AzureUploadBlocks(string uri, EncByteArray data, Func<Task<string>> renewalFunc)
{
_httpClient.Timeout = TimeSpan.FromHours(3);
var baseParams = HttpUtility.ParseQueryString(CoreHelpers.GetUri(uri).Query);
@@ -83,7 +82,7 @@ namespace Bit.Core.Services
while (blockIndex < numBlocks)
{
uri = await RenewUriIfNecessary(uri, renewalFunc, cancellationToken);
uri = await RenewUriIfNecessary(uri, renewalFunc);
var blockUriBuilder = new UriBuilder(uri);
var blockId = EncodeBlockId(blockIndex);
var blockParams = HttpUtility.ParseQueryString(blockUriBuilder.Query);
@@ -102,7 +101,7 @@ namespace Bit.Core.Services
requestMessage.Method = HttpMethod.Put;
requestMessage.RequestUri = blockUriBuilder.Uri;
var blockResponse = await _httpClient.SendAsync(requestMessage, cancellationToken);
var blockResponse = await _httpClient.SendAsync(requestMessage);
if (blockResponse.StatusCode != HttpStatusCode.Created)
{
@@ -116,7 +115,7 @@ namespace Bit.Core.Services
using (var requestMessage = new HttpRequestMessage())
{
uri = await RenewUriIfNecessary(uri, renewalFunc, cancellationToken);
uri = await RenewUriIfNecessary(uri, renewalFunc);
var blockListXml = GenerateBlockListXml(blocksStaged);
var blockListUriBuilder = new UriBuilder(uri);
var blockListParams = HttpUtility.ParseQueryString(blockListUriBuilder.Query);
@@ -131,7 +130,7 @@ namespace Bit.Core.Services
requestMessage.Method = HttpMethod.Put;
requestMessage.RequestUri = blockListUriBuilder.Uri;
var blockListResponse = await _httpClient.SendAsync(requestMessage, cancellationToken);
var blockListResponse = await _httpClient.SendAsync(requestMessage);
if (blockListResponse.StatusCode != HttpStatusCode.Created)
{
@@ -140,13 +139,13 @@ namespace Bit.Core.Services
}
}
private async Task<string> RenewUriIfNecessary(string uri, Func<CancellationToken, Task<string>> renewalFunc, CancellationToken cancellationToken)
private async Task<string> RenewUriIfNecessary(string uri, Func<Task<string>> renewalFunc)
{
var uriParams = HttpUtility.ParseQueryString(CoreHelpers.GetUri(uri).Query);
if (DateTime.TryParse(uriParams.Get("se") ?? "", out DateTime expiry) && expiry < DateTime.UtcNow.AddSeconds(1))
{
return await renewalFunc(cancellationToken);
return await renewalFunc();
}
return uri;
}

View File

@@ -2,7 +2,6 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Models.Domain;
@@ -10,21 +9,21 @@ namespace Bit.Core.Services
{
public class BitwardenFileUploadService
{
private readonly ApiService _apiService;
public BitwardenFileUploadService(ApiService apiService)
{
_apiService = apiService;
}
public async Task Upload(string encryptedFileName, EncByteArray encryptedFileData, Func<MultipartFormDataContent, CancellationToken, Task> apiCall, CancellationToken cancellationToken)
private readonly ApiService _apiService;
public async Task Upload(string encryptedFileName, EncByteArray encryptedFileData, Func<MultipartFormDataContent, Task> apiCall)
{
var fd = new MultipartFormDataContent($"--BWMobileFormBoundary{DateTime.UtcNow.Ticks}")
{
{ new ByteArrayContent(encryptedFileData.Buffer) { Headers = { ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet) } }, "data", encryptedFileName }
};
await apiCall(fd, cancellationToken);
await apiCall(fd);
}
}
}

View File

@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
@@ -556,15 +555,13 @@ namespace Bit.Core.Services
await UpsertAsync(data);
}
public async Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data, CancellationToken cancellationToken)
public async Task<Cipher> SaveAttachmentRawWithServerAsync(Cipher cipher, string filename, byte[] data)
{
var orgKey = await _cryptoService.GetOrgKeyAsync(cipher.OrganizationId);
var encFileName = await _cryptoService.EncryptAsync(filename, orgKey);
var (attachmentKey, orgEncAttachmentKey) = await _cryptoService.MakeEncKeyAsync(orgKey);
var encFileData = await _cryptoService.EncryptToBytesAsync(data, attachmentKey);
cancellationToken.ThrowIfCancellationRequested();
CipherResponse response;
try
{
@@ -575,9 +572,9 @@ namespace Bit.Core.Services
FileSize = encFileData.Buffer.Length,
};
var uploadDataResponse = await _apiService.PostCipherAttachmentAsync(cipher.Id, request, cancellationToken);
var uploadDataResponse = await _apiService.PostCipherAttachmentAsync(cipher.Id, request);
response = uploadDataResponse.CipherResponse;
await _fileUploadService.UploadCipherAttachmentFileAsync(uploadDataResponse, encFileName, encFileData, cancellationToken);
await _fileUploadService.UploadCipherAttachmentFileAsync(uploadDataResponse, encFileName, encFileData);
}
catch (ApiException e) when (e.Error.StatusCode == System.Net.HttpStatusCode.NotFound || e.Error.StatusCode == System.Net.HttpStatusCode.MethodNotAllowed)
{

View File

@@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Response;
using Bit.Core.Models.View;
namespace Bit.Core.Services
{
public class ConfigService : IConfigService
{
private const int UPDATE_INTERVAL_MINS = 60;
private ConfigResponse _configs;
private readonly IApiService _apiService;
private readonly IStateService _stateService;
private readonly ILogger _logger;
public ConfigService(IApiService apiService, IStateService stateService, ILogger logger)
{
_apiService = apiService;
_stateService = stateService;
_logger = logger;
}
public async Task<ConfigResponse> GetAsync(bool forceRefresh = false)
{
try
{
_configs = _stateService.GetConfigs();
if (forceRefresh || _configs?.ExpiresOn is null || _configs.ExpiresOn <= DateTime.UtcNow)
{
_configs = await _apiService.GetConfigsAsync();
_configs.ExpiresOn = DateTime.UtcNow.AddMinutes(UPDATE_INTERVAL_MINS);
_stateService.SetConfigs(_configs);
}
}
catch (ApiException ex) when (ex.Error.StatusCode == System.Net.HttpStatusCode.BadGateway)
{
// ignore if there is no internet connection and return local configs
}
catch (Exception ex)
{
_logger.Exception(ex);
}
return _configs;
}
public async Task<bool> GetFeatureFlagBoolAsync(string key, bool forceRefresh = false, bool defaultValue = false) => await GetFeatureFlagAsync<bool>(key, forceRefresh, defaultValue);
public async Task<string> GetFeatureFlagStringAsync(string key, bool forceRefresh = false, string defaultValue = null) => await GetFeatureFlagAsync<string>(key, forceRefresh, defaultValue);
public async Task<int> GetFeatureFlagIntAsync(string key, bool forceRefresh = false, int defaultValue = 0) => await GetFeatureFlagAsync<int>(key, forceRefresh, defaultValue);
private async Task<T> GetFeatureFlagAsync<T>(string key, bool forceRefresh = false, T defaultValue = default)
{
await GetAsync(forceRefresh);
if (_configs == null || _configs.FeatureStates == null)
{
return defaultValue;
}
if (_configs.FeatureStates.TryGetValue(key, out var val) == true
&&
val is T actualValue)
{
return actualValue;
}
return defaultValue;
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
@@ -22,7 +21,7 @@ namespace Bit.Core.Services
private readonly ApiService _apiService;
public async Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData,
EncString encryptedFileName, EncByteArray encryptedFileData, CancellationToken cancellationToken)
EncString encryptedFileName, EncByteArray encryptedFileData)
{
try
{
@@ -30,15 +29,15 @@ namespace Bit.Core.Services
{
case FileUploadType.Direct:
await _bitwardenFileUploadService.Upload(encryptedFileName.EncryptedString, encryptedFileData,
(fd, ct) => _apiService.PostAttachmentFileAsync(uploadData.CipherResponse.Id, uploadData.AttachmentId, fd, ct), cancellationToken);
fd => _apiService.PostAttachmentFileAsync(uploadData.CipherResponse.Id, uploadData.AttachmentId, fd));
break;
case FileUploadType.Azure:
Func<CancellationToken, Task<string>> renewalCallback = async ct =>
Func<Task<string>> renewalCallback = async () =>
{
var response = await _apiService.RenewAttachmentUploadUrlAsync(uploadData.CipherResponse.Id, uploadData.AttachmentId, ct);
var response = await _apiService.RenewAttachmentUploadUrlAsync(uploadData.CipherResponse.Id, uploadData.AttachmentId);
return response.Url;
};
await _azureFileUploadService.Upload(uploadData.Url, encryptedFileData, renewalCallback, cancellationToken);
await _azureFileUploadService.Upload(uploadData.Url, encryptedFileData, renewalCallback);
break;
default:
throw new Exception($"Unkown file upload type: {uploadData.FileUploadType}");
@@ -59,16 +58,16 @@ namespace Bit.Core.Services
{
case FileUploadType.Direct:
await _bitwardenFileUploadService.Upload(fileName.EncryptedString, encryptedFileData,
(fd, _) => _apiService.PostSendFileAsync(uploadData.SendResponse.Id, uploadData.SendResponse.File.Id, fd), default);
fd => _apiService.PostSendFileAsync(uploadData.SendResponse.Id, uploadData.SendResponse.File.Id, fd));
break;
case FileUploadType.Azure:
Func<CancellationToken, Task<string>> renewalCallback = async ct =>
Func<Task<string>> renewalCallback = async () =>
{
var response = await _apiService.RenewFileUploadUrlAsync(uploadData.SendResponse.Id, uploadData.SendResponse.File.Id);
return response.Url;
};
await _azureFileUploadService.Upload(uploadData.Url, encryptedFileData, renewalCallback, default);
await _azureFileUploadService.Upload(uploadData.Url, encryptedFileData, renewalCallback);
break;
default:
throw new Exception("Unknown file upload type");

View File

@@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Utilities;
using Zxcvbn;
@@ -14,17 +15,17 @@ namespace Bit.Core.Services
{
public class PasswordGenerationService : IPasswordGenerationService
{
private const int MAX_PASSWORDS_IN_HISTORY = 100;
private const string LOWERCASE_CHAR_SET = "abcdefghijkmnopqrstuvwxyz";
private const string UPPERCASE_CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZ";
private const string NUMER_CHAR_SET = "23456789";
private const string SPECIAL_CHAR_SET = "!@#$%^&*";
private const int MaxPasswordsInHistory = 100;
private const string LowercaseCharSet = "abcdefghijkmnopqrstuvwxyz";
private const string UppercaseCharSet = "ABCDEFGHJKLMNPQRSTUVWXYZ";
private const string NumberCharSet = "23456789";
private const string SpecialCharSet = "!@#$%^&*";
private readonly ICryptoService _cryptoService;
private readonly IStateService _stateService;
private readonly ICryptoFunctionService _cryptoFunctionService;
private readonly IPolicyService _policyService;
private PasswordGenerationOptions _defaultOptions = PasswordGenerationOptions.CreateDefault;
private PasswordGenerationOptions _defaultOptions = new PasswordGenerationOptions(true);
private PasswordGenerationOptions _optionsCache;
private List<GeneratedPasswordHistory> _history;
@@ -44,7 +45,7 @@ namespace Bit.Core.Services
{
// Overload defaults with given options
options.Merge(_defaultOptions);
if (options.Type == PasswordGenerationOptions.TYPE_PASSPHRASE)
if (options.Type == "passphrase")
{
return await GeneratePassphraseAsync(options);
}
@@ -53,30 +54,30 @@ namespace Bit.Core.Services
SanitizePasswordLength(options, true);
var positionsBuilder = new StringBuilder();
if (options.Lowercase.GetValueOrDefault() && options.MinLowercase > 0)
if (options.Lowercase.GetValueOrDefault() && options.MinLowercase.GetValueOrDefault() > 0)
{
for (int i = 0; i < options.MinLowercase; i++)
for (int i = 0; i < options.MinLowercase.GetValueOrDefault(); i++)
{
positionsBuilder.Append("l");
}
}
if (options.Uppercase.GetValueOrDefault() && options.MinUppercase > 0)
if (options.Uppercase.GetValueOrDefault() && options.MinUppercase.GetValueOrDefault() > 0)
{
for (int i = 0; i < options.MinUppercase; i++)
for (int i = 0; i < options.MinUppercase.GetValueOrDefault(); i++)
{
positionsBuilder.Append("u");
}
}
if (options.Number.GetValueOrDefault() && options.MinNumber > 0)
if (options.Number.GetValueOrDefault() && options.MinNumber.GetValueOrDefault() > 0)
{
for (int i = 0; i < options.MinNumber; i++)
for (int i = 0; i < options.MinNumber.GetValueOrDefault(); i++)
{
positionsBuilder.Append("n");
}
}
if (options.Special.GetValueOrDefault() && options.MinSpecial > 0)
if (options.Special.GetValueOrDefault() && options.MinSpecial.GetValueOrDefault() > 0)
{
for (int i = 0; i < options.MinSpecial; i++)
for (int i = 0; i < options.MinSpecial.GetValueOrDefault(); i++)
{
positionsBuilder.Append("s");
}
@@ -91,68 +92,68 @@ namespace Bit.Core.Services
.OrderBy(a => _cryptoFunctionService.RandomNumber()).ToArray();
// Build out other character sets
var allCharSet = new StringBuilder();
var lowercaseCharSet = LOWERCASE_CHAR_SET;
var allCharSet = string.Empty;
var lowercaseCharSet = LowercaseCharSet;
if (options.AllowAmbiguousChar.GetValueOrDefault())
{
lowercaseCharSet = string.Concat(lowercaseCharSet, "l");
}
if (options.Lowercase.GetValueOrDefault())
{
allCharSet.Append(lowercaseCharSet);
allCharSet = string.Concat(allCharSet, lowercaseCharSet);
}
var uppercaseCharSet = UPPERCASE_CHAR_SET;
var uppercaseCharSet = UppercaseCharSet;
if (options.AllowAmbiguousChar.GetValueOrDefault())
{
uppercaseCharSet = string.Concat(uppercaseCharSet, "IO");
}
if (options.Uppercase.GetValueOrDefault())
{
allCharSet.Append(uppercaseCharSet);
allCharSet = string.Concat(allCharSet, uppercaseCharSet);
}
var numberCharSet = NUMER_CHAR_SET;
var numberCharSet = NumberCharSet;
if (options.AllowAmbiguousChar.GetValueOrDefault())
{
numberCharSet = string.Concat(numberCharSet, "01");
}
if (options.Number.GetValueOrDefault())
{
allCharSet.Append(numberCharSet);
allCharSet = string.Concat(allCharSet, numberCharSet);
}
var specialCharSet = SpecialCharSet;
if (options.Special.GetValueOrDefault())
{
allCharSet.Append(SPECIAL_CHAR_SET);
allCharSet = string.Concat(allCharSet, specialCharSet);
}
var password = new StringBuilder();
for (var i = 0; i < options.Length.GetValueOrDefault(); i++)
{
var charSetOnCurrentPosition = string.Empty;
var positionChars = string.Empty;
switch (positions[i])
{
case 'l':
charSetOnCurrentPosition = lowercaseCharSet;
positionChars = lowercaseCharSet;
break;
case 'u':
charSetOnCurrentPosition = uppercaseCharSet;
positionChars = uppercaseCharSet;
break;
case 'n':
charSetOnCurrentPosition = numberCharSet;
positionChars = numberCharSet;
break;
case 's':
charSetOnCurrentPosition = SPECIAL_CHAR_SET;
positionChars = specialCharSet;
break;
case 'a':
charSetOnCurrentPosition = allCharSet.ToString();
positionChars = allCharSet;
break;
}
var randomCharIndex = await _cryptoService.RandomNumberAsync(0, charSetOnCurrentPosition.Length - 1);
password.Append(charSetOnCurrentPosition[randomCharIndex]);
var randomCharIndex = await _cryptoService.RandomNumberAsync(0, positionChars.Length - 1);
password.Append(positionChars[randomCharIndex]);
}
return password.ToString();
@@ -167,7 +168,7 @@ namespace Bit.Core.Services
public async Task<string> GeneratePassphraseAsync(PasswordGenerationOptions options)
{
options.Merge(_defaultOptions);
if (options.NumWords <= 2)
if (options.NumWords.GetValueOrDefault() <= 2)
{
options.NumWords = _defaultOptions.NumWords;
}
@@ -220,10 +221,179 @@ namespace Bit.Core.Services
}
}
var policyOptions = await _policyService.GetPasswordGeneratorPolicyOptionsAsync();
_optionsCache.EnforcePolicy(policyOptions);
var (enforcedOptions, enforcedPolicyOptions) = await EnforcePasswordGeneratorPoliciesOnOptionsAsync(
_optionsCache);
_optionsCache = enforcedOptions;
return (_optionsCache, enforcedPolicyOptions);
}
return (_optionsCache, policyOptions ?? new PasswordGeneratorPolicyOptions());
public async Task<(PasswordGenerationOptions, PasswordGeneratorPolicyOptions)>
EnforcePasswordGeneratorPoliciesOnOptionsAsync(PasswordGenerationOptions options)
{
var enforcedPolicyOptions = await GetPasswordGeneratorPolicyOptions();
if (enforcedPolicyOptions != null)
{
if (options.Length < enforcedPolicyOptions.MinLength)
{
options.Length = enforcedPolicyOptions.MinLength;
}
if (enforcedPolicyOptions.UseUppercase)
{
options.Uppercase = true;
}
if (enforcedPolicyOptions.UseLowercase)
{
options.Lowercase = true;
}
if (enforcedPolicyOptions.UseNumbers)
{
options.Number = true;
}
if (options.MinNumber < enforcedPolicyOptions.NumberCount)
{
options.MinNumber = enforcedPolicyOptions.NumberCount;
}
if (enforcedPolicyOptions.UseSpecial)
{
options.Special = true;
}
if (options.MinSpecial < enforcedPolicyOptions.SpecialCount)
{
options.MinSpecial = enforcedPolicyOptions.SpecialCount;
}
// Must normalize these fields because the receiving call expects all options to pass the current rules
if (options.MinSpecial + options.MinNumber > options.Length)
{
options.MinSpecial = options.Length - options.MinNumber;
}
if (options.NumWords < enforcedPolicyOptions.MinNumberOfWords)
{
options.NumWords = enforcedPolicyOptions.MinNumberOfWords;
}
if (enforcedPolicyOptions.Capitalize)
{
options.Capitalize = true;
}
if (enforcedPolicyOptions.IncludeNumber)
{
options.IncludeNumber = true;
}
// Force default type if password/passphrase selected via policy
if (enforcedPolicyOptions.DefaultType == "password" || enforcedPolicyOptions.DefaultType == "passphrase")
{
options.Type = enforcedPolicyOptions.DefaultType;
}
}
else
{
// UI layer expects an instantiated object to prevent more explicit null checks
enforcedPolicyOptions = new PasswordGeneratorPolicyOptions();
}
return (options, enforcedPolicyOptions);
}
public async Task<PasswordGeneratorPolicyOptions> GetPasswordGeneratorPolicyOptions()
{
var policies = await _policyService.GetAll(PolicyType.PasswordGenerator);
PasswordGeneratorPolicyOptions enforcedOptions = null;
if (policies == null || !policies.Any())
{
return enforcedOptions;
}
foreach (var currentPolicy in policies)
{
if (!currentPolicy.Enabled || currentPolicy.Data == null)
{
continue;
}
if (enforcedOptions == null)
{
enforcedOptions = new PasswordGeneratorPolicyOptions();
}
var defaultType = GetPolicyString(currentPolicy, "defaultType");
if (defaultType != null && enforcedOptions.DefaultType != "password")
{
enforcedOptions.DefaultType = defaultType;
}
var minLength = GetPolicyInt(currentPolicy, "minLength");
if (minLength != null && (int)(long)minLength > enforcedOptions.MinLength)
{
enforcedOptions.MinLength = (int)(long)minLength;
}
var useUpper = GetPolicyBool(currentPolicy, "useUpper");
if (useUpper != null && (bool)useUpper)
{
enforcedOptions.UseUppercase = true;
}
var useLower = GetPolicyBool(currentPolicy, "useLower");
if (useLower != null && (bool)useLower)
{
enforcedOptions.UseLowercase = true;
}
var useNumbers = GetPolicyBool(currentPolicy, "useNumbers");
if (useNumbers != null && (bool)useNumbers)
{
enforcedOptions.UseNumbers = true;
}
var minNumbers = GetPolicyInt(currentPolicy, "minNumbers");
if (minNumbers != null && (int)(long)minNumbers > enforcedOptions.NumberCount)
{
enforcedOptions.NumberCount = (int)(long)minNumbers;
}
var useSpecial = GetPolicyBool(currentPolicy, "useSpecial");
if (useSpecial != null && (bool)useSpecial)
{
enforcedOptions.UseSpecial = true;
}
var minSpecial = GetPolicyInt(currentPolicy, "minSpecial");
if (minSpecial != null && (int)(long)minSpecial > enforcedOptions.SpecialCount)
{
enforcedOptions.SpecialCount = (int)(long)minSpecial;
}
var minNumberWords = GetPolicyInt(currentPolicy, "minNumberWords");
if (minNumberWords != null && (int)(long)minNumberWords > enforcedOptions.MinNumberOfWords)
{
enforcedOptions.MinNumberOfWords = (int)(long)minNumberWords;
}
var capitalize = GetPolicyBool(currentPolicy, "capitalize");
if (capitalize != null && (bool)capitalize)
{
enforcedOptions.Capitalize = true;
}
var includeNumber = GetPolicyBool(currentPolicy, "includeNumber");
if (includeNumber != null && (bool)includeNumber)
{
enforcedOptions.IncludeNumber = true;
}
}
return enforcedOptions;
}
public List<string> GetPasswordStrengthUserInput(string email)
@@ -239,6 +409,45 @@ namespace Bit.Core.Services
return new List<string>(data);
}
private int? GetPolicyInt(Policy policy, string key)
{
if (policy.Data.ContainsKey(key))
{
var value = policy.Data[key];
if (value != null)
{
return (int)(long)value;
}
}
return null;
}
private bool? GetPolicyBool(Policy policy, string key)
{
if (policy.Data.ContainsKey(key))
{
var value = policy.Data[key];
if (value != null)
{
return (bool)value;
}
}
return null;
}
private string GetPolicyString(Policy policy, string key)
{
if (policy.Data.ContainsKey(key))
{
var value = policy.Data[key];
if (value != null)
{
return (string)value;
}
}
return null;
}
public async Task SaveOptionsAsync(PasswordGenerationOptions options)
{
await _stateService.SetPasswordGenerationOptionsAsync(options);
@@ -276,7 +485,7 @@ namespace Bit.Core.Services
token.ThrowIfCancellationRequested();
currentHistory.Insert(0, new GeneratedPasswordHistory { Password = password, Date = DateTime.UtcNow });
// Remove old items.
if (currentHistory.Count > MAX_PASSWORDS_IN_HISTORY)
if (currentHistory.Count > MaxPasswordsInHistory)
{
currentHistory.RemoveAt(currentHistory.Count - 1);
}

View File

@@ -17,6 +17,11 @@ namespace Bit.Core.Services
private IEnumerable<Policy> _policyCache;
public const string TIMEOUT_POLICY_MINUTES = "minutes";
public const string TIMEOUT_POLICY_ACTION = "action";
public const string TIMEOUT_POLICY_ACTION_LOCK = "lock";
public const string TIMEOUT_POLICY_ACTION_LOGOUT = "logOut";
public PolicyService(
IStateService stateService,
IOrganizationService organizationService)
@@ -46,8 +51,10 @@ namespace Bit.Core.Services
{
return _policyCache.Where(p => p.Type == type).ToList();
}
return _policyCache;
else
{
return _policyCache;
}
}
public async Task Replace(Dictionary<string, PolicyData> policies, string userId = null)
@@ -70,7 +77,7 @@ namespace Bit.Core.Services
public async Task UpdateVaultTimeoutFromPolicyAsync(Policy policy, string userId = null)
{
var policyTimeout = policy.GetInt(Policy.MINUTES_KEY);
var policyTimeout = GetPolicyInt(policy, PolicyService.TIMEOUT_POLICY_MINUTES);
if (policyTimeout != null)
{
var vaultTimeout = await _stateService.GetVaultTimeoutAsync(userId);
@@ -85,11 +92,11 @@ namespace Bit.Core.Services
}
}
var policyAction = policy.GetString(Policy.ACTION_KEY);
var policyAction = GetPolicyString(policy, PolicyService.TIMEOUT_POLICY_ACTION);
if (!string.IsNullOrEmpty(policyAction))
{
var vaultTimeoutAction = await _stateService.GetVaultTimeoutActionAsync(userId);
var action = policyAction == Policy.ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout;
var action = policyAction == PolicyService.TIMEOUT_POLICY_ACTION_LOCK ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout;
if (vaultTimeoutAction != action)
{
await _stateService.SetVaultTimeoutActionAsync(action, userId);
@@ -100,63 +107,71 @@ namespace Bit.Core.Services
public async Task<MasterPasswordPolicyOptions> GetMasterPasswordPolicyOptions(
IEnumerable<Policy> policies = null, string userId = null)
{
MasterPasswordPolicyOptions enforcedOptions = null;
if (policies == null)
{
policies = await GetAll(PolicyType.MasterPassword, userId);
if (policies == null)
{
return null;
}
}
else
{
policies = policies.Where(p => p.Type == PolicyType.MasterPassword);
}
policies = policies.Where(p => p.Enabled && p.Data != null);
if (!policies.Any())
if (policies == null || !policies.Any())
{
return null;
return enforcedOptions;
}
var enforcedOptions = new MasterPasswordPolicyOptions();
foreach (var currentPolicy in policies)
{
var minComplexity = currentPolicy.GetInt("minComplexity");
if (minComplexity > enforcedOptions.MinComplexity)
if (!currentPolicy.Enabled || currentPolicy.Data == null)
{
enforcedOptions.MinComplexity = minComplexity.Value;
continue;
}
var minLength = currentPolicy.GetInt("minLength");
if (minLength > enforcedOptions.MinLength)
if (enforcedOptions == null)
{
enforcedOptions.MinLength = minLength.Value;
enforcedOptions = new MasterPasswordPolicyOptions();
}
if (currentPolicy.GetBool("requireUpper") == true)
var minComplexity = GetPolicyInt(currentPolicy, "minComplexity");
if (minComplexity != null && (int)(long)minComplexity > enforcedOptions.MinComplexity)
{
enforcedOptions.MinComplexity = (int)(long)minComplexity;
}
var minLength = GetPolicyInt(currentPolicy, "minLength");
if (minLength != null && (int)(long)minLength > enforcedOptions.MinLength)
{
enforcedOptions.MinLength = (int)(long)minLength;
}
var requireUpper = GetPolicyBool(currentPolicy, "requireUpper");
if (requireUpper == true)
{
enforcedOptions.RequireUpper = true;
}
if (currentPolicy.GetBool("requireLower") == true)
var requireLower = GetPolicyBool(currentPolicy, "requireLower");
if (requireLower == true)
{
enforcedOptions.RequireLower = true;
}
if (currentPolicy.GetBool("requireNumbers") == true)
var requireNumbers = GetPolicyBool(currentPolicy, "requireNumbers");
if (requireNumbers == true)
{
enforcedOptions.RequireNumbers = true;
}
if (currentPolicy.GetBool("requireSpecial") == true)
var requireSpecial = GetPolicyBool(currentPolicy, "requireSpecial");
if (requireSpecial == true)
{
enforcedOptions.RequireSpecial = true;
}
var enforceOnLogin = currentPolicy.GetBool("enforceOnLogin");
var enforceOnLogin = GetPolicyBool(currentPolicy, "enforceOnLogin");
if (enforceOnLogin == true)
{
enforcedOptions.EnforceOnLogin = true;
@@ -219,7 +234,7 @@ namespace Bit.Core.Services
var policy = policies.FirstOrDefault(p =>
p.OrganizationId == orgId && p.Type == PolicyType.ResetPassword && p.Enabled);
resetPasswordPolicyOptions.AutoEnrollEnabled = policy.GetBool("autoEnrollEnabled") ?? false;
resetPasswordPolicyOptions.AutoEnrollEnabled = GetPolicyBool(policy, "autoEnrollEnabled") ?? false;
return new Tuple<ResetPasswordPolicyOptions, bool>(resetPasswordPolicyOptions, policy != null);
}
@@ -265,6 +280,23 @@ namespace Bit.Core.Services
return organization.isExemptFromPolicies;
}
public int? GetPolicyInt(Policy policy, string key)
{
if (policy.Data.ContainsKey(key))
{
var value = policy.Data[key];
if (value != null)
{
return (int)(long)value;
}
}
return null;
}
public string GetPolicyString(Policy policy, string key) =>
policy.Data.TryGetValue(key, out var val) ? val as string : null;
public async Task<bool> ShouldShowVaultFilterAsync()
{
var personalOwnershipPolicyApplies = await PolicyAppliesToUser(PolicyType.PersonalOwnership);
@@ -277,86 +309,19 @@ namespace Bit.Core.Services
return organizations?.Any() ?? false;
}
public async Task<PasswordGeneratorPolicyOptions> GetPasswordGeneratorPolicyOptionsAsync()
private bool? GetPolicyBool(Policy policy, string key)
{
var policies = await GetAll(PolicyType.PasswordGenerator);
if (policies == null)
if (policy.Data.ContainsKey(key))
{
return null;
}
var actualPolicies = policies.Where(p => p.Enabled && p.Data != null);
if (!actualPolicies.Any())
{
return null;
}
var enforcedOptions = new PasswordGeneratorPolicyOptions();
foreach (var currentPolicy in actualPolicies)
{
var defaultType = currentPolicy.GetString("defaultType");
if (defaultType != null && enforcedOptions.DefaultType != PasswordGenerationOptions.TYPE_PASSWORD)
var value = policy.Data[key];
if (value != null)
{
enforcedOptions.DefaultType = defaultType;
}
var minLength = currentPolicy.GetInt("minLength");
if (minLength > enforcedOptions.MinLength)
{
enforcedOptions.MinLength = minLength.Value;
}
if (currentPolicy.GetBool("useUpper") == true)
{
enforcedOptions.UseUppercase = true;
}
if (currentPolicy.GetBool("useLower") == true)
{
enforcedOptions.UseLowercase = true;
}
if (currentPolicy.GetBool("useNumbers") == true)
{
enforcedOptions.UseNumbers = true;
}
var minNumbers = currentPolicy.GetInt("minNumbers");
if (minNumbers > enforcedOptions.NumberCount)
{
enforcedOptions.NumberCount = minNumbers.Value;
}
if (currentPolicy.GetBool("useSpecial") == true)
{
enforcedOptions.UseSpecial = true;
}
var minSpecial = currentPolicy.GetInt("minSpecial");
if (minSpecial > enforcedOptions.SpecialCount)
{
enforcedOptions.SpecialCount = minSpecial.Value;
}
var minNumberWords = currentPolicy.GetInt("minNumberWords");
if (minNumberWords > enforcedOptions.MinNumberOfWords)
{
enforcedOptions.MinNumberOfWords = minNumberWords.Value;
}
if (currentPolicy.GetBool("capitalize") == true)
{
enforcedOptions.Capitalize = true;
}
if (currentPolicy.GetBool("includeNumber") == true)
{
enforcedOptions.IncludeNumber = true;
return (bool)value;
}
}
return enforcedOptions;
return null;
}
}
}

View File

@@ -1280,16 +1280,6 @@ namespace Bit.Core.Services
await SetValueAsync(Constants.PreLoginEmailKey, value, options);
}
public ConfigResponse GetConfigs()
{
return _storageMediatorService.Get<ConfigResponse>(Constants.ConfigsKey);
}
public void SetConfigs(ConfigResponse value)
{
_storageMediatorService.Save(Constants.ConfigsKey, value);
}
// Helpers
[Obsolete("Use IStorageMediatorService instead")]

View File

@@ -3,7 +3,6 @@ using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
namespace Bit.Core.Services
{

View File

@@ -75,7 +75,8 @@ namespace Bit.Core.Utilities
messagingService.Send("logout", extras);
return Task.CompletedTask;
});
var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService, cryptoFunctionService, policyService);
var passwordGenerationService = new PasswordGenerationService(cryptoService, stateService,
cryptoFunctionService, policyService);
var totpService = new TotpService(cryptoFunctionService);
var authService = new AuthService(cryptoService, cryptoFunctionService, apiService, stateService,
tokenService, appIdService, i18nService, platformUtilsService, messagingService, vaultTimeoutService,
@@ -87,7 +88,6 @@ namespace Bit.Core.Utilities
var userVerificationService = new UserVerificationService(apiService, platformUtilsService, i18nService,
cryptoService);
var usernameGenerationService = new UsernameGenerationService(cryptoService, apiService, stateService);
var configService = new ConfigService(apiService, stateService, logger);
Register<IConditionedAwaiterManager>(conditionedRunner);
Register<ITokenService>("tokenService", tokenService);
@@ -113,7 +113,6 @@ namespace Bit.Core.Utilities
Register<IKeyConnectorService>("keyConnectorService", keyConnectorService);
Register<IUserVerificationService>("userVerificationService", userVerificationService);
Register<IUsernameGenerationService>(usernameGenerationService);
Register<IConfigService>(configService);
}
public static void Register<T>(string serviceName, T obj)

View File

@@ -266,7 +266,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AppCenter.Crashes">
<Version>5.0.1</Version>
<Version>4.5.3</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>

View File

@@ -72,7 +72,6 @@ namespace Bit.iOS.Core.Controllers
UsernameCell.TextField.ReturnKeyType = UIReturnKeyType.Next;
UsernameCell.Button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
UsernameCell.Button.SetTitle(BitwardenIcons.Generate, UIControlState.Normal);
UsernameCell.Button.AccessibilityLabel = AppResources.GenerateUsername;
UsernameCell.Button.TouchUpInside += (sender, e) =>
{
LaunchUsernameGeneratorFlow();
@@ -87,7 +86,6 @@ namespace Bit.iOS.Core.Controllers
PasswordCell.TextField.ReturnKeyType = UIReturnKeyType.Next;
PasswordCell.Button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
PasswordCell.Button.SetTitle(BitwardenIcons.Generate, UIControlState.Normal);
PasswordCell.Button.AccessibilityLabel = AppResources.GeneratePassword;
PasswordCell.Button.TouchUpInside += (sender, e) =>
{
PerformSegue("passwordGeneratorSegue", this);

View File

@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Resources;
@@ -62,7 +61,7 @@ namespace Bit.iOS.Core.Services
};
}
public Task ShowLoadingAsync(string text, CancellationTokenSource cts = null, string cancelButtonText = null)
public Task ShowLoadingAsync(string text)
{
if (_progressAlert != null)
{
@@ -85,14 +84,6 @@ namespace Bit.iOS.Core.Services
_progressAlert = UIAlertController.Create(null, text, UIAlertControllerStyle.Alert);
_progressAlert.View.TintColor = UIColor.Black;
_progressAlert.View.Add(loadingIndicator);
if (cts != null)
{
_progressAlert.AddAction(UIAlertAction.Create(cancelButtonText ?? AppResources.Cancel, UIAlertActionStyle.Cancel, x =>
{
cts.Cancel();
result.TrySetResult(0);
}));
}
vc.PresentViewController(_progressAlert, false, () => result.TrySetResult(0));
return result.Task;

View File

@@ -1,5 +1,4 @@
using System;
using Bit.App.Resources;
using Bit.Core;
using Bit.iOS.Core.Controllers;
using Bit.iOS.Core.Utilities;
@@ -172,13 +171,10 @@ namespace Bit.iOS.Core.Views
var button = useSecondaryButton ? SecondButton : Button;
button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
button.SetTitle(BitwardenIcons.Eye, UIControlState.Normal);
button.AccessibilityLabel = AppResources.ToggleVisibility;
button.AccessibilityHint = AppResources.PasswordIsNotVisibleTapToShow;
button.TouchUpInside += (sender, e) =>
{
TextField.SecureTextEntry = !TextField.SecureTextEntry;
button.SetTitle(TextField.SecureTextEntry ? BitwardenIcons.Eye : BitwardenIcons.EyeSlash, UIControlState.Normal);
button.AccessibilityHint = TextField.SecureTextEntry ? AppResources.PasswordIsNotVisibleTapToShow : AppResources.PasswordIsVisibleTapToHide;
};
}

View File

@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>10.0</string>
<key>CFBundleDisplayName</key>
<string>Bitwarden</string>
<key>CFBundleName</key>

View File

@@ -242,7 +242,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AppCenter.Crashes">
<Version>5.0.1</Version>
<Version>4.5.3</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.AppExtension.CSharp.targets" />

View File

@@ -19,7 +19,7 @@
<key>CFBundleVersion</key>
<string>1</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>10.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionMainStoryboard</key>

View File

@@ -167,7 +167,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AppCenter.Crashes">
<Version>5.0.1</Version>
<Version>4.5.3</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>

View File

@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>10.0</string>
<key>CFBundleDisplayName</key>
<string>Bitwarden</string>
<key>CFBundleName</key>

View File

@@ -195,7 +195,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Essentials">
<Version>1.7.5</Version>
<Version>1.7.3</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />

View File

@@ -2,7 +2,7 @@ import Foundation
struct CipherMock {
static let ciphers:[Cipher] = [
Cipher(id: "0", name: "MySite", userId: "123123", login: Login(username: "test@testing.com", totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)),
Cipher(id: "0", name: "1933", userId: "123123", login: Login(username: "thisisatest@testing.com", totp: "otpauth://account?period=10&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)),
Cipher(id: "1", name: "GitHub", userId: "123123", login: Login(username: "thisisatest@testing.com", totp: "LLLLLLLLLLLLLLLL", uris: cipherLoginUris)),
Cipher(id: "2", name: "No user", userId: "123123", login: Login(username: nil, totp: "otpauth://account?period=10&digits=8&algorithm=sha256&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)),
Cipher(id: "3", name: "Site 2", userId: "123123", login: Login(username: "longtestemail000000@fastmailasdfasdf.com", totp: "otpauth://account?period=10&digits=7&algorithm=sha512&secret=LLLLLLLLLLLLLLLL", uris: cipherLoginUris)),

View File

@@ -34,34 +34,30 @@ class CipherDetailsViewModel: ObservableObject{
self.counter = self.period - mod
self.progress = Double(self.counter) / Double(self.period)
}
if mod == 0 || self.totpFormatted == "" {
do {
try self.regenerateTotp()
var totpF = try TotpService.shared.GetCodeAsync(key: self.key) ?? ""
if totpF.count > 4 {
let halfIndex = totpF.index(totpF.startIndex, offsetBy: totpF.count / 2)
totpF = "\(totpF[totpF.startIndex..<halfIndex]) \(totpF[halfIndex..<totpF.endIndex])"
}
DispatchQueue.main.async {
self.totpFormatted = totpF
}
} catch {
DispatchQueue.main.async {
self.totpFormatted = "error"
t.invalidate()
}
}
}
})
RunLoop.current.add(timer!, forMode: .common)
timer?.fire()
}
func stopGeneration() {
func stopGeneration(){
self.timer?.invalidate()
}
func regenerateTotp() throws {
var totpF = try TotpService.shared.GetCodeAsync(key: self.key) ?? ""
if totpF.count > 4 {
let halfIndex = totpF.index(totpF.startIndex, offsetBy: totpF.count / 2)
totpF = "\(totpF[totpF.startIndex..<halfIndex]) \(totpF[halfIndex..<totpF.endIndex])"
}
DispatchQueue.main.async {
self.totpFormatted = totpF
}
}
}

View File

@@ -2,7 +2,6 @@ import SwiftUI
struct CipherDetailsView: View {
@ObservedObject var cipherDetailsViewModel: CipherDetailsViewModel
@Environment(\.scenePhase) var scenePhase
let iconSize: CGSize = CGSize(width: 30, height: 30)
@@ -50,7 +49,6 @@ struct CipherDetailsView: View {
.fontWeight(.bold)
.lineLimit(1)
.truncationMode(.tail)
.privacySensitive()
}
if cipherDetailsViewModel.totpFormatted == "" {
ProgressView()
@@ -63,7 +61,6 @@ struct CipherDetailsView: View {
.minimumScaleFactor(0.01)
.lineLimit(1)
.id(cipherDetailsViewModel.totpFormatted)
.privacySensitive()
.transition(transition)
.animation(.default.speed(0.7), value: cipherDetailsViewModel.totpFormatted)
Spacer()
@@ -73,7 +70,6 @@ struct CipherDetailsView: View {
Text("\(cipherDetailsViewModel.counter)")
.font(.title3)
.fontWeight(.semibold)
.privacySensitive()
}
}
.padding(.top, 20)
@@ -87,11 +83,6 @@ struct CipherDetailsView: View {
.onDisappear{
self.cipherDetailsViewModel.stopGeneration()
}
.onChange(of: scenePhase) { newPhase in
if newPhase == .active {
try? self.cipherDetailsViewModel.regenerateTotp()
}
}
}
var iconPlaceholderImage: some View{

View File

@@ -36,7 +36,6 @@ struct CipherItemView: View {
.truncationMode(.tail)
.foregroundColor(Color.ui.darkTextMuted)
.frame(maxWidth: .infinity, alignment: .leading)
.privacySensitive()
}
}
.padding()

View File

@@ -87,7 +87,6 @@ struct CipherListView: View {
.font(.headline)
.lineLimit(1)
.truncationMode(.tail)
.privacySensitive()
}
}

View File

@@ -118,55 +118,55 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Name" xml:space="preserve">
<value>बिटवार्डन पासवर्ड मैनेजर</value>
<value>Bitwarden पासवर्ड मैनेजर</value>
<comment>Max 30 characters</comment>
</data>
<data name="Description" xml:space="preserve">
<value>बिटवार्डन अंतरराष्ट्रीय कॉरपोरेशन, 8बिट सॉल्यूश्नस एलएलसी की मूल कंपनी है।
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
द वर्ज, यूएस न्यूज़ एंड वर्ल्ड रिपोर्ट, सीनेट, और कई दूसरे मीडिया संगठन द्वारा बोला गया दुनिया का सबसे बेहतरीन पासवर्ड मैनेजर।
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
अनगिनत पासवर्ड मैनेज, स्टोर, महफूज़, और शेयर करें कही से भी। बिटवार्डन देता है ओपन सोर्स पासवर्ड मैनेजमेंट सुविधा सबको, चाहे वो घर पर हो, दफ्तर पर हो, या घूम रहे हो।
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
बिटवार्डन सेंड किसी को भी एन्क्रिप्टेड जानकारी, फाइल और सादा टेक्सट, तुरंत भेजें।
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
बिटवार्डन कंपनियों के लिए टीम और बिज़नेस प्लान भी देता है ताकि आप अपने साथ काम करनेवालो के साथ पासवर्ड शेयर करे सुरक्षित होकर।
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
बिटवार्डन को क्यों चुनें:
Why Choose Bitwarden:
ताकतवर एन्क्रिप्शन
पासवर्ड एडवांस एंड-टू-एंड एन्क्रिप्शन (एईएस-256 बिट, सॉल्टेड हैशटैग, और पीबीकेडीएफ2 शा-256) के साथ सुरक्षित रखा जाता है ताकि आपका डाटा महफूज़ और निजी रहे।
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
पहले से बना पासवर्ड जेनरेटर
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
अंतरराष्ट्रीय अनुवाद
40 से ज़्यादा भाषा में बिटवार्डन इस्तेमाल करें, जिसे लिखा है हमारी अंतरराष्ट्रीय दोस्तो ने।
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
कई प्लेनफॉर्म पर मौजूद
अपने बिटवार्डन तिजोरी से संवेदनशील डाटा महफूज़ और शेयर करें किसी भी ब्राउज़र, फोन, या डेस्कटॉप जैसे डिवाइसो से।
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="Keywords" xml:space="preserve">
<value>बिटवर्डन, 8 बिट, पासवर्ड, मुफ्त पासवर्ड मैनेजर, पासवर्ड मैनेजर, लॉगन मैनेजर</value>
<value>बिटवर्डन, 8 बिट, पासवर्ड, फ्री पासवर्ड मैनेजर, पासवर्ड मैनेजर, लॉगिन मैनेजर</value>
<comment>Max 100 characters</comment>
</data>
<data name="Screenshot1" xml:space="preserve">
<value>एक सुरक्षित तिजोरी से अपने सारे लॉगन और पासवर्ड मैनेज करें</value>
<value>एक सुरक्षित तिजोरी से अपने सभी लॉगिन और पासवर्ड प्रबंधित करें</value>
</data>
<data name="Screenshot2" xml:space="preserve">
<value>अपनेआप ताकतवर, बेतरतीब, और महफूज़ पासवर्ड बनाएं</value>
<value>स्वचालित रूप से मजबूत, यादृच्छिक और सुरक्षित पासवर्ड उत्पन्न करते हैं</value>
</data>
<data name="Screenshot3" xml:space="preserve">
<value>टच आईडी, पिन कोड, या मुख्य पासवर्ड से अपनी तिजोरी सुरक्षित रखें</value>
<value>टच आईडी, पिन कोड या मास्टर पासवर्ड से अपनी तिजोरी को सुरक्षित रखें</value>
</data>
<data name="Screenshot4" xml:space="preserve">
<value>सफारी, क्रोम, और सैकड़ों दूसरे ऐप से अपनेआप भरकर लॉगन करें</value>
<value>सफारी, क्रोम और अन्य सैकड़ों ऐप्स से ऑटो-फिल लॉगिन करें</value>
</data>
<data name="Screenshot5" xml:space="preserve">
<value>अपने तिजोरी को अलग-अलग डिवाइसो से सिंक और एक्सेस करें</value>
<value>कई उपकरणों से अपने Vault को सिंक और एक्सेस करें</value>
</data>
</root>

View File

@@ -122,50 +122,51 @@
<comment>Max 30 characters</comment>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden, Inc. je matično podjetje podjetja 8bit Solutions LLC.
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
NAJBOŠJI UPRAVLJALNIK GESEL PO MNEJU THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET IN DRUGIH.
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
Upravljajte, shranjujte, varujte in delite neomejeno število gesel na neomejenem številu naprav, kjerkoli. Bitwarden ponuja odprtokodne rešitve za upravljanje gesel vsem, tako doma kot v službi ali na poti.
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
Za vas ustvari močna, edinstvena in naključna gesla, skladna z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete.
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
S pošiljkami Bitwarden Send hitro prenesite šifrirane informacije --- datoteke in navadno besedilo -- neposredno komurkoli.
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
Bitwarden ponuja storitvi za organizacije Teams in Enterprise, s katerima lahko gesla varno souporabljate s sodelavci.
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
Zakaj izbrati Bitwarden:
Why Choose Bitwarden:
Vrhunsko šifriranje
Gesla so zaščitena z naprednim šifriranjem (AES-256, soljene hash-vrednosti in PBKDF2 SHA-256), tako da vaši podatki ostanejo varni in zasebni.
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
Vgrajen generator gesel
Ustvarite močna, edinstvena in naključna gesla v skladu z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete.
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Prevodi za ves svet
Bitwarden je preveden že v 40 jezikov, naša globalna skupnost pa ves čas posodabljan in ustvarja nove prevede.
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
Deluje na vseh platformah
Varujte in souporabljajte svoje občutljive podatke znotraj vašega Bitwarden trezorja v katerem koli brskalniku, mobilni napravi, namiznem računalniku in drugje.</value>
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="Keywords" xml:space="preserve">
<value>bit warden,8bit,password,free password manager,password manager,login manager,upravljalnik gesel,shranjevalnik gesel,geslo,upravljalnik prijav</value>
<value>bit warden,8bit,password,free password manager,password manager,login manager</value>
<comment>Max 100 characters</comment>
</data>
<data name="Screenshot1" xml:space="preserve">
<value>Urejajte vse svoje prijavne podatke in gesla v zavarovanem trezorju</value>
<value>Manage all your logins and passwords from a secure vault</value>
</data>
<data name="Screenshot2" xml:space="preserve">
<value>Samodejno ustvari močna, naključna in varna gesla</value>
<value>Automatically generate strong, random, and secure passwords</value>
</data>
<data name="Screenshot3" xml:space="preserve">
<value>Zaščitite svoj trezor s pristnim odtisom, PIN-kodo ali glavnim geslom</value>
<value>Protect your vault with Touch ID, PIN code, or master password</value>
</data>
<data name="Screenshot4" xml:space="preserve">
<value>Samodejno izpolnjevanje prijav v aplikacijah Safari, Chrome in stotinah drugih</value>
<value>Auto-fill logins from Safari, Chrome, and hundreds of other apps</value>
</data>
<data name="Screenshot5" xml:space="preserve">
<value>Sinhronizirajte svoj trezor gesel in dostopajte do njega z več naprav</value>
<value>Sync and access your vault from multiple devices</value>
</data>
</root>

View File

@@ -118,61 +118,61 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Title" xml:space="preserve">
<value>बिटवार्डन पासवर्ड मैनेजर</value>
<value>bitwarden Password Manager</value>
<comment>Max 30 characters</comment>
</data>
<data name="ShortDescription" xml:space="preserve">
<value>बिटवाडर्न एक लॉगइन और पासवर्ड मैनेजर है जो आपको ऑनलाइन महफूज़ रखता है।</value>
<value>bitwarden is a login and password manager that helps keep you safe while online.</value>
<comment>Max 80 characters</comment>
</data>
<data name="FullDesciption" xml:space="preserve">
<value>बिटवार्डन अंतरराष्ट्रीय कॉरपोरेशन, 8बिट सॉल्यूश्नस एलएलसी की मूल कंपनी है।
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
द वर्ज, यूएस न्यूज़ एंड वर्ल्ड रिपोर्ट, सीनेट, और कई दूसरे मीडिया संगठन द्वारा बोला गया दुनिया का सबसे बेहतरीन पासवर्ड मैनेजर।
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
अनगिनत पासवर्ड मैनेज, स्टोर, महफूज़, और शेयर करें कही से भी। बिटवार्डन देता है ओपन सोर्स पासवर्ड मैनेजमेंट सुविधा सबको, चाहे वो घर पर हो, दफ्तर पर हो, या घूम रहे हो।
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
बिटवार्डन सेंड किसी को भी एन्क्रिप्टेड जानकारी, फाइल और सादा टेक्सट, तुरंत भेजें।
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
बिटवार्डन कंपनियों के लिए टीम और बिज़नेस प्लान भी देता है ताकि आप अपने साथ काम करनेवालो के साथ पासवर्ड शेयर करे सुरक्षित होकर।
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
बिटवार्डन को क्यों चुनें:
Why Choose Bitwarden:
ताकतवर एन्क्रिप्शन
पासवर्ड एडवांस एंड-टू-एंड एन्क्रिप्शन (एईएस-256 बिट, सॉल्टेड हैशटैग, और पीबीकेडीएफ2 शा-256) के साथ सुरक्षित रखा जाता है ताकि आपका डाटा महफूज़ और निजी रहे।
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
पहले से बना पासवर्ड जेनरेटर
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
अंतरराष्ट्रीय अनुवाद
40 से ज़्यादा भाषा में बिटवार्डन इस्तेमाल करें, जिसे लिखा है हमारी अंतरराष्ट्रीय दोस्तो ने।
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
कई प्लेनफॉर्म पर मौजूद
अपने बिटवार्डन तिजोरी से संवेदनशील डाटा महफूज़ और शेयर करें किसी भी ब्राउज़र, फोन, या डेस्कटॉप जैसे डिवाइसो से।
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="FeatureGraphic" xml:space="preserve">
<value>आपके सारे डिवाइसो के लिए एक सुरक्षित और मुफ्त पासवर्ड मैनेजर</value>
<value>आपके सभी उपकरणों के लिए एक सुरक्षित और मुफ्त पासवर्ड प्रबंधक</value>
</data>
<data name="Screenshot1" xml:space="preserve">
<value>एक सुरक्षित तिजोरी से अपने सारे लॉगन और पासवर्ड मैनेज करें</value>
<value>एक सुरक्षित तिजोरी से अपने सभी लॉगिन और पासवर्ड प्रबंधित करें</value>
</data>
<data name="Screenshot2" xml:space="preserve">
<value>अपनेआप ताकतवर, बेतरतीब, और महफूज़ पासवर्ड बनाएं</value>
<value>स्वचालित रूप से मजबूत, यादृच्छिक और सुरक्षित पासवर्ड उत्पन्न करते हैं</value>
</data>
<data name="Screenshot3" xml:space="preserve">
<value>फिंगरप्रिंट, पिन कोड, या मुख्य पासवर्ड से अपनी तिजोरी सुरक्षित रखें</value>
<value>टच आईडी, पिन कोड या मास्टर पासवर्ड से अपनी तिजोरी को सुरक्षित रखें</value>
</data>
<data name="Screenshot4" xml:space="preserve">
<value>अपने वेब ब्राउज़र और दूसरे ऐप से जल्दी लॉगन करें</value>
<value>अपने वेब ब्राउज़र और अन्य एप्लिकेशन के भीतर से जल्दी से लॉगिन करें</value>
</data>
<data name="Screenshot5" xml:space="preserve">
<value>अपने तिजोरी को अलग-अलग डिवाइसों से सिंक और एक्सेस करें
<value>कई उपकरणों से अपने वॉल्ट को सिंक और एक्सेस करें
- फोन
- फोन
- टैबलेट
- डेस्कटॉप
- वेब</value>

View File

@@ -118,61 +118,61 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Title" xml:space="preserve">
<value>Bitwarden - upravitelj gesel</value>
<value>Bitwarden shranjevalnik gesel</value>
<comment>Max 30 characters</comment>
</data>
<data name="ShortDescription" xml:space="preserve">
<value>Bitwarden je upravitelj prijavnih podatkov in gesel, ki vam pomaga ohraniti varnost na spletu.</value>
<value>Bitwarden je shranjevalnik dostopnih podatkov in gesel, ki vam pomaga ostati varen na spletu.</value>
<comment>Max 80 characters</comment>
</data>
<data name="FullDesciption" xml:space="preserve">
<value>Bitwarden, Inc. je matično podjetje podjetja 8bit Solutions LLC.
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
NAJBOŠJI UPRAVLJALNIK GESEL PO MNEJU THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET IN DRUGIH.
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
Upravljajte, shranjujte, varujte in delite neomejeno število gesel na neomejenem številu naprav, kjerkoli. Bitwarden ponuja odprtokodne rešitve za upravljanje gesel vsem, tako doma kot v službi ali na poti.
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
Za vas ustvari močna, edinstvena in naključna gesla, skladna z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete.
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
S pošiljkami Bitwarden Send hitro prenesite šifrirane informacije --- datoteke in navadno besedilo -- neposredno komurkoli.
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
Bitwarden ponuja storitvi za organizacije Teams in Enterprise, s katerima lahko gesla varno souporabljate s sodelavci.
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
Zakaj izbrati Bitwarden:
Why Choose Bitwarden:
Vrhunsko šifriranje
Gesla so zaščitena z naprednim šifriranjem (AES-256, soljene hash-vrednosti in PBKDF2 SHA-256), tako da vaši podatki ostanejo varni in zasebni.
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
Vgrajen generator gesel
Ustvarite močna, edinstvena in naključna gesla v skladu z varnostnimi zahtevami za vsako spletno mesto, ki ga obiščete.
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
Prevodi za ves svet
Bitwarden je preveden že v 40 jezikov, naša globalna skupnost pa ves čas posodabljan in ustvarja nove prevede.
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
Deluje na vseh platformah
Varujte in souporabljajte svoje občutljive podatke znotraj vašega Bitwarden trezorja v katerem koli brskalniku, mobilni napravi, namiznem računalniku in drugje.</value>
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="FeatureGraphic" xml:space="preserve">
<value>Varen in brezplačen upravitelj gesel za vse vaše naprave</value>
<value>Varen in brezplačen shranjevalnik gesel za vse vaše naprave</value>
</data>
<data name="Screenshot1" xml:space="preserve">
<value>Urejajte vse svoje prijavne podatke in gesla v zavarovanem trezorju</value>
<value>Urejate vse svoje dostopne podatke in gesla iz varnega sefa</value>
</data>
<data name="Screenshot2" xml:space="preserve">
<value>Samodejno ustvari močna, naključna in varna gesla</value>
<value>Samodejni ustvari močna, naključna in varna gesla</value>
</data>
<data name="Screenshot3" xml:space="preserve">
<value>Zaščitite svoj trezor s pristnim odtisom, PIN-kodo ali glavnim geslom</value>
<value>Zaščitite svoj sef s pristnim odtisom, kodo PIN ali glavnim geslom</value>
</data>
<data name="Screenshot4" xml:space="preserve">
<value>Hitro samodejno vnašanje prijavnih podatkov na spletu in v drugih aplikacijah</value>
<value>Hitro vnašanje prijavnih podatkov na spletu in v drugih aplikacijah</value>
</data>
<data name="Screenshot5" xml:space="preserve">
<value>Dostopajte do svojega sefa z različnih naprav:
- Telefon
<value>- Telefon
- Tablica
- Računalnik
- Namizje
- Splet</value>
</data>
</root>

View File

@@ -7,15 +7,15 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="NSubstitute" Version="4.4.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.0" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.18.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
</ItemGroup>
</Project>

View File

@@ -7,15 +7,15 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="NSubstitute" Version="4.4.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.0" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.18.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.17.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -14,7 +14,7 @@ namespace Bit.Core.Test.Models.Request
{
[Theory]
[InlineCustomAutoData(new[] { typeof(TextSendCustomization) }, null)]
[InlineCustomAutoData(new[] { typeof(FileSendCustomization) }, 100L)]
[InlineCustomAutoData(new[] { typeof(FileSendCustomization) }, 100)]
public void SendRequest_FromSend_Success(long? fileLength, Send send)
{
var request = new SendRequest(send, fileLength);