diff options
author | Saturneric <[email protected]> | 2021-07-20 16:42:50 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-07-20 16:42:50 +0000 |
commit | c57feb6a678e27140bb9ae7d132b641947514c31 (patch) | |
tree | 5ed7a7728c084214ce858323a4eccdcba98200b6 | |
parent | Update Workflow (diff) | |
parent | Fix problem that macos cannot use multi-languages. (diff) | |
download | GpgFrontend-c57feb6a678e27140bb9ae7d132b641947514c31.tar.gz GpgFrontend-c57feb6a678e27140bb9ae7d132b641947514c31.zip |
Merge branch 'develop' into develop-ci
Diffstat (limited to '')
127 files changed, 26109 insertions, 6867 deletions
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..c50377b9 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,128 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + schedule: + - cron: '19 14 * * 2' + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Debug + EXECUTABLE_OUTPUT_PATH: ./ + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + - name: Install Dependence (Linux) + run: | + sudo apt-get update + sudo apt-get -y install build-essential binutils git autoconf automake gettext texinfo + sudo apt-get -y install gcc g++ + sudo apt-get -y install gpgsm + - name: Cache Qt + id: cache-qt + uses: actions/cache@v1 + with: + path: ../Qt + key: ${{ runner.os }}-QtCache + + - name: Install Qt + uses: jurplel/install-qt-action@v2 + with: + cached: ${{ steps.cache-qt.outputs.cache-hit }} + + - name: Build gpg-error (Linux) + run: | + cd ${{github.workspace}}/.. + git clone https://github.com/saturneric/libgpg-error + cd libgpg-error + ./autogen.sh + ./configure --enable-maintainer-mode --enable-static=yes && make -j2 + sudo make install + cd ${{github.workspace}} + + - name: Build assuan (Linux) + run: | + cd ${{github.workspace}}/.. + git clone https://github.com/saturneric/libassuan + cd libassuan + ./autogen.sh + ./configure --enable-maintainer-mode --enable-static=yes && make -j2 + sudo make install + cd ${{github.workspace}} + + - name: Build GpgME (Linux) + run: | + cd ${{github.workspace}}/.. + git clone https://github.com/saturneric/gpgme + cd gpgme + ./autogen.sh + ./configure --enable-maintainer-mode --enable-static=yes --enable-languages=cpp && make -j2 + sudo make install + cd ${{github.workspace}} + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DEXECUTABLE_OUTPUT_PATH=${{env.EXECUTABLE_OUTPUT_PATH}} + + - name: Build GpgFrontend + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml index 2de9716c..11194af0 100644 --- a/.github/workflows/debug.yml +++ b/.github/workflows/debug.yml @@ -123,7 +123,7 @@ jobs: - name: Build GpgFrontend # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config $env.BUILD_TYPE}} -- -j 2 + run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2 if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' - name: Configure CMake & Build Binary(Windows) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8ec9f553..6a67d524 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,7 @@ jobs: shell: msys2 {0} run: | pacman --noconfirm -S --needed mingw-w64-x86_64-gcc mingw-w64-x86_64-make mingw-w64-x86_64-cmake autoconf automake mingw-w64-x86_64-qt-creator mingw-w64-x86_64-gpgme - pacman --noconfirm -S --needed make texinfo + pacman --noconfirm -S --needed make texinfo zip if: matrix.os == 'windows-latest' - name: Build gpg-error (Linux) @@ -142,9 +142,13 @@ jobs: - name: Build GpgFrontend # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config $env.BUILD_TYPE}} -- -j 2 + run: cmake --build ${{github.workspace}}/build --config {{$env.BUILD_TYPE}} -- -j 2 if: matrix.os == 'ubuntu-16.04' || matrix.os == 'macos-latest' + - name: Get Short SHA of Commit + id: vars + run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" + - name: Package App Bundle (macOS) run: | macdeployqt ${{github.workspace}}/build/release/GpgFrontend.app @@ -154,12 +158,13 @@ jobs: mkdir ${{github.workspace}}/build/artifactOut hdiutil convert ${{github.workspace}}/build/tmp/tmp.dmg -format UDZO -o ${{github.workspace}}/build/artifactOut/GpgFrontend.dmg codesign -s "Developer ID Application: Yu Hu (4279AWUL3X)" GpgFrontend.dmg + mv ${{github.workspace}}/build/artifactOut/GpgFrontend.dmg ${{github.workspace}}/build/artifactOut/GpgFrontend-${{steps.vars.outputs.sha_short}}-x86_64.dmg if: matrix.os == 'macos-latest' - name: Notarize Release Build (macOS) uses: devbotsxyz/xcode-notarize@v1 with: - product-path: "Export/Rings.app" + product-path: ${{github.workspace}}/build/artifactOut/GpgFrontend-${{steps.vars.outputs.sha_short}}-x86_64.dmg appstore-connect-username: ${{ secrets.APPLE_DEVELOPER_ID }} appstore-connect-password: ${{ secrets.APPLE_DEVELOPER_ID_SECRET }} if: matrix.os == 'macos-latest' @@ -173,7 +178,7 @@ jobs: ./linuxdeployqt-continuous-x86_64.AppImage ${{github.workspace}}/build/release/gpgfrontend/usr/share/applications/*.desktop -appimage if: matrix.os == 'ubuntu-16.04' - - name: Configure CMake & Build Binary(Windows) + - name: Configure CMake & Build Binary (Windows) shell: msys2 {0} run: | cd $(echo "/${{github.workspace}}" | sed 's/\\/\//g' | sed 's/://') @@ -183,10 +188,6 @@ jobs: cmake --build . --config ${{env.BUILD_TYPE}} -- -j 2 if: matrix.os == 'windows-latest' - - name: Get Short SHA of Commit - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - name: Upload Artifact(Linux) uses: actions/upload-artifact@master with: @@ -1,5 +1,6 @@ # Project include/GpgFrontend.h +include/GpgFrontendBuildInfo.h #CLion .idea/* diff --git a/CMakeLists.txt b/CMakeLists.txt index c11b26af..f80087c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(GpgFrontend VERSION 1.1.0 LANGUAGES CXX) +project(GpgFrontend VERSION 1.2.2 LANGUAGES CXX) message(STATUS "GPGFrontend Build Configuration Started CMAKE Version ${CMAKE_VERSION}") @@ -5,28 +5,28 @@    -[](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&utm_medium=referral&utm_content=saturneric/GpgFrontend&utm_campaign=Badge_Grade) +[](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&utm_medium=referral&utm_content=saturneric/GpgFrontend&utm_campaign=Badge_Grade)  [](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_small) -GpgFrontend is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free [OpenPGP](https://www.openpgp.org/) +GpgFrontend is a Powerful, Easy-to-Use, Compact, Cross-Platform, and +Installation-Free [OpenPGP](https://www.openpgp.org/) Crypto Tool. -By using GpgFrontend, you can quickly **encrypt and decrypt text or files**. Or at the same time as the above -operations, you can add **your own signature** to let others know that this document or this paragraph of text was -issued by you. It aims to allow ordinary users to quickly use gpg and make professional users more convenient. -GpgFrontend supports new features of OpenPGP. +By using GpgFrontend, you can quickly encrypt and decrypt text or files. Or at the same time as the above operations, +you can add your own signature to let others know that this document or this paragraph of text was issued by you. +Please **take the initiative to protect privacy in your own hands**, instead of relying on servers and algorithms +provided by large companies. **Notice:** GpgFrontend does not provide an embedded [gnupg](https://gnupg.org/) binary library and needs to be -installed by the user. **This is to ensure safety and avoid code or binary files involved in encryption and decryption being implanted in the backdoor during -the delivery process.** +installed by the user. **This is to ensure safety and avoid code or binary files involved in encryption and decryption +being implanted in the backdoor during the delivery process.** -[>> Quick Start](#quick-start) - -[>> Code & Binary Security](https://saturneric.github.io/GpgFrontend/index.html#/about/code-binary-verify) - -[>> 中文文档](https://github.com/saturneric/GpgFrontend/blob/main/README_CN.md) +If you find this tool useful and promising, welcome to encourage me through STAR this project. Thanks! +[>> Quick Start <<](#quick-start) | +[>> Code & Binary Security <<](https://gpgfrontend.pub/#/about/code-binary-verify) | +[>> 简中README <<](https://github.com/saturneric/GpgFrontend/blob/main/README_CN.md) <div align="center"> <img width="640" src="https://github.com/saturneric/Blob/blob/master/screenshots/main_mac.jpg?raw=true" alt="macOS Screenshot"/> @@ -54,6 +54,7 @@ the delivery process.** - [Document](#document) - [Purpose](#purpose) - [Build](#build) +- [Languages Support](#languages-support) - [Contributing & Bugs Report](#contributing--bugs-report) - [Contract](#contract) - [Maintainers](#maintainers) @@ -64,44 +65,48 @@ the delivery process.** - Can run on **Windows, Linux and macOS**. - Open source, free, no need to install. - Just double-click, and then you can use it freely. -- Supports multiple languages. - - If you are interested, you can help - me [translate the interface](https://saturneric.github.io/GpgFrontend/index.html#/translate-interface). +- Supports multiple [languages](#languages-support). ## Usage ### Quick Start -### Fast encryption +### Fast Text Encryption Encryption can be done in just a few clicks.  -### Fast Decryption +### Fast Text Decryption I want to see what you wrote right away.  +### Fast File Encryption & Sign + +What about files? + + + ### More Helpful Operation -Read the animated pictures in the [Document](https://saturneric.github.io/GpgFrontend/index.html#/) to learn more -awesome operations. +Read the animated pictures in the [Document](https://gpgfrontend.pub/#/quick-start) to learn more awesome operations. ### How to Run it #### Windows -1. [Download](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) `gnupg-w32-******.exe` -2. Double Click it to install it -3. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from the latest release -4. Unzip `gpgfrontend-windows-latest-*******.zip` -5. Go into the directory and double click `GpgFrontend.exe`. +0. If you haven't installed gnupg, + please [Download](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) `gnupg-w32-******.exe` and + install it. +1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from the latest release +2. Unzip `gpgfrontend-windows-latest-*******.zip` +3. Go into the directory and double click `GpgFrontend.exe`. #### macOS -0. If command `gpg` is not avaliable, please use homebrew to install it first. +0. If command `gpg` is not available, please use homebrew to install it first. 1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) macOS edition from the latest release 2. Double-Click GpgFrontend.dmg to load it - macOS will automatically decompress the zip file and then you will be able to see the dmg @@ -111,28 +116,28 @@ awesome operations. #### Debian/Ubuntu/CentOS -1. Install gnupg (If you have already followed please skip) +[](https://github.com/saturneric/GpgFrontend/releases/latest) + +0. Install gnupg (If you have already followed please skip) - For Debian/Ubuntu - ```shell - $ sudo apt update - $ sudo apt install gpg - ``` + ```shell + $ sudo apt update + $ sudo apt install gpg + ``` - For CentOS ```shell $ sudo yum install gnupg ``` -2. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Linux edition from the latest release -3. Unzip gpgfrontend-ubuntu-16.04-*******.zip - - `ubuntu-16.04` shows that Linux distributions at the same time as 16.04 or later are supported. -4. Give `GpgFrontend-***.AppImage` permission to execute +1. [Download GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Linux edition from the latest release +2. Give `GpgFrontend-***.AppImage` permission to execute ```shell $ chmod u+x ./GpgFrontend-***.AppImage ``` -5. Just double-click `GpgFrontend-***.AppImage` to run it. +3. Just double-click `GpgFrontend-***.AppImage` to run it. ## Document -For more usage information, please read [Document](https://saturneric.github.io/GpgFrontend/index.html#/). +for more usage information, please read [document](https://gpgfrontend.pub/#/overview). ## Purpose @@ -149,7 +154,26 @@ The GpgFrontend project is as open source, and it also insists on using open sou ## Build -The tutorial for building the software will be released shortly. Before the relevant documents are released, you can refer to the project-related Github Action file if you know it. +The tutorial for building the software will be released shortly. Before the relevant documents are released, you can +refer to the project-related Github Action file if you know it. + +## Languages Support + +The supported languages are listed here. Some languages use machine translation and have not been verified. If you want +to join translation and verification work, please refer to +the [translate the interface](https://gpgfrontend.pub/#/translate-interface). + +Notice: The verification may not be complete and rigorous. + +| Language | English | 简体中文 | français | Французский | Español | +| ---- | ---- | ---- | ---- | ---- | ---- | +| Support | Support | 支持 | Etre prêt | ожидать | apoyar | +| Verification | Origin | 不完全 | Jamais |Никогда | Nunca | + +| Language | 日本語 | 繁體中文 | عربى | português | +| ---- | ---- | ---- | ---- | ---- | +| Support | 未だに | 尚未 | ليس بعد | Ainda não | +| Verification | | | | | ## Contract @@ -171,19 +195,30 @@ Feel free to dive in! [Open an issue](https://github.com/saturneric/GpgFrontend/ GpgFrontend itself is licensed under the [GPLv3](COPYING). +[](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_large) + +### Dependency + There are some libraries and binary included in the zip-file which (may) have different licenses, for more information check their homepages. You can also obtain the sources from there. -gpg4usb: https://www.gpg4usb.org/ +gnupg: https://gnupg.org/ -Gnupg: https://gnupg.org/ +gpg4usb: https://www.gpg4usb.org/ -QT: https://www.qt.io/ +QT 5.15.2(opensource): https://www.qt.io/ MSYS2: https://www.msys2.org/ mingw-w64: http://mingw-w64.org/doku.php -The icons of this software use materials from Alibaba vector icon library. The Alibaba vector icon library is free to -use. The icons in the free library aren't registered as trademarks. There is no copyright issue involved and can be used -commercially. +AppImage: https://appimage.org/ + +rapidjson: https://github.com/Tencent/rapidjson + +Application +Bundles: [Link](https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1) + +The icons of this software use materials from [Alibaba Iconfont](!https://www.iconfont.cn/). The Alibaba vector icon +library is free to use. The icons in the free library aren't registered as trademarks. There is no copyright issue +involved and can be used commercially. diff --git a/README_CN.md b/README_CN.md index e2f524df..e86a62e3 100644 --- a/README_CN.md +++ b/README_CN.md @@ -5,20 +5,21 @@    -[](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&utm_medium=referral&utm_content=saturneric/GpgFrontend&utm_campaign=Badge_Grade) +[](https://www.codacy.com/gh/saturneric/GpgFrontend/dashboard?utm_source=github.com&utm_medium=referral&utm_content=saturneric/GpgFrontend&utm_campaign=Badge_Grade)  [](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_small) GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP](https://www.openpgp.org/) 加密解密签名工具。 -通过使用 GpgFrontend,你可以快速加密和解密文本或文件。或者在进行上述操作的同时加上自己的签名,让别人知道这个文件或者这段文字是出自你之手。 -该软件旨在让普通用户更快上手gpg工具,让专业用户更便捷。 GpgFrontend 支持 OpenPGP 的新特性。 +通过使用 GpgFrontend,你可以快速加密和解密文本或文件。或者在进行上述操作的同时加上自己的签名,让别人知道这个文件或者这段文字是出自你之手。 请将隐私保护的主动权掌握在自己手上,而不是依赖大公司提供的服务器和算法。 -注意:GpgFrontend 不提供嵌入式 gnupg 二进制库,需要用户自行安装。这是为了确保安全,避免代码或二进制文件在传递过程中被植入后门。 +注意:GpgFrontend 不提供嵌入式 gnupg 二进制库,需要用户自行安装。这是为了确保安全,避免涉及加密解密的代码或二进制文件在传递过程中被植入后门。 + +如果你觉得这款工具有用或者有希望,`欢迎通过STAR这个项目来鼓励我`。 [>> 快速开始](#quick-start) -[>> 代码与二进制文件安全](https://saturneric.github.io/GpgFrontend/index.html#/about/code-binary-verify) +[>> 代码与二进制文件安全](https://gpgfrontend.pub/#/about/code-binary-verify) <div align="center"> <img width="640" src="https://github.com/saturneric/Blob/blob/master/screenshots/main_mac.jpg?raw=true" alt="macOS Screenshot"/> @@ -47,8 +48,8 @@ GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP]( - [开发宗旨](#开发宗旨) - [构建方法](#构建方法) - [联系](#联系) - - [做出贡献](#做出贡献) - - [维护者](#维护者) + - [做出贡献或者报告问题](#做出贡献或者报告问题) + - [关于维护者](#关于维护者) - [许可证](#许可证) ## 软件特性 @@ -57,7 +58,7 @@ GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP]( - 开源,免费,无需安装。 - 只需双击即可自由使用。 - 支持多种语言。 - - 有兴趣的可以帮我 [翻译一下界面](https://saturneric.github.io/GpgFrontend/index.html#/translate-interface) 。 + - 有兴趣的可以帮我 [翻译一下界面](https://gpgfrontend.pub/#/translate-interface) 。 ## 使用方法 @@ -75,79 +76,81 @@ GpgFrontend 是一个易于使用、小巧、跨平台和免安装的 [OpenPGP](  +### 快速文件加密与签名 + +对于文件,我该怎么做? + + + ### 还有那些有用的操作 -阅读 [文档](https://saturneric.github.io/GpgFrontend/index.html#/) 中的动图,了解更多精彩操作。 +阅读 [文档](https://gpgfrontend.pub/#/quick-start) 中的动图,了解更多精彩操作。 ### 如何安装 #### Windows -1. [下载](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) gnupg-w32-******.exe -2. 双击安装 -3. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from release -4. 解压 gpgfrontend-windows-latest-*******.zip -5. 进入目录,双击运行 GpgFrontend.exe +0. 如果你还没有安装gnupg,请 [下载](https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.3.1_20210420.exe) gnupg-w32-**\*\***.exe 并双击安装 +1. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Windows Edition from release +2. 解压 gpgfrontend-windows-latest-**\*\*\***.zip +3. 进入目录,双击运行 GpgFrontend.exe #### macOS -0. 如果命令 `gpg` 不可用,请先用Homebrew安装它. +0. 如果命令 `gpg` 不可用,请先用 Homebrew 安装它. 1. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) macOS edition from release -2. 双击并加载 GpgFrontend.dmg +2. 双击并加载 GpgFrontend-***.dmg 3. 双击并运行 - (由于macOS的安全策略,在真正能运行前请遵照系统说明). -4. 如果你满意的话,可以将本软件复制到Application文件夹. + (由于 macOS 的安全策略,在真正能运行前请遵照系统说明). +4. 如果你满意的话,可以将本软件复制到 Application 文件夹. #### Debian/Ubuntu/CentOS 1. 安装 gnupg (如果你已经安装了请跳过) - For Debian/Ubuntu - ```shell - $ sudo apt update - $ sudo apt install gpg - ``` + ```shell + $ sudo apt update + $ sudo apt install gpg + ``` - For CentOS - ```shell - $ sudo yum install gnupg - ``` + ```shell + $ sudo yum install gnupg + ``` 2. [下载 GpgFrontend](https://github.com/saturneric/GpgFrontend/releases) Linux edition from the latest release -3. 解压 gpgfrontend-ubuntu-16.04-*******.zip - - `ubuntu-16.04` 说明ubuntu 16.04及其同时期与后来的Linux发行版都可以正常运行。 -4. 赋予 `GpgFrontend-***.AppImage` 执行权限 +3. 赋予 `GpgFrontend-***.AppImage` 执行权限 ```shell $ chmod u+x ./GpgFrontend-***.AppImage ``` -5. 双击运行 `GpgFrontend-***.AppImage`. +4. 双击运行 `GpgFrontend-***.AppImage`. ## 文档 -如果你想获取更多信息,请阅读 [文档](https://saturneric.github.io/GpgFrontend/index.html#/). +如果你想获取更多信息,请阅读 [文档](https://gpgfrontend.pub/#/overview). ## 开发宗旨 -GpgFrontend 项目继承自一个相对成熟但未维护的 [gpg4usb](https://www.gpg4usb.org/) 项目。 -它继承了 gpg4usb 稳定、易用、小巧、免安装的特点。 +GpgFrontend 项目继承自一个相对成熟但未维护的 [gpg4usb](https://www.gpg4usb.org/) 项目。 它继承了 gpg4usb 稳定、易用、小巧、免安装的特点。 -GpgFrontend 未来会增加更多功能,提高GPG在端到端传输中的易用性并缩短密文长度。同时,新功能的加入不影响旧的基础功能。 -我个人的力量总是有限的。 GpgFrontend 欢迎志愿者加入。你可以使用 GitHub 平台提交问题或提交pull request。 +GpgFrontend 未来会增加更多功能,提高 GPG 在端到端传输中的易用性并缩短密文长度。同时,新功能的加入不影响旧的基础功能。 我个人的力量总是有限的。 GpgFrontend 欢迎志愿者加入。你可以使用 GitHub +平台提交问题或提交 pull request。 GpgFrontend 项目作为开源项目,也坚持使用开源代码和库。 ## 构建方法 -构建软件的教程将很快发布。 +构建软件的教程将很快发布。你可以先查看本项目的 GitHub Action 文件。 ## 联系 -如果你想单独与我联系,你可以发送电子邮件到 [[email protected]](mailto:[email protected])。 +如果你想与我私下联系,你可以发送电子邮件到 [[email protected]](mailto:[email protected])。 -### 做出贡献 +### 做出贡献或者报告问题 -欢迎!你可以通过 [提出issue](https://github.com/saturneric/GpgFrontend/issues/new) 或提交 PR来做出贡献。 +欢迎!你可以通过 [提出 issue](https://github.com/saturneric/GpgFrontend/issues/new) 或提交 PR 来做出贡献。 -### 维护者 +### 关于维护者 -[@Saturneric](https://github.com/saturneric). +该项目的维护者是 [@Saturneric](https://github.com/saturneric). ## LOGO @@ -157,16 +160,27 @@ GpgFrontend 项目作为开源项目,也坚持使用开源代码和库。 GpgFrontend 在 [GPLv3](COPYING) 许可证下。 +[](https://app.fossa.com/projects/git%2Bgithub.com%2Fsaturneric%2FGpgFrontend?ref=badge_large) + +### 依赖 + 项目使用到了一些库和二进制文件,它们(可能)具有不同的许可证,请查看它们的主页获取更多信息。您也可以从那里获取相关信息。 -gpg4usb: https://www.gpg4usb.org/ +gnupg: https://gnupg.org/ -Gnupg: https://gnupg.org/ +gpg4usb: https://www.gpg4usb.org/ -QT: https://www.qt.io/ +QT 5.15.2(opensource): https://www.qt.io/ MSYS2: https://www.msys2.org/ mingw-w64: http://mingw-w64.org/doku.php -本软件图标使用来自阿里巴巴矢量图标库的素材。免费库中的图标未注册为商标。不涉及版权问题。
\ No newline at end of file +AppImage: https://appimage.org/ + +rapidjson: https://github.com/Tencent/rapidjson + +Application +Bundles: [Link](!https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1) + +本软件图标使用来自 [阿里巴巴矢量图标库](!https://www.iconfont.cn/) 的素材。免费库中的图标未注册为商标。不涉及版权问题。 diff --git a/gpgfrontend.qrc b/gpgfrontend.qrc index fce9f6bc..71513dbd 100644 --- a/gpgfrontend.qrc +++ b/gpgfrontend.qrc @@ -55,5 +55,7 @@ <file alias="mimetypes/unknown.png">resource/icons/mimetypes/unknown.png</file> <file alias="button_previous.png">resource/icons/button_previous.png</file> <file alias="button_next.png">resource/icons/button_next.png</file> + <file alias="refresh.png">resource/icons/refresh.png</file> + <file alias="up.png">resource/icons/up.png</file> </qresource> </RCC> diff --git a/include/GpgFrontend.h.in b/include/GpgFrontend.h.in index de88bab2..555f4589 100644 --- a/include/GpgFrontend.h.in +++ b/include/GpgFrontend.h.in @@ -1,3 +1,27 @@ +/** + * This file is part of GPGFrontend. + * + * GPGFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + #ifndef GPGFRONTEND_H_IN #define GPGFRONTEND_H_IN @@ -23,22 +47,8 @@ #define RELEASE 0 #define DEBUG 1 -#define PROJECT_NAME "@PROJECT_NAME@" -#define BUILD_VERSION "@BUILD_VERSION@" -#define GIT_VERSION "@GIT_VERSION@" #define OS_PLATFORM @OS_PLATFORM@ -#define BUILD_FLAG @BUILD_FLAG@ - -#define VERSION_MAJOR @CMAKE_PROJECT_VERSION_MAJOR@ -#define VERSION_MINOR @CMAKE_PROJECT_VERSION_MINOR@ -#define VERSION_PATCH @CMAKE_PROJECT_VERSION_PATCH@ - -#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@" - -#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@" -#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@" - #if OS_PLATFORM == MACOS && BUILD_FLAG == RELEASE # define RESOURCE_DIR(appDir) (appDir + "/../Resources/") #elif OS_PLATFORM == LINUX && BUILD_FLAG == RELEASE diff --git a/include/GpgFrontendBuildInfo.h b/include/GpgFrontendBuildInfo.h.in index 6e07a8bc..1da57de9 100644 --- a/include/GpgFrontendBuildInfo.h +++ b/include/GpgFrontendBuildInfo.h.in @@ -25,20 +25,19 @@ #ifndef GPGFRONTEND_BUILD_INFO_H_IN #define GPGFRONTEND_BUILD_INFO_H_IN -#define VERSION_MAJOR 1 -#define VERSION_MINOR 2 -#define VERSION_PATCH 2 +#define VERSION_MAJOR @CMAKE_PROJECT_VERSION_MAJOR@ +#define VERSION_MINOR @CMAKE_PROJECT_VERSION_MINOR@ +#define VERSION_PATCH @CMAKE_PROJECT_VERSION_PATCH@ -#define GIT_BRANCH_NAME "develop" -#define GIT_COMMIT_HASH "70053b17c76b010537a5c183621dc0c14e9e416e" +#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@" +#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@" -#define PROJECT_NAME "GpgFrontend" -#define BUILD_VERSION "1.2.2_Darwin-20.5.0_x86_64_Release" -#define GIT_VERSION "develop_70053b17c76b010537a5c183621dc0c14e9e416e" -#define OS_PLATFORM 1 +#define PROJECT_NAME "@PROJECT_NAME@" +#define BUILD_VERSION "@BUILD_VERSION@" +#define GIT_VERSION "@GIT_VERSION@" -#define BUILD_FLAG 0 +#define BUILD_FLAG @BUILD_FLAG@ -#define BUILD_TIMESTAMP "2021-07-20 21:56:45" +#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@" #endif // GPGFRONTEND_BUILD_INFO_H_IN diff --git a/include/MainWindow.h b/include/MainWindow.h index 418a56db..20f9a0b5 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -26,12 +26,11 @@ #define __GPGWIN_H__ #include "gpg/GpgConstants.h" -#include "ui/widgets/Attachments.h" #include "ui/KeyMgmt.h" #include "ui/widgets/TextEdit.h" #include "ui/FileEncryptionDialog.h" #include "ui/SettingsDialog.h" -#include "ui/AboutDialog.h" +#include "ui/help/AboutDialog.h" #include "ui/widgets/InfoBoardWidget.h" #include "ui/FindWidget.h" #include "ui/Wizard.h" @@ -217,6 +216,11 @@ private slots: void slotAbout(); /** + * @details Open check-update-tab in about-dialog. + */ + void slotCheckUpdate(); + + /** * @details Open File Opera Tab */ void slotOpenFileTab(); @@ -258,6 +262,11 @@ private slots: */ void slotSetRestartNeeded(bool needed); + /** + * @details called when need to upgrade. + */ + void slotVersionUpgrade(const QString ¤tVersion, const QString &latestVersion); + private: /** * @details Create actions for the main-menu and the context-menu of the keylist. @@ -363,6 +372,7 @@ private: QAction *zoomInAct; /** Action to zoom in */ QAction *zoomOutAct; /** Action to zoom out */ QAction *aboutAct; /** Action to open about dialog */ + QAction *checkUpdateAct; /** Action to open about dialog */ QAction *fileEncryptAct; /** Action to open dialog for encrypting file */ QAction *fileDecryptAct; /** Action to open dialog for decrypting file */ QAction *fileSignAct; /** Action to open dialog for signing file */ @@ -382,11 +392,12 @@ private: KeyList *mKeyList; InfoBoardWidget *infoBoard; - Attachments *mAttachments; /**< TODO */ - GpgME::GpgContext *mCtx; /**< TODO */ - KeyMgmt *keyMgmt; /**< TODO */ + GpgME::GpgContext *mCtx; + KeyMgmt *keyMgmt; KeyServerImportDialog *importDialog; /**< TODO */ + QNetworkAccessManager *networkAccessManager; + bool attachmentDockCreated; bool restartNeeded; }; diff --git a/include/Mime.h b/include/Mime.h deleted file mode 100644 index c86ac630..00000000 --- a/include/Mime.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#ifndef __MIME_H__ -#define __MIME_H__ - -#include <GpgFrontend.h> -#include <utility> - -class HeadElem { -public: - QString name; - QString value; - QHash<QString, QString> params; - - /* QDataStream & operator<<(QDataStream& Stream, const HeadElem& H) - { - return Stream << H.name << " : " << H.value; - }*/ - -}; - -class Header { -public: - QList<HeadElem> headElems; - - Header() = default; - - explicit Header(QList<HeadElem> heads) { - headElems = std::move(heads); - } - - [[maybe_unused]] void setHeader(QList<HeadElem> heads) { - headElems = std::move(heads); - } - - QString getValue(const QString &key) { - foreach(HeadElem tmp, headElems) { - //qDebug() << "gv: " << tmp.name << ":" << tmp.value; - if (tmp.name == key) - return tmp.value; - } - return ""; - } - - QHash<QString, QString> getParams(const QString &key) { - foreach(HeadElem tmp, headElems) { - //qDebug() << "gv: " << tmp.name << ":" << tmp.value; - if (tmp.name == key) - //return tmp.value; - return tmp.params; - } - return *(new QHash<QString, QString>()); - } - - QString getParam(const QString &key, const QString &pKey) { - foreach(HeadElem tmp, headElems) { - //qDebug() << "gv: " << tmp.name << ":" << tmp.value; - if (tmp.name == key) - return tmp.params.value(pKey); - } - return ""; - } - - -}; - -class MimePart { -public: - Header header; - QByteArray body; - - - - /* QDataStream & operator<<(QDataStream& Stream, const Part& P) - { - foreach(HeadElem tmp, header) { - Stream << tmp << "\n"; - } - return Stream; - }*/ -}; - -class Mime { - -public: - explicit Mime(QByteArray *message); // Constructor - ~Mime(); // Destructor - static bool isMultipart(QByteArray *message); - - static bool isMime(const QByteArray *message); - - QList<MimePart> parts() { - return mPartList; - } - - void splitParts(QByteArray *message); - - static Header getHeader(const QByteArray *message); - - static Header parseHeader(QByteArray *header); - - static void quotedPrintableDecode(const QByteArray &in, QByteArray &out); - -private: - QList<MimePart> mPartList; -}; - -#endif // __MIME_H__ diff --git a/include/gpg/GpgContext.h b/include/gpg/GpgContext.h index a2812b4e..fc4d8692 100644 --- a/include/gpg/GpgContext.h +++ b/include/gpg/GpgContext.h @@ -71,7 +71,7 @@ namespace GpgME { ~GpgContext() override; - bool isGood() const; + [[nodiscard]] bool isGood() const; GpgImportInformation importKey(QByteArray inBuffer); @@ -115,7 +115,7 @@ namespace GpgME { gpg_error_t sign(const QVector<GpgKey> &keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false, - gpgme_sign_result_t* result = nullptr); + gpgme_sign_result_t *result = nullptr); bool addUID(const GpgKey &key, const GpgUID &uid); @@ -125,6 +125,8 @@ namespace GpgME { bool setExpire(const GpgKey &key, const GpgSubKey *subkey, QDateTime *expires); + QProcess * generateRevokeCert(const GpgKey &key, const QString &outputFileName); + static bool checkIfKeyCanSign(const GpgKey &key); static bool checkIfKeyCanCert(const GpgKey &key); @@ -133,6 +135,7 @@ namespace GpgME { static bool checkIfKeyCanEncr(const GpgKey &key); + /** * @details If text contains PGP-message, put a linebreak before the message, * so that gpgme can decrypt correctly @@ -143,7 +146,7 @@ namespace GpgME { GpgKey getKeyByFpr(const QString &fpr); - const GpgKey & getKeyById(const QString &id); + const GpgKey &getKeyById(const QString &id); static QString gpgErrString(gpgme_error_t err); @@ -173,7 +176,7 @@ namespace GpgME { void slotRefreshKeyList(); - void slotUpdateKeyList(const QString& key_id); + void slotUpdateKeyList(const QString &key_id); private: gpgme_ctx_t mCtx{}; @@ -204,11 +207,11 @@ namespace GpgME { const char *passphrase_info, int last_was_bad, int fd); - void executeGpgCommand(const QStringList &arguments, - QByteArray *stdOut, - QByteArray *stdErr); + QProcess * executeGpgCommand(const QStringList &arguments, + QByteArray *stdOut, + QByteArray *stdErr, const std::function<void(QProcess *)> &interactFunc); - QString gpgBin; + QString gpgExec; QString gpgKeys; }; } // namespace GpgME diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h new file mode 100644 index 00000000..98affe03 --- /dev/null +++ b/include/rapidjson/allocators.h @@ -0,0 +1,271 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return std::malloc(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + std::free(originalPtr); + return NULL; + } + return std::realloc(originalPtr, newSize); + } + static void Free(void *ptr) { std::free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template <typename BaseAllocator = CrtAllocator> +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer); + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + RAPIDJSON_DELETE(ownBaseAllocator_); + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while (chunkHead_ && chunkHead_ != userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + if (chunkHead_ && chunkHead_ == userBuffer_) + chunkHead_->size = 0; // Clear user buffer + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + + void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + if (newSize == 0) + return NULL; + + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { + size_t increment = static_cast<size_t>(newSize - originalSize); + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) { (void)ptr; } // Do nothing + +private: + //! Copy constructor is not permitted. + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; + //! Copy assignment operator is not permitted. + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; + + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); + if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + return true; + } + else + return false; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + void *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h new file mode 100644 index 00000000..e3e20dfb --- /dev/null +++ b/include/rapidjson/document.h @@ -0,0 +1,2575 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include "memorystream.h" +#include "encodedstream.h" +#include <new> // placement new +#include <limits> + +RAPIDJSON_DIAG_PUSH +#ifdef _MSC_VER +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#if __GNUC__ >= 6 +RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions +#endif +#endif // __GNUC__ + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include <iterator> // std::iterator, std::random_access_iterator_tag +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include <utility> // std::move +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template <typename Encoding, typename Allocator> +class GenericValue; + +template <typename Encoding, typename Allocator, typename StackAllocator> +class GenericDocument; + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template <typename Encoding, typename Allocator> +struct GenericMember { + GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) + GenericValue<Encoding, Allocator> value; //!< value of member. +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ <iterator> header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator + : public std::iterator<std::random_access_iterator_tag + , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> { + + friend class GenericValue<Encoding,Allocator>; + template <bool, typename, typename> friend class GenericMemberIterator; + + typedef GenericMember<Encoding,Allocator> PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator; + + //! Pointer to (const) GenericMember + typedef typename BaseType::pointer Pointer; + //! Reference to (const) GenericMember + typedef typename BaseType::reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef typename BaseType::difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; } + bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; } + bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; } + bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; } + bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; } + bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; } + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template <bool Const, typename Encoding, typename Allocator> +struct GenericMemberIterator; + +//! non-const GenericMemberIterator +template <typename Encoding, typename Allocator> +struct GenericMemberIterator<false,Encoding,Allocator> { + //! use plain pointer as iterator type + typedef GenericMember<Encoding,Allocator>* Iterator; +}; +//! const GenericMemberIterator +template <typename Encoding, typename Allocator> +struct GenericMemberIterator<true,Encoding,Allocator> { + //! use plain const pointer as iterator type + typedef const GenericMember<Encoding,Allocator>* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template<typename CharType> +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + template<SizeType N> + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + explicit GenericStringRef(const CharType* str) + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } + + //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ +#endif + GenericStringRef(const CharType* str, SizeType len) + : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + + GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + //! Disallow construction from non-const array + template<SizeType N> + GenericStringRef(CharType (&str)[N]) /* = delete */; +}; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str) { + return GenericStringRef<CharType>(str, internal::StrLen(str)); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) { + return GenericStringRef<CharType>(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template<typename CharType> +inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) { + return GenericStringRef<CharType>(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template <typename T, typename Encoding = void, typename Allocator = void> +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type> + : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template <typename ValueType, typename T> +struct TypeHelper {}; + +template<typename ValueType> +struct TypeHelper<ValueType, bool> { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, int> { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, unsigned> { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, int64_t> { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, uint64_t> { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, double> { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, float> { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, const typename ValueType::Ch*> { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template<typename ValueType> +struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { + typedef std::basic_string<typename ValueType::Ch> StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; +#endif + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::Array> { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::ConstArray> { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::Object> { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; } +}; + +template<typename ValueType> +struct TypeHelper<ValueType, typename ValueType::ConstObject> { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template <bool, typename> class GenericArray; +template <bool, typename> class GenericObject; + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember<Encoding, Allocator> Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself. + typedef GenericArray<false, ValueType> Array; + typedef GenericArray<true, ValueType> ConstArray; + typedef GenericObject<false, ValueType> Object; + typedef GenericObject<true, ValueType> ConstObject; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template <typename StackAllocator> + GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template <typename StackAllocator> + GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs); +#endif + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \see CopyFrom() + */ + template< typename SourceAllocator > + GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator); + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template <typename T> + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if (i64 >= 0) { + data_.f.flags |= kNumberUint64Flag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + data_.f.flags |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(e); + } + break; + + case kObjectFlag: + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + break; + + case kCopyStringFlag: + Allocator::Free(const_cast<Ch*>(GetStringPointer())); + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + RawAssign(rhs); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template <typename SourceAllocator> + GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs)); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Linear time complexity (number of all values in the subtree and total lengths of all strings). + */ + template <typename SourceAllocator> + bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const { + typedef GenericValue<Encoding, SourceAllocator> RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template <typename SourceAllocator> + bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast<double>(u); + return (d >= 0.0) + && (d < static_cast<double>(std::numeric_limits<uint64_t>::max())) + && (u == static_cast<uint64_t>(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast<double>(i); + return (d >= static_cast<double>(std::numeric_limits<int64_t>::min())) + && (d < static_cast<double>(std::numeric_limits<int64_t>::max())) + && (i == static_cast<int64_t>(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast<double>(-std::numeric_limits<float>::max()) + || a > static_cast<double>(std::numeric_limits<float>::max())) + return false; + double b = static_cast<double>(static_cast<float>(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template <typename SourceAllocator> + GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); + } + } + template <typename SourceAllocator> + const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template <typename SourceAllocator> + bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template <typename SourceAllocator> + MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + + ObjectData& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)))); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 + SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); + } + } + Member* members = GetMembersPointer(); + members[o.size].name.RawAssign(name); + members[o.size].value.RawAssign(value); + o.size++; + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + + MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) + *m = *last; // Move the last one to this place + else + m->~Member(); // Only one left, just destroy + --data_.o.size; + return m; + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + + MemberIterator pos = MemberBegin() + (first - MemberBegin()); + for (MemberIterator itr = pos; itr != last; ++itr) + itr->~Member(); + std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member)); + data_.o.size -= static_cast<SizeType>(last - first); + return pos; + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template <typename SourceAllocator> + bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack<StringRefType>(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast<SizeType>(last - first); + return pos; + } + + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast<float>(GetDouble()); + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } +#endif + + //@} + + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch> + */ + template <typename T> + bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); } + + template <typename T> + T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } + + template <typename T> + T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); } + + template<typename T> + ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } + + template<typename T> + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template <typename Handler> + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) + return false; + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; + for (const GenericValue* v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else return handler.Uint64(data_.n.u64); + } + } + +private: + template <typename, typename> friend class GenericValue; + template <typename, typename, typename> friend class GenericDocument; + + enum { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + + struct String { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); } + inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct ObjectData { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct ArrayData { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + data_.f.flags = kArrayFlag; + if (count) { + GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(e, values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { + Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member))); + SetMembersPointer(m); + std::memcpy(m, members, count * sizeof(Member)); + } + else + SetMembersPointer(0); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } + + template <typename SourceAllocator> + bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue<UTF8<> > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator> +class GenericDocument : public GenericValue<Encoding, Allocator> { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward<ValueType>(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template <typename Generator> + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document + } + return *this; + } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags, typename SourceEncoding, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + GenericReader<SourceEncoding, Encoding, StackAllocator> reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse<parseFlags>(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags, typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<parseFlags, Encoding, InputStream>(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template <typename InputStream> + GenericDocument& ParseStream(InputStream& is) { + return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template <unsigned parseFlags> + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream<Encoding> s(str); + return ParseStream<parseFlags | kParseInsituFlag>(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu<kParseDefaultFlags>(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream<SourceEncoding> s(str); + return ParseStream<parseFlags, SourceEncoding>(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template <unsigned parseFlags> + GenericDocument& Parse(const Ch* str) { + return Parse<parseFlags, Encoding>(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse<kParseDefaultFlags>(str); + } + + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream<SourceEncoding, MemoryStream> is(ms); + ParseStream<parseFlags, SourceEncoding>(is); + return *this; + } + + template <unsigned parseFlags> + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse<parseFlags, Encoding>(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse<kParseDefaultFlags>(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template <unsigned parseFlags, typename SourceEncoding> + GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse<parseFlags, SourceEncoding>(str.c_str()); + } + + template <unsigned parseFlags> + GenericDocument& Parse(const std::basic_string<Ch>& str) { + return Parse<parseFlags, Encoding>(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string<Ch>& str) { + return Parse<kParseDefaultFlags>(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + // template <typename,typename,typename> friend class GenericReader; // for parsing + template <typename, typename> friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push<ValueType>()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount); + stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop<ValueType>(elementCount); + stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop<ValueType>(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack<StackAllocator> stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument<UTF8<> > Document; + +// defined here due to the dependency on GenericDocument +template <typename Encoding, typename Allocator> +template <typename SourceAllocator> +inline +GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator) +{ + switch (rhs.GetType()) { + case kObjectType: + case kArrayType: { // perform deep copy via SAX Handler + GenericDocument<Encoding,Allocator> d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop<GenericValue>(1)); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast<const Data*>(&rhs.data_); + } else { + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + } + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast<const Data*>(&rhs.data_); + break; + } +} + +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template <bool Const, typename ValueT> +class GenericArray { +public: + typedef GenericArray<true, ValueT> ConstArray; + typedef GenericArray<false, ValueT> Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + + template <typename, typename> + friend class GenericValue; + + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } +#endif + +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template <bool Const, typename ValueT> +class GenericObject { +public: + typedef GenericObject<true, ValueT> ConstObject; + typedef GenericObject<false, ValueT> Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; + typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template <typename, typename> + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + SizeType MemberCount() const { return value_.MemberCount(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template <typename T> ValueType& operator[](T* name) const { return value_[name]; } + template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); } +#endif + template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { return value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); } +#endif + template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/include/rapidjson/encodedstream.h b/include/rapidjson/encodedstream.h new file mode 100644 index 00000000..14506838 --- /dev/null +++ b/include/rapidjson/encodedstream.h @@ -0,0 +1,299 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "stream.h" +#include "memorystream.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template <typename Encoding, typename InputByteStream> +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream<UTF8<>, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template <typename Encoding, typename OutputByteStream> +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template <typename CharType, typename InputByteStream> +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam OutputByteStream type of output byte stream to be wrapped. +*/ +template <typename CharType, typename OutputByteStream> +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/include/rapidjson/encodings.h b/include/rapidjson/encodings.h new file mode 100644 index 00000000..baa7c2b1 --- /dev/null +++ b/include/rapidjson/encodings.h @@ -0,0 +1,716 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template <typename InputByteStream> + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template<typename CharType = char> +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) +#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast<unsigned char>(c); + return true; + } + + unsigned char type = GetRange(static_cast<unsigned char>(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFF >> type) & static_cast<unsigned char>(c); + } + bool result = true; + switch (type) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { +#define COPY() os.Put(c = is.Take()) +#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) +#define TAIL() COPY(); TRANS(0x70) + Ch c; + COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast<unsigned char>(c))) { + case 2: TAIL(); return result; + case 3: TAIL(); TAIL(); return result; + case 4: COPY(); TRANS(0x50); TAIL(); return result; + case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result; + case 6: TAIL(); TAIL(); TAIL(); return result; + case 10: COPY(); TRANS(0x20); TAIL(); return result; + case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result; + default: return false; + } +#undef COPY +#undef TRANS +#undef TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast<unsigned char>(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast<unsigned char>(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast<unsigned char>(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast<Ch>(is.Take()); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template<typename CharType = wchar_t> +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + os.Put((v & 0x3FF) | 0xDC00); + } + } + + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); + PutUnsafe(os, (v & 0x3FF) | 0xDC00); + } + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + typename InputStream::Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = static_cast<unsigned>(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast<unsigned>(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + typename InputStream::Ch c; + os.Put(static_cast<typename OutputStream::Ch>(c = is.Take())); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template<typename CharType = wchar_t> +struct UTF16LE : UTF16<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<uint8_t>(is.Take()); + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu)); + } +}; + +//! UTF-16 big endian encoding. +template<typename CharType = wchar_t> +struct UTF16BE : UTF16<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<uint8_t>(is.Take()); + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template<typename CharType = unsigned> +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template<typename CharType = unsigned> +struct UTF32LE : UTF32<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<uint8_t>(is.Take()); + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24; + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu)); + } +}; + +//! UTF-32 big endian encoding. +template<typename CharType = unsigned> +struct UTF32BE : UTF32<CharType> { + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; + } + + template <typename InputByteStream> + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; + c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())); + return static_cast<CharType>(c); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0x00u)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu)); + os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu)); + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu)); + os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template<typename CharType = char> +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template<typename OutputStream> + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast<Ch>(codepoint & 0xFF)); + } + + template<typename OutputStream> + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); + } + + template <typename InputStream> + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast<uint8_t>(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template <typename InputStream, typename OutputStream> + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast<uint8_t>(is.Take()); + os.Put(static_cast<typename OutputStream::Ch>(c)); + return c <= 0x7F; + } + + template <typename InputByteStream> + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast<uint8_t>(Take(is)); + return static_cast<Ch>(c); + } + + template <typename InputByteStream> + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast<Ch>(is.Take()); + } + + template <typename OutputByteStream> + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template <typename OutputByteStream> + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast<typename OutputByteStream::Ch>(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template<typename CharType> +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x + + template<typename OutputStream> + RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template<typename OutputStream> + RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; + (*f[os.GetType()])(os, codepoint); + } + + template <typename InputStream> + RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template <typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template<typename SourceEncoding, typename TargetEncoding> +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +// Forward declaration. +template<typename Stream> +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + +//! Specialization of Transcoder with same source and target encoding. +template<typename Encoding> +struct Transcoder<Encoding, Encoding> { + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template<typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/include/rapidjson/error/en.h b/include/rapidjson/error/en.h new file mode 100644 index 00000000..2db838bf --- /dev/null +++ b/include/rapidjson/error/en.h @@ -0,0 +1,74 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ + +#include "error.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/include/rapidjson/error/error.h b/include/rapidjson/error/error.h new file mode 100644 index 00000000..95cb31a7 --- /dev/null +++ b/include/rapidjson/error/error.h @@ -0,0 +1,155 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ + +#include "../rapidjson.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { +public: + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Conversion to \c bool, returns \c true, iff !\ref IsError(). + operator bool() const { return !IsError(); } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h new file mode 100644 index 00000000..b56ea13b --- /dev/null +++ b/include/rapidjson/filereadstream.h @@ -0,0 +1,99 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "stream.h" +#include <cstdio> + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/include/rapidjson/filewritestream.h b/include/rapidjson/filewritestream.h new file mode 100644 index 00000000..6378dd60 --- /dev/null +++ b/include/rapidjson/filewritestream.h @@ -0,0 +1,104 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "stream.h" +#include <cstdio> + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast<size_t>(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast<size_t>(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_); + if (result < static_cast<size_t>(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/include/rapidjson/fwd.h b/include/rapidjson/fwd.h new file mode 100644 index 00000000..e8104e84 --- /dev/null +++ b/include/rapidjson/fwd.h @@ -0,0 +1,151 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FWD_H_ +#define RAPIDJSON_FWD_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +// encodings.h + +template<typename CharType> struct UTF8; +template<typename CharType> struct UTF16; +template<typename CharType> struct UTF16BE; +template<typename CharType> struct UTF16LE; +template<typename CharType> struct UTF32; +template<typename CharType> struct UTF32BE; +template<typename CharType> struct UTF32LE; +template<typename CharType> struct ASCII; +template<typename CharType> struct AutoUTF; + +template<typename SourceEncoding, typename TargetEncoding> +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template <typename BaseAllocator> +class MemoryPoolAllocator; + +// stream.h + +template <typename Encoding> +struct GenericStringStream; + +typedef GenericStringStream<UTF8<char> > StringStream; + +template <typename Encoding> +struct GenericInsituStringStream; + +typedef GenericInsituStringStream<UTF8<char> > InsituStringStream; + +// stringbuffer.h + +template <typename Encoding, typename Allocator> +class GenericStringBuffer; + +typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template <typename Allocator> +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template<typename Encoding, typename Derived> +struct BaseReaderHandler; + +template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator> +class GenericReader; + +typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader; + +// writer.h + +template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> +class Writer; + +// prettywriter.h + +template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> +class PrettyWriter; + +// document.h + +template <typename Encoding, typename Allocator> +struct GenericMember; + +template <bool Const, typename Encoding, typename Allocator> +class GenericMemberIterator; + +template<typename CharType> +struct GenericStringRef; + +template <typename Encoding, typename Allocator> +class GenericValue; + +typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value; + +template <typename Encoding, typename Allocator, typename StackAllocator> +class GenericDocument; + +typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document; + +// pointer.h + +template <typename ValueType, typename Allocator> +class GenericPointer; + +typedef GenericPointer<Value, CrtAllocator> Pointer; + +// schema.h + +template <typename SchemaDocumentType> +class IGenericRemoteSchemaDocumentProvider; + +template <typename ValueT, typename Allocator> +class GenericSchemaDocument; + +typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSONFWD_H_ diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h new file mode 100644 index 00000000..9d3e88c9 --- /dev/null +++ b/include/rapidjson/internal/biginteger.h @@ -0,0 +1,290 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include <intrin.h> // for _umul128 +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + BigInteger(const char* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + void AppendDecimal64(const char* begin, const char* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast<unsigned>(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + static uint64_t ParseUint64(const char* begin, const char* end) { + uint64_t r = 0; + for (const char* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); + r = r * 10u + static_cast<unsigned>(*p - '0'); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b); + p += k; + *outHigh = static_cast<uint64_t>(p >> 64); + return static_cast<uint64_t>(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast<uint64_t>(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h new file mode 100644 index 00000000..c9fefdc6 --- /dev/null +++ b/include/rapidjson/internal/diyfp.h @@ -0,0 +1,258 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && defined(_M_AMD64) +#include <intrin.h> +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_umul128) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +struct DiyFp { + DiyFp() : f(), e() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f); + uint64_t h = static_cast<uint64_t>(p >> 64); + uint64_t l = static_cast<uint64_t>(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { +#if defined(_MSC_VER) && defined(_M_AMD64) + unsigned long index; + _BitScanReverse64(&index, f); + return DiyFp(f << (63 - index), e - (63 - index)); +#elif defined(__GNUC__) && __GNUC__ >= 4 + int s = __builtin_clzll(f); + return DiyFp(f << s, e - s); +#else + DiyFp res = *this; + while (!(res.f & (static_cast<uint64_t>(1) << 63))) { + res.f <<= 1; + res.e--; + } + return res; +#endif + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast<uint64_t>(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast<int>(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast<unsigned>((k >> 3) + 1); + *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u; + *outExp = -348 + static_cast<int>(index) * 8; + return GetCachedPowerByIndex(index); + } + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/include/rapidjson/internal/dtoa.h b/include/rapidjson/internal/dtoa.h new file mode 100644 index 00000000..8d6350e6 --- /dev/null +++ b/include/rapidjson/internal/dtoa.h @@ -0,0 +1,245 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline unsigned CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d)); + kappa--; + uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast<char>(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast<char>('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + int index = -static_cast<int>(kappa); + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0)); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast<char>('0' + static_cast<char>(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (0 <= k && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk)); + buffer[kk] = '.'; + if (0 > k + maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[kk + 2]; // Reserve one zero + } + else + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length)); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + if (length - kk > maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = maxDecimalPlaces + 1; i > 2; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[3]; // Reserve one zero + } + else + return &buffer[length + offset]; + } + else if (kk < -maxDecimalPlaces) { + // Truncate to zero + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1)); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K, maxDecimalPlaces); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h new file mode 100644 index 00000000..82bb0b99 --- /dev/null +++ b/include/rapidjson/internal/ieee754.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static unsigned EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return static_cast<unsigned>(order) + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/include/rapidjson/internal/itoa.h b/include/rapidjson/internal/itoa.h new file mode 100644 index 00000000..01a4e7e7 --- /dev/null +++ b/include/rapidjson/internal/itoa.h @@ -0,0 +1,304 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast<char>('0' + static_cast<char>(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + uint32_t u = static_cast<uint32_t>(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast<uint32_t>(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast<uint32_t>(value / kTen8); + const uint32_t v1 = static_cast<uint32_t>(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + if (value >= kTen8) + *buffer++ = cDigitsLut[d4 + 1]; + + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast<char>('0' + static_cast<char>(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast<uint32_t>(value / kTen8); + const uint32_t v1 = static_cast<uint32_t>(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + uint64_t u = static_cast<uint64_t>(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/include/rapidjson/internal/meta.h b/include/rapidjson/internal/meta.h new file mode 100644 index 00000000..5a9aaa42 --- /dev/null +++ b/include/rapidjson/internal/meta.h @@ -0,0 +1,181 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif +#if defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include <type_traits> +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template <typename T> struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template <bool Cond> struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType<true> TrueType; +typedef BoolType<false> FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; +template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; +template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; + +template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; +template <> struct AndExprCond<true, true> : TrueType {}; +template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; +template <> struct OrExprCond<false, false> : FalseType {}; + +template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; +template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; +template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; +template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template <typename T> struct AddConst { typedef const T Type; }; +template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; +template <typename T> struct RemoveConst { typedef T Type; }; +template <typename T> struct RemoveConst<const T> { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template <typename T, typename U> struct IsSame : FalseType {}; +template <typename T> struct IsSame<T, T> : TrueType {}; + +template <typename T> struct IsConst : FalseType {}; +template <typename T> struct IsConst<const T> : TrueType {}; + +template <typename CT, typename T> +struct IsMoreConst + : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, + BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; + +template <typename T> struct IsPointer : FalseType {}; +template <typename T> struct IsPointer<T*> : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template <typename B, typename D> struct IsBaseOf + : BoolType< ::std::is_base_of<B,D>::value> {}; + +#else // simplified version adopted from Boost + +template<typename B, typename D> struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template <typename T> + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template <typename B, typename D> struct IsBaseOf + : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; +template <typename T> struct EnableIfCond<false, T> { /* empty */ }; + +template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; +template <typename T> struct DisableIfCond<true, T> { /* empty */ }; + +template <typename Condition, typename T = void> +struct EnableIf : EnableIfCond<Condition::Value, T> {}; + +template <typename Condition, typename T = void> +struct DisableIf : DisableIfCond<Condition::Value, T> {}; + +// SFINAE helpers +struct SfinaeTag {}; +template <typename T> struct RemoveSfinaeTag; +template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + <RAPIDJSON_REMOVEFPTR_(cond), \ + RAPIDJSON_REMOVEFPTR_(returntype)>::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + <RAPIDJSON_REMOVEFPTR_(cond), \ + RAPIDJSON_REMOVEFPTR_(returntype)>::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(__GNUC__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/include/rapidjson/internal/pow10.h b/include/rapidjson/internal/pow10.h new file mode 100644 index 00000000..02f475d7 --- /dev/null +++ b/include/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/include/rapidjson/internal/regex.h b/include/rapidjson/internal/regex.h new file mode 100644 index 00000000..422a5240 --- /dev/null +++ b/include/rapidjson/internal/regex.h @@ -0,0 +1,701 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_REGEX_H_ +#define RAPIDJSON_INTERNAL_REGEX_H_ + +#include "../allocators.h" +#include "../stream.h" +#include "stack.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(implicit-fallthrough) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +#ifndef RAPIDJSON_REGEX_VERBOSE +#define RAPIDJSON_REGEX_VERBOSE 0 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// GenericRegex + +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 +static const SizeType kRegexInvalidRange = ~SizeType(0); + +//! Regular expression engine with subset of ECMAscript grammar. +/*! + Supported regular expression syntax: + - \c ab Concatenation + - \c a|b Alternation + - \c a? Zero or one + - \c a* Zero or more + - \c a+ One or more + - \c a{3} Exactly 3 times + - \c a{3,} At least 3 times + - \c a{3,5} 3 to 5 times + - \c (ab) Grouping + - \c ^a At the beginning + - \c a$ At the end + - \c . Any character + - \c [abc] Character classes + - \c [a-c] Character class range + - \c [a-z0-9_] Character class combination + - \c [^abc] Negated character classes + - \c [^a-c] Negated character class range + - \c [\b] Backspace (U+0008) + - \c \\| \\\\ ... Escape characters + - \c \\f Form feed (U+000C) + - \c \\n Line feed (U+000A) + - \c \\r Carriage return (U+000D) + - \c \\t Tab (U+0009) + - \c \\v Vertical tab (U+000B) + + \note This is a Thompson NFA engine, implemented with reference to + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", + https://swtch.com/~rsc/regexp/regexp1.html +*/ +template <typename Encoding, typename Allocator = CrtAllocator> +class GenericRegex { +public: + typedef typename Encoding::Ch Ch; + + GenericRegex(const Ch* source, Allocator* allocator = 0) : + states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), + stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_() + { + GenericStringStream<Encoding> ss(source); + DecodedStream<GenericStringStream<Encoding> > ds(ss); + Parse(ds); + } + + ~GenericRegex() { + Allocator::Free(stateSet_); + } + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + + template <typename InputStream> + bool Match(InputStream& is) const { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) const { + GenericStringStream<Encoding> is(s); + return Match(is); + } + + template <typename InputStream> + bool Search(InputStream& is) const { + return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); + } + + bool Search(const Ch* s) const { + GenericStringStream<Encoding> is(s); + return Search(is); + } + +private: + enum Operator { + kZeroOrOne, + kZeroOrMore, + kOneOrMore, + kConcatenation, + kAlternation, + kLeftParenthesis + }; + + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; + static const unsigned kRangeNegationFlag = 0x80000000; + + struct Range { + unsigned start; // + unsigned end; + SizeType next; + }; + + struct State { + SizeType out; //!< Equals to kInvalid for matching state + SizeType out1; //!< Equals to non-kInvalid for split + SizeType rangeStart; + unsigned codepoint; + }; + + struct Frag { + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} + SizeType start; + SizeType out; //!< link-list of all output states + SizeType minIndex; + }; + + template <typename SourceStream> + class DecodedStream { + public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + + private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; + }; + + State& GetState(SizeType index) { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom<State>()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom<State>()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom<Range>()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom<Range>()[index]; + } + + template <typename InputStream> + void Parse(DecodedStream<InputStream>& ds) { + Allocator allocator; + Stack<Allocator> operandStack(&allocator, 256); // Frag + Stack<Allocator> operatorStack(&allocator, 256); // Operator + Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push<unsigned>() = 0; + + unsigned codepoint; + while (ds.Peek() != 0) { + switch (codepoint = ds.Take()) { + case '^': + anchorBegin_ = true; + break; + + case '$': + anchorEnd_ = true; + break; + + case '|': + while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) + return; + *operatorStack.template Push<Operator>() = kAlternation; + *atomCountStack.template Top<unsigned>() = 0; + break; + + case '(': + *operatorStack.template Push<Operator>() = kLeftParenthesis; + *atomCountStack.template Push<unsigned>() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop<Operator>(1); + atomCountStack.template Pop<unsigned>(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '?': + if (!Eval(operandStack, kZeroOrOne)) + return; + break; + + case '*': + if (!Eval(operandStack, kZeroOrMore)) + return; + break; + + case '+': + if (!Eval(operandStack, kOneOrMore)) + return; + break; + + case '{': + { + unsigned n, m; + if (!ParseUnsigned(ds, &n)) + return; + + if (ds.Peek() == ',') { + ds.Take(); + if (ds.Peek() == '}') + m = kInfinityQuantifier; + else if (!ParseUnsigned(ds, &m) || m < n) + return; + } + else + m = n; + + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + return; + ds.Take(); + } + break; + + case '.': + PushOperand(operandStack, kAnyCharacterClass); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '[': + { + SizeType range; + if (!ParseRange(ds, &range)) + return; + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); + GetState(s).rangeStart = range; + *operandStack.template Push<Frag>() = Frag(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '\\': // Escape character + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default + + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } + + while (!operatorStack.Empty()) + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop<Frag>(1); + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); + root_ = e->start; + +#if RAPIDJSON_REGEX_VERBOSE + printf("root: %d\n", root_); + for (SizeType i = 0; i < stateCount_ ; i++) { + State& s = GetState(i); + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); + } + printf("\n"); +#endif + } + + // Preallocate buffer for SearchWithAnchoring() + RAPIDJSON_ASSERT(stateSet_ == 0); + if (stateCount_ > 0) { + stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize())); + state0_.template Reserve<SizeType>(stateCount_); + state1_.template Reserve<SizeType>(stateCount_); + } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { + State* s = states_.template Push<State>(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push<Frag>() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) { + if (*atomCountStack.template Top<unsigned>()) + *operatorStack.template Push<Operator>() = kConcatenation; + (*atomCountStack.template Top<unsigned>())++; + } + + SizeType Append(SizeType l1, SizeType l2) { + SizeType old = l1; + while (GetState(l1).out != kRegexInvalidState) + l1 = GetState(l1).out; + GetState(l1).out = l2; + return old; + } + + void Patch(SizeType l, SizeType s) { + for (SizeType next; l != kRegexInvalidState; l = next) { + next = GetState(l).out; + GetState(l).out = s; + } + } + + bool Eval(Stack<Allocator>& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop<Frag>(1); + Frag e1 = *operandStack.template Pop<Frag>(1); + Patch(e1.out, e2.start); + *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); + } + return true; + + case kAlternation: + if (operandStack.GetSize() >= sizeof(Frag) * 2) { + Frag e2 = *operandStack.template Pop<Frag>(1); + Frag e1 = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); + return true; + } + return false; + + case kZeroOrOne: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex); + return true; + } + return false; + + default: + RAPIDJSON_ASSERT(op == kOneOrMore); + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop<Frag>(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + } + } + + bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) { + RAPIDJSON_ASSERT(n <= m); + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + + if (n == 0) { + if (m == 0) // a{0} not support + return false; + else if (m == kInfinityQuantifier) + Eval(operandStack, kZeroOrMore); // a{0,} -> a* + else { + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? + for (unsigned i = 0; i < m - 1; i++) + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? + for (unsigned i = 0; i < m - 1; i++) + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? + } + return true; + } + + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a + CloneTopOperand(operandStack); + + if (m == kInfinityQuantifier) + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ + else if (m > n) { + CloneTopOperand(operandStack); // a{3,5} -> a a a a + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? + for (unsigned i = n; i < m - 1; i++) + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? + for (unsigned i = n; i < m; i++) + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? + } + + for (unsigned i = 0; i < n - 1; i++) + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? + + return true; + } + + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + + void CloneTopOperand(Stack<Allocator>& operandStack) { + const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push<State>(count); + memcpy(s, &GetState(src.minIndex), count * sizeof(State)); + for (SizeType j = 0; j < count; j++) { + if (s[j].out != kRegexInvalidState) + s[j].out += count; + if (s[j].out1 != kRegexInvalidState) + s[j].out1 += count; + } + *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template <typename InputStream> + bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; + while (ds.Peek() >= '0' && ds.Peek() <= '9') { + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 + return false; // overflow + r = r * 10 + (ds.Take() - '0'); + } + *u = r; + return true; + } + + template <typename InputStream> + bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; + SizeType start = kRegexInvalidRange; + SizeType current = kRegexInvalidRange; + unsigned codepoint; + while ((codepoint = ds.Take()) != 0) { + if (isBegin) { + isBegin = false; + if (codepoint == '^') { + negate = true; + continue; + } + } + + switch (codepoint) { + case ']': + if (start == kRegexInvalidRange) + return false; // Error: nothing inside [] + if (step == 2) { // Add trailing '-' + SizeType r = NewRange('-'); + RAPIDJSON_ASSERT(current != kRegexInvalidRange); + GetRange(current).next = r; + } + if (negate) + GetRange(start).start |= kRangeNegationFlag; + *range = start; + return true; + + case '\\': + if (ds.Peek() == 'b') { + ds.Take(); + codepoint = 0x0008; // Escape backspace character + } + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default + + default: + switch (step) { + case 1: + if (codepoint == '-') { + step++; + break; + } + // fall through to step 0 for other characters + + case 0: + { + SizeType r = NewRange(codepoint); + if (current != kRegexInvalidRange) + GetRange(current).next = r; + if (start == kRegexInvalidRange) + start = r; + current = r; + } + step = 1; + break; + + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } + + SizeType NewRange(unsigned codepoint) { + Range* r = ranges_.template Push<Range>(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template <typename InputStream> + bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': + case '$': + case '|': + case '(': + case ')': + case '?': + case '*': + case '+': + case '.': + case '[': + case ']': + case '{': + case '}': + case '\\': + *escapedCodepoint = codepoint; return true; + case 'f': *escapedCodepoint = 0x000C; return true; + case 'n': *escapedCodepoint = 0x000A; return true; + case 'r': *escapedCodepoint = 0x000D; return true; + case 't': *escapedCodepoint = 0x0009; return true; + case 'v': *escapedCodepoint = 0x000B; return true; + default: + return false; // Unsupported escape character + } + } + + template <typename InputStream> + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { + RAPIDJSON_ASSERT(IsValid()); + DecodedStream<InputStream> ds(is); + + state0_.Clear(); + Stack<Allocator> *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + + bool matched = AddState(*current, root_); + unsigned codepoint; + while (!current->Empty() && (codepoint = ds.Take()) != 0) { + std::memset(stateSet_, 0, stateSetSize); + next->Clear(); + matched = false; + for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) { + const State& sr = GetState(*s); + if (sr.codepoint == codepoint || + sr.codepoint == kAnyCharacterClass || + (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) + AddState(*next, root_); + } + internal::Swap(current, next); + } + + return matched; + } + + size_t GetStateSetSize() const { + return (stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state + bool AddState(Stack<Allocator>& l, SizeType index) const { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + + const State& s = GetState(index); + if (s.out1 != kRegexInvalidState) { // Split + bool matched = AddState(l, s.out); + return AddState(l, s.out1) || matched; + } + else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) { + stateSet_[index >> 5] |= (1 << (index & 31)); + *l.template PushUnsafe<SizeType>() = index; + } + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } + + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { + bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { + const Range& r = GetRange(rangeIndex); + if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + + Stack<Allocator> states_; + Stack<Allocator> ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + uint32_t* stateSet_; // allocated by states_.GetAllocator() + mutable Stack<Allocator> state0_; + mutable Stack<Allocator> state1_; + bool anchorBegin_; + bool anchorEnd_; +}; + +typedef GenericRegex<UTF8<> > Regex; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_REGEX_H_ diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h new file mode 100644 index 00000000..022c9aab --- /dev/null +++ b/include/rapidjson/internal/stack.h @@ -0,0 +1,230 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../allocators.h" +#include "swap.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template <typename Allocator> +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template<typename T> + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) + Expand<T>(count); + } + + template<typename T> + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve<T>(count); + return PushUnsafe<T>(count); + } + + template<typename T> + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); + T* ret = reinterpret_cast<T*>(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template<typename T> + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast<T*>(stackTop_); + } + + template<typename T> + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); + } + + template<typename T> + T* End() { return reinterpret_cast<T*>(stackTop_); } + + template<typename T> + const T* End() const { return reinterpret_cast<T*>(stackTop_); } + + template<typename T> + T* Bottom() { return reinterpret_cast<T*>(stack_); } + + template<typename T> + const T* Bottom() const { return reinterpret_cast<T*>(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } + +private: + template<typename T> + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STACK_H_ diff --git a/include/rapidjson/internal/strfunc.h b/include/rapidjson/internal/strfunc.h new file mode 100644 index 00000000..2edfae52 --- /dev/null +++ b/include/rapidjson/internal/strfunc.h @@ -0,0 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../stream.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template <typename Ch> +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +//! Returns number of code points in a encoded string. +template<typename Encoding> +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + GenericStringStream<Encoding> is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h new file mode 100644 index 00000000..289c413b --- /dev/null +++ b/include/rapidjson/internal/strtod.h @@ -0,0 +1,269 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template <typename T> +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2); + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { + uint64_t significand = 0; + size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < length; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) + break; + significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0'); + } + + if (i < length && decimals[i] >= '5') // Rounding + significand++; + + size_t remaining = length - i; + const unsigned kUlpShift = 3; + const unsigned kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp - 1; + RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); + v = v * kPow10[adjustment]; + if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + unsigned precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + unsigned scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + static_cast<int>(kUlp); + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize)); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + static_cast<unsigned>(error)) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); +} + +inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { + const BigInteger dInt(decimals, length); + const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp; + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result; + if (StrtodFast(d, p, &result)) + return result; + + // Trim leading zeros + while (*decimals == '0' && length > 1) { + length--; + decimals++; + decimalPosition--; + } + + // Trim trailing zeros + while (decimals[length - 1] == '0' && length > 1) { + length--; + decimalPosition--; + exp++; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 780; + if (static_cast<int>(length) > kMaxDecimalDigit) { + int delta = (static_cast<int>(length) - kMaxDecimalDigit); + exp += delta; + decimalPosition -= static_cast<unsigned>(delta); + length = kMaxDecimalDigit; + } + + // If too small, underflow to zero + if (int(length) + exp < -324) + return 0.0; + + if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, length, decimalPosition, exp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/include/rapidjson/internal/swap.h b/include/rapidjson/internal/swap.h new file mode 100644 index 00000000..666e49f9 --- /dev/null +++ b/include/rapidjson/internal/swap.h @@ -0,0 +1,46 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ <algorithm> header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template <typename T> +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/include/rapidjson/istreamwrapper.h b/include/rapidjson/istreamwrapper.h new file mode 100644 index 00000000..f5fe2897 --- /dev/null +++ b/include/rapidjson/istreamwrapper.h @@ -0,0 +1,115 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ISTREAMWRAPPER_H_ +#define RAPIDJSON_ISTREAMWRAPPER_H_ + +#include "stream.h" +#include <iosfwd> + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::istringstream + - \c std::stringstream + - \c std::wistringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wifstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_istream. +*/ + +template <typename StreamType> +class BasicIStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} + + Ch Peek() const { + typename StreamType::int_type c = stream_.peek(); + return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0'; + } + + Ch Take() { + typename StreamType::int_type c = stream_.get(); + if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { + count_++; + return static_cast<Ch>(c); + } + else + return '\0'; + } + + // tellg() may return -1 when failed. So we count by ourself. + size_t Tell() const { return count_; } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. + int i; + bool hasError = false; + for (i = 0; i < 4; ++i) { + typename StreamType::int_type c = stream_.get(); + if (c == StreamType::traits_type::eof()) { + hasError = true; + stream_.clear(); + break; + } + peekBuffer_[i] = static_cast<Ch>(c); + } + for (--i; i >= 0; --i) + stream_.putback(peekBuffer_[i]); + return !hasError ? peekBuffer_ : 0; + } + +private: + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + + StreamType& stream_; + size_t count_; //!< Number of characters read. Note: + mutable Ch peekBuffer_[4]; +}; + +typedef BasicIStreamWrapper<std::istream> IStreamWrapper; +typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper; + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ISTREAMWRAPPER_H_ diff --git a/include/rapidjson/memorybuffer.h b/include/rapidjson/memorybuffer.h new file mode 100644 index 00000000..39bee1de --- /dev/null +++ b/include/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template <typename Allocator = CrtAllocator> +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push<Ch>() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom<Ch>(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack<Allocator> stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/include/rapidjson/memorystream.h b/include/rapidjson/memorystream.h new file mode 100644 index 00000000..1d71d8a4 --- /dev/null +++ b/include/rapidjson/memorystream.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "stream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast<size_t>(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/include/rapidjson/msinttypes/inttypes.h b/include/rapidjson/msinttypes/inttypes.h new file mode 100644 index 00000000..18111286 --- /dev/null +++ b/include/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include <inttypes.h> +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/include/rapidjson/msinttypes/stdint.h b/include/rapidjson/msinttypes/stdint.h new file mode 100644 index 00000000..3d4477b9 --- /dev/null +++ b/include/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the product nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include <stdint.h> + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}' +// or compiler would give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if defined(__cplusplus) && !defined(_M_ARM) +extern "C" { +#endif +# include <wchar.h> +#if defined(__cplusplus) && !defined(_M_ARM) +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/include/rapidjson/ostreamwrapper.h b/include/rapidjson/ostreamwrapper.h new file mode 100644 index 00000000..6f4667c0 --- /dev/null +++ b/include/rapidjson/ostreamwrapper.h @@ -0,0 +1,81 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_OSTREAMWRAPPER_H_ +#define RAPIDJSON_OSTREAMWRAPPER_H_ + +#include "stream.h" +#include <iosfwd> + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::ostringstream + - \c std::stringstream + - \c std::wpstringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wofstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_ostream. +*/ + +template <typename StreamType> +class BasicOStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + + void Put(Ch c) { + stream_.put(c); + } + + void Flush() { + stream_.flush(); + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + BasicOStreamWrapper(const BasicOStreamWrapper&); + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); + + StreamType& stream_; +}; + +typedef BasicOStreamWrapper<std::ostream> OStreamWrapper; +typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper; + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_OSTREAMWRAPPER_H_ diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h new file mode 100644 index 00000000..0206ac1c --- /dev/null +++ b/include/rapidjson/pointer.h @@ -0,0 +1,1358 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" +#include "internal/itoa.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, //!< The parse is successful + + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericPointer + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. + + \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> > + \tparam Allocator The allocator type for allocating memory for internal representation. + + \note GenericPointer uses same encoding of ValueType. + However, Allocator of GenericPointer is independent of Allocator of Value. +*/ +template <typename ValueType, typename Allocator = CrtAllocator> +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value + + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor. + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, internal::StrLen(source)); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, length); + } + + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Destructor. + ~GenericPointer() { + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + Allocator::Free(tokens_); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator. + GenericPointer& operator=(const GenericPointer& rhs) { + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) + Allocator::Free(tokens_); + + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; + + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } + + //@} + + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast<SizeType>(end - buffer); + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { reinterpret_cast<Ch*>(buffer), length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = buffer[i]; + Token token = { name, length, index }; + return Append(token, allocator); + } + } + + //! Append a token by value, and return a new Pointer + /*! + \param token token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast<SizeType>(token.GetUint64()), allocator); + } + } + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + + //@} + + //! Get the allocator of this pointer. + Allocator& GetAllocator() { return *allocator_; } + + //!@name Tokens + //@{ + + //! Get the token array (const version only). + const Token* GetTokens() const { return tokens_; } + + //! Get the number of tokens. + size_t GetTokenCount() const { return tokenCount_; } + + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } + + return true; + } + + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template<typename OutputStream> + bool Stringify(OutputStream& os) const { + return Stringify<false, OutputStream>(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template<typename OutputStream> + bool StringifyUriFragment(OutputStream& os) const { + return Stringify<true, OutputStream>(os); + } + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(ValueType().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name + if (!v->IsObject()) + v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(ValueType().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); + if (m == v->MemberEnd()) { + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); + v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template <typename stackAllocator> + ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); + } + + //@} + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \return Pointer to the value if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast<size_t>(t - tokens_); + return 0; + } + return v; + } + + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { + return Get(const_cast<ValueType&>(root), unresolvedTokenIndex); + } + + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); + } + + //! Query a value in a subtree with default null-terminated string. + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } +#endif + + //! Query a value in a subtree with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } + + //! Query a value in a document with default value. + template <typename stackAllocator> + ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template <typename stackAllocator> + ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a document with default std::basic_string. + template <typename stackAllocator> + ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } +#endif + + //! Query a value in a document with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template <typename T, typename stackAllocator> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) + GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. + ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } +#endif + + //! Set a primitive value in a subtree. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template <typename T> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value).Move(); + } + + //! Set a value in a document, with move semantics. + template <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template <typename stackAllocator> + ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif + + //! Set a primitive value in a document. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template <typename T, typename stackAllocator> + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) + Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const { + return Create(document) = value; + } + + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } + + //! Swap a value with a value in a document. + template <typename stackAllocator> + ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != last; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); + if (m == v->MemberEnd()) + return false; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef<Ch>(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } + +private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_); + if (rhs.tokenCount_ > 0) { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if (nameBufferSize > 0) { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } + + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) + t->name += diff; + + return nameBuffer_ + nameBufferSize; + } + + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + + //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ +#endif + void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + // Count number of '/' as tokenCount + tokenCount_ = 0; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_); + size_t i = 0; + + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' + + token->name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i]; + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream<EncodingType> os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; + i++; + continue; + } + } + else if (NeedPercentEncode(c)) { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } + + i++; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token->length = static_cast<SizeType>(name - token->name); + if (token->length == 0) + isNumber = false; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token->length > 1 && token->name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; + + error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } + + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template<bool uriFragment, typename OutputStream> + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]); + PercentEncodeStream<OutputStream> target(os); + if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream { + public: + typedef typename ValueType::Ch Ch; + + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + + Ch Take() { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c = static_cast<Ch>(c << 4); + Ch h = *src_; + if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10); + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return static_cast<size_t>(src_ - head_); } + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; + + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template <typename OutputStream> + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast<unsigned char>(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(hexDigits[u >> 4]); + os_.Put(hexDigits[u & 15]); + } + private: + OutputStream& os_; + }; + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. +}; + +//! GenericPointer for Value (UTF-8, default allocator). +typedef GenericPointer<Value> Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template <typename DocumentType> +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) { + return pointer.Create(document); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template <typename T> +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); +} + +template <typename T, typename CharType, size_t N> +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template <typename T> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template <typename T, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T, typename CharType, size_t N> +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template <typename T, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template <typename DocumentType> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template <typename DocumentType> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template <typename DocumentType, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template <typename DocumentType, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T> +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template <typename T, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename T, typename CharType, size_t N> +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} +#endif + +template <typename T, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) { + return pointer.Set(document, value); +} +#endif + +template <typename DocumentType, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) { + return pointer.Set(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} +#endif + +template <typename DocumentType, typename CharType, size_t N, typename T2> +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template <typename T, typename CharType, size_t N> +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a); +} + +template <typename DocumentType> +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template <typename DocumentType, typename CharType, size_t N> +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template <typename T> +bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) { + return pointer.Erase(root); +} + +template <typename T, typename CharType, size_t N> +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root); +} + +//@} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_POINTER_H_ diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h new file mode 100644 index 00000000..0dcb0fee --- /dev/null +++ b/include/rapidjson/prettywriter.h @@ -0,0 +1,255 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of ouptut os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { +public: + typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kNumberType); + return Base::WriteString(str, length); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + PrettyPrefix(kStringType); + return Base::WriteString(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string<Ch>& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); + bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndObject(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); + bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; + + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::WriteEndArray(); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::os_->Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); } + +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); + } + + if (!(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count); + } + + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h new file mode 100644 index 00000000..053b2ce4 --- /dev/null +++ b/include/rapidjson/rapidjson.h @@ -0,0 +1,615 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overriden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include <cstdlib> // malloc(), realloc(), free(), size_t +#include <cstring> // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include <string> +#endif // RAPIDJSON_HAS_STDSTRING + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include <stdint.h> +#include <inttypes.h> +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include <endian.h> +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && defined(_M_ARM) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. Currently the default uses 4 bytes + alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms. + User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#if RAPIDJSON_64BIT == 1 +#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u)) +#else +#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_48BITPOINTER_OPTIMIZATION + +//! Use only lower 48-bit address for some pointers. +/*! + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. +*/ +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2 optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible + processors. + + To enable these optimizations, two different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + \c RAPIDJSON_SSE42 takes precedence, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include <cassert> +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Adopt from boost +#ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif +RAPIDJSON_NAMESPACE_BEGIN +template <bool x> struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; +template<int x> struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y + +#if defined(__GNUC__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +#ifndef __clang__ +//!@endcond +#endif + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if defined(__clang__) +#if __has_feature(cxx_rvalue_references) && \ + (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT /* noexcept */ +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(x) new x +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Type + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h new file mode 100644 index 00000000..19f8849b --- /dev/null +++ b/include/rapidjson/reader.h @@ -0,0 +1,1879 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" +#include <limits> + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include <nmmintrin.h> +#elif defined(RAPIDJSON_SSE2) +#include <emmintrin.h> +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include <stdexcept> // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template<typename Encoding = UTF8<>, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast<Override&>(*this).Default(); } + bool Bool(bool) { return static_cast<Override&>(*this).Default(); } + bool Int(int) { return static_cast<Override&>(*this).Default(); } + bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); } + bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); } + bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); } + bool Double(double) { return static_cast<Override&>(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); } + bool StartObject() { return static_cast<Override&>(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); } + bool StartArray() { return static_cast<Override&>(*this).Default(); } + bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template<typename Stream, int = StreamTraits<Stream>::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template<typename Stream> +class StreamLocalCopy<Stream, 1> { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template<typename Stream> +class StreamLocalCopy<Stream, 0> { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template<typename InputStream> +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy<InputStream> copy(is); + InputStream& s(copy.s); + + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + s.Take(); +} + +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r != 0) { // some of characters is non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} + +template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator> +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse<parseFlags>(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template <typename InputStream, typename Handler> + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse<kParseDefaultFlags>(is, handler); + } + + //! Whether a parse error has occured in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template<unsigned parseFlags, typename InputStream> + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n'); + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString<parseFlags>(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + // Parse array: [ value, ... ] + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue<parseFlags>(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template<typename InputStream> + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template<typename InputStream> + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast<unsigned>(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } + + template <typename CharType> + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push<Ch>() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push<Ch>(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop<Ch>(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack<StackAllocator>& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy<InputStream> copy(is); + InputStream& s(copy.s); + + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream<typename TargetEncoding::Ch> stackStream(stack_); + ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast<SizeType>(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (RAPIDJSON_UNLIKELY(!success)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) { + is.Take(); + os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)])); + } + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) { + // Handle UTF-16 surrogate pair + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell()); + } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder<SEncoding, TEncoding>::Validate(is, os) : + !Transcoder<SEncoding, TEncoding>::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template<typename InputStream, typename OutputStream> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream<char> + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast<SizeType>(__builtin_ffs(r) - 1); + #endif + char* q = reinterpret_cast<char*>(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast<size_t>(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast<size_t>(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif + + template<typename InputStream, bool backup, bool pushOnTake> + class NumberStream; + + template<typename InputStream> + class NumberStream<InputStream, false, false> { + public: + typedef typename InputStream::Ch Ch; + + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const char* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template<typename InputStream> + class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> { + typedef NumberStream<InputStream, false, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast<char>(Base::is.Peek())); + return Base::is.Take(); + } + + RAPIDJSON_FORCEINLINE void Push(char c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + + const char* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream<char> stackStream; + }; + + template<typename InputStream> + class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> { + typedef NumberStream<InputStream, true, false> Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} + ~NumberStream() {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseNumber(InputStream& is, Handler& handler) { + internal::StreamLocalCopy<InputStream> copy(is); + NumberStream<InputStream, + ((parseFlags & kParseNumbersAsStringsFlag) != 0) ? + ((parseFlags & kParseInsituFlag) == 0) : + ((parseFlags & kParseFullPrecisionFlag) != 0), + (parseFlags & kParseNumbersAsStringsFlag) != 0 && + (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; + + // Parse minus + bool minus = Consume(s, '-'); + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { + i = 0; + s.TakePush(); + } + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { + i = static_cast<unsigned>(s.TakePush() - '0'); + + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + useNanOrInf = true; + if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) { + d = std::numeric_limits<double>::quiet_NaN(); + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) { + d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity()); + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + if (use64bit) { + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast<double>(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast<double>(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (Consume(s, '.')) { + decimalPosition = s.Length(); + + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast<double>(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast<double>(use64bit ? i64 : i); +#endif + useDouble = true; + } + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (RAPIDJSON_LIKELY(d > 0.0)) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (Consume(s, 'e') || Consume(s, 'E')) { + if (!useDouble) { + d = static_cast<double>(use64bit ? i64 : i); + useDouble = true; + } + + bool expMinus = false; + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) + expMinus = true; + + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast<int>(s.Take() - '0'); + if (expMinus) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast<int>(s.Take() - '0'); + if (exp >= 214748364) { // Issue #313: prevent overflow exponent + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast<int>(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast<SizeType>(s.Length()); + StringStream srcStream(s.Pop()); + StackStream<typename TargetEncoding::Ch> dstStream(stack_); + while (numCharsToCopy--) { + Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else { + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast<int64_t>(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast<int32_t>(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template<unsigned parseFlags, typename InputStream, typename Handler> + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull <parseFlags>(is, handler); break; + case 't': ParseTrue <parseFlags>(is, handler); break; + case 'f': ParseFalse <parseFlags>(is, handler); break; + case '"': ParseString<parseFlags>(is, handler); break; + case '{': ParseObject<parseFlags>(is, handler); break; + case '[': ParseArray <parseFlags>(is, handler); break; + default : + ParseNumber<parseFlags>(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingStartState = 0, + IterativeParsingFinishState, + IterativeParsingErrorState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingKeyValueDelimiterState, + IterativeParsingMemberValueState, + IterativeParsingMemberDelimiterState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingElementDelimiterState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState + }; + + enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) + return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]); + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + } + }; // End of G + + return static_cast<IterativeParsingState>(G[state][token]); + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template <unsigned parseFlags, typename InputStream, typename Handler> + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push<SizeType>(1) = n; + // Initialize and push the member/element count. + *stack_.template Push<SizeType>(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString<parseFlags>(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop<SizeType>(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop<SizeType>(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue<parseFlags>(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template <typename InputStream> + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } + } + + template <unsigned parseFlags, typename InputStream, typename Handler> + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments<parseFlags>(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader<UTF8<>, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h new file mode 100644 index 00000000..b182aa27 --- /dev/null +++ b/include/rapidjson/schema.h @@ -0,0 +1,2006 @@ +// Tencent is pleased to support the open source community by making RapidJSON available-> +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved-> +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License-> You may obtain a copy of the License at +// +// http://opensource->org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied-> See the License for the +// specific language governing permissions and limitations under the License-> + +#ifndef RAPIDJSON_SCHEMA_H_ +#define RAPIDJSON_SCHEMA_H_ + +#include "document.h" +#include "pointer.h" +#include <cmath> // abs, floor + +#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 +#endif + +#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) +#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +#include "internal/regex.h" +#elif RAPIDJSON_SCHEMA_USE_STDREGEX +#include <regex> +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX +#define RAPIDJSON_SCHEMA_HAS_REGEX 1 +#else +#define RAPIDJSON_SCHEMA_HAS_REGEX 0 +#endif + +#ifndef RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#endif + +#if RAPIDJSON_SCHEMA_VERBOSE +#include "stringbuffer.h" +#endif + +RAPIDJSON_DIAG_PUSH + +#if defined(__GNUC__) +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(weak-vtables) +RAPIDJSON_DIAG_OFF(exit-time-destructors) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +RAPIDJSON_DIAG_OFF(variadic-macros) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Verbose Utilities + +#if RAPIDJSON_SCHEMA_VERBOSE + +namespace internal { + +inline void PrintInvalidKeyword(const char* keyword) { + printf("Fail keyword: %s\n", keyword); +} + +inline void PrintInvalidKeyword(const wchar_t* keyword) { + wprintf(L"Fail keyword: %ls\n", keyword); +} + +inline void PrintInvalidDocument(const char* document) { + printf("Fail document: %s\n\n", document); +} + +inline void PrintInvalidDocument(const wchar_t* document) { + wprintf(L"Fail document: %ls\n\n", document); +} + +inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { + printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { + wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) +#else +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) +#endif + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidKeyword = keyword.GetString();\ + RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\ + return false;\ +RAPIDJSON_MULTILINEMACRO_END + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template <typename ValueType, typename Allocator> +class GenericSchemaDocument; + +namespace internal { + +template <typename SchemaDocumentType> +class Schema; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaValidator + +class ISchemaValidator { +public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaStateFactory + +template <typename SchemaType> +class ISchemaStateFactory { +public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template<typename Encoding, typename Allocator> +class Hasher { +public: + typedef typename Encoding::Ch Ch; + + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + + bool Null() { return WriteType(kNullType); } + bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } + bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast<int64_t>(d); + else n.u.u = static_cast<uint64_t>(d); + n.d = d; + return WriteNumber(n); + } + + bool RawNumber(const Ch* str, SizeType len, bool) { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } + + bool String(const Ch* str, SizeType len, bool) { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } + + bool StartObject() { return true; } + bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } + bool EndObject(SizeType memberCount) { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2); + for (SizeType i = 0; i < memberCount; i++) + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + *stack_.template Push<uint64_t>() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop<uint64_t>(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push<uint64_t>() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top<uint64_t>(); + } + +private: + static const size_t kDefaultSize = 256; + struct Number { + union U { + uint64_t u; + int64_t i; + }u; + double d; + }; + + bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } + + bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } + + bool WriteBuffer(Type type, const void* data, size_t len) { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast<const unsigned char*>(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push<uint64_t>() = h; + return true; + } + + static uint64_t Hash(uint64_t h, uint64_t d) { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } + + Stack<Allocator> stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template <typename SchemaDocumentType> +struct SchemaValidationContext { + typedef Schema<SchemaDocumentType> SchemaType; + typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) : + factory(f), + schema(s), + valueSchema(), + invalidKeyword(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } + + ~SchemaValidationContext() { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { + for (SizeType i = 0; i < validatorCount; i++) + factory.DestroySchemaValidator(validators[i]); + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) + factory.FreeState(patternPropertiesSchemas); + if (propertyExist) + factory.FreeState(propertyExist); + } + + SchemaValidatorFactoryType& factory; + const SchemaType* schema; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Schema + +template <typename SchemaDocumentType> +class Schema { +public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext<SchemaDocumentType> Context; + typedef Schema<SchemaDocumentType> SchemaType; + typedef GenericValue<EncodingType, AllocatorType> SValue; + friend class GenericSchemaDocument<ValueType, AllocatorType>; + + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : + allocator_(allocator), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false) + { + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + + if (!value.IsObject()) + return; + + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) + AddType(*v); + else if (v->IsArray()) + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + AddType(*itr); + } + + if (const ValueType* v = GetMember(value, GetEnumString())) + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType; + char buffer[256 + 24]; + MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } + + if (schemaDocument) { + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + } + + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } + + // Object + + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); + + if (properties && properties->IsObject()) + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + AddUniqueElement(allProperties, itr->name); + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) + AddUniqueElement(allProperties, *itr); + + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); + if (itr->value.IsArray()) + for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if (i->IsString()) + AddUniqueElement(allProperties, *i); + } + + if (allProperties.Size() > 0) { + propertyCount_ = allProperties.Size(); + properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = GetTypeless(); + } + } + } + + if (properties && properties->IsObject()) { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { + SizeType index; + if (FindPropertyIndex(itr->name, &index)) + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document); + } + } + + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document); + patternPropertyCount_++; + } + } + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) { + SizeType index; + if (FindPropertyIndex(*itr, &index)) { + properties_[index].required = true; + hasRequired_ = true; + } + } + + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + SizeType sourceIndex; + if (FindPropertyIndex(itr->name, &sourceIndex)) { + if (itr->value.IsArray()) { + properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { + SizeType targetIndex; + if (FindPropertyIndex(*targetItr, &targetIndex)) + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } + + if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + + // Array + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation + schemaDocument->CreateSchema(&itemsList_, q, *v, document); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + + if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { + if (v->IsBool()) + additionalItems_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) + pattern_ = CreatePattern(*v); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) + if (v->IsNumber()) + minimum_.CopyFrom(*v, *allocator_); + + if (const ValueType* v = GetMember(value, GetMaximumString())) + if (v->IsNumber()) + maximum_.CopyFrom(*v, *allocator_); + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); + } + + ~Schema() { + if (allocator_) { + allocator_->Free(enum_); + } + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); + AllocatorType::Free(properties_); + } + if (patternProperties_) { + for (SizeType i = 0; i < patternPropertyCount_; i++) + patternProperties_[i].~PatternProperty(); + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); +#if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); + allocator_->Free(pattern_); + } +#endif + } + + bool BeginValue(Context& context) const { + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; + + if (itemsList_) + context.valueSchema = itemsList_; + else if (itemsTuple_) { + if (context.arrayElementIndex < itemsTupleCount_) + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) + context.valueSchema = GetTypeless(); + else + RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); + } + else + context.valueSchema = GetTypeless(); + + context.arrayElementIndex++; + } + return true; + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + + bool patternValid = true; + for (SizeType i = 0; i < count; i++) + if (!context.patternPropertiesValidators[i]->IsValid()) { + patternValid = false; + break; + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { + if (!patternValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { + if (!patternValid || !otherValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + + if (enum_) { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for (SizeType i = 0; i < enumCount_; i++) + if (enum_[i] == h) + goto foundEnum; + RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString()); + foundEnum:; + } + + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString()); + + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString()); + foundAny:; + } + + if (oneOf_.schemas) { + bool oneValid = false; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + else + oneValid = true; + } + if (!oneValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString()); + + return true; + } + + bool Null(Context& context) const { + if (!(type_ & (1 << kNullSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + if (!(type_ & (1 << kNumberSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + return false; + + if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + return false; + + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + return false; + + return CreateParallelValidator(context); + } + + bool String(Context& context, const Ch* str, SizeType length, bool) const { + if (!(type_ & (1 << kStringSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) { + if (count < minLength_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString()); + if (count > maxLength_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString()); + } + } + + if (pattern_ && !IsPatternMatch(pattern_, str, length)) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString()); + + return CreateParallelValidator(context); + } + + bool StartObject(Context& context) const { + if (!(type_ & (1 << kObjectSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } + + if (patternProperties_) { // pre-allocate schema array + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } + + return CreateParallelValidator(context); + } + + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) + if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + } + + SizeType index; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = GetTypeless(); + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + context.valueSchema = properties_[index].schema; + + if (context.propertyExist) + context.propertyExist[index] = true; + + return true; + } + + if (additionalPropertiesSchema_) { + if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = GetTypeless(); + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + context.valueSchema = additionalPropertiesSchema_; + return true; + } + else if (additionalProperties_) { + context.valueSchema = GetTypeless(); + return true; + } + + if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString()); + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { + if (hasRequired_) + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].required) + if (!context.propertyExist[index]) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); + + if (memberCount < minProperties_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString()); + + if (memberCount > maxProperties_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString()); + + if (hasDependencies_) { + for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) + if (context.propertyExist[sourceIndex]) { + if (properties_[sourceIndex].dependencies) { + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex]) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + else if (properties_[sourceIndex].dependenciesSchema) + if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + } + + return true; + } + + bool StartArray(Context& context) const { + if (!(type_ & (1 << kArraySchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + context.arrayElementIndex = 0; + context.inArray = true; + + return CreateParallelValidator(context); + } + + bool EndArray(Context& context, SizeType elementCount) const { + context.inArray = false; + + if (elementCount < minItems_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString()); + + if (elementCount > maxItems_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString()); + + return true; + } + + // Generate functions for string literal according to Ch +#define RAPIDJSON_STRING_(name, ...) \ + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\ + return v;\ + } + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex<EncodingType> RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex<Ch> RegexType; +#else + typedef char RegexType; +#endif + + struct SchemaArray { + SchemaArray() : schemas(), count() {} + ~SchemaArray() { AllocatorType::Free(schemas); } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; + + static const SchemaType* GetTypeless() { + static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); + return &typeless; + } + + template <typename V1, typename V2> + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if (*itr == v) + return; + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } + + static const ValueType* GetMember(const ValueType& value, const ValueType& name) { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } + + static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsBool()) + out = v->GetBool(); + } + + static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) + out = static_cast<SizeType>(v->GetUint64()); + } + + void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { + if (const ValueType* v = GetMember(value, name)) { + if (v->IsArray() && v->Size() > 0) { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for (SizeType i = 0; i < out.count; i++) + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template <typename ValueType> + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString()); + if (!r->IsValid()) { + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + return pattern->Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template <typename ValueType> + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) + try { + return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch (const std::regex_error&) { + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results<const Ch*> r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template <typename ValueType> + RegexType* CreatePattern(const ValueType&) { return 0; } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } +#endif // RAPIDJSON_SCHEMA_USE_STDREGEX + + void AddType(const ValueType& type) { + if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; + else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; + else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; + else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; + else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; + else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); + + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + context.validatorCount = validatorCount_; + + if (allOf_.schemas) + CreateSchemaValidators(context, allOf_); + + if (anyOf_.schemas) + CreateSchemaValidators(context, anyOf_); + + if (oneOf_.schemas) + CreateSchemaValidators(context, oneOf_); + + if (not_) + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); + + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema); + } + } + + return true; + } + + void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const { + for (SizeType i = 0; i < schemas.count; i++) + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); + } + + // O(n) + bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } + + bool CheckInt(Context& context, int64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + else if (minimum_.IsUint64()) { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast<double>(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + else if (maximum_.IsUint64()) + /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast<double>(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + else if (!CheckDoubleMultipleOf(context, static_cast<double>(i))) + return false; + } + + return true; + } + + bool CheckUint(Context& context, uint64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if (!CheckDoubleMinimum(context, static_cast<double>(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + else if (maximum_.IsInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_ + else if (!CheckDoubleMaximum(context, static_cast<double>(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (i % multipleOf_.GetUint64() != 0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + else if (!CheckDoubleMultipleOf(context, static_cast<double>(i))) + return false; + } + + return true; + } + + bool CheckDoubleMinimum(Context& context, double d) const { + if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { + if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + return true; + } + + bool CheckDoubleMultipleOf(Context& context, double d) const { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if (r > 0.0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + return true; + } + + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; + + AllocatorType* allocator_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; + + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; + + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; + + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; +}; + +template<typename Stack, typename Ch> +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push<Ch>() = '/'; + char buffer[21]; + size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push<Ch>() = buffer[i]; + } +}; + +// Partial specialized version for char to prevent buffer copying. +template <typename Stack> +struct TokenHelper<Stack, char> { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template <typename SchemaDocumentType> +class IGenericRemoteSchemaDocumentProvider { +public: + typedef typename SchemaDocumentType::Ch Ch; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaDocument + +//! JSON schema document. +/*! + A JSON schema document is a compiled version of a JSON schema. + It is basically a tree of internal::Schema. + + \note This is an immutable class (i.e. its instance cannot be modified after construction). + \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding. + \tparam Allocator Allocator type for allocating memory of this document. +*/ +template <typename ValueT, typename Allocator = CrtAllocator> +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema<GenericSchemaDocument> SchemaType; + typedef GenericPointer<ValueType, Allocator> PointerType; + friend class internal::Schema<GenericSchemaDocument>; + template <typename, typename, typename> + friend class GenericSchemaValidator; + + //! Constructor. + /*! + Compile a JSON document into schema document. + + \param document A JSON document as source. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + */ + explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize) + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call AddRefSchema() if there are $ref. + CreateSchemaRecursive(&root_, PointerType(), document, document); + + // Resolve $ref + while (!schemaRef_.Empty()) { + SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1); + if (const SchemaType* s = GetSchema(refEntry->target)) { + if (refEntry->schema) + *refEntry->schema = s; + + // Create entry in map if not exist + if (!GetSchema(refEntry->source)) { + new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_); + } + } + refEntry->~SchemaRefEntry(); + } + + RAPIDJSON_ASSERT(root_ != 0); + + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry(); + + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + +private: + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument&); + //! Prohibit assignment + GenericSchemaDocument& operator=(const GenericSchemaDocument&); + + struct SchemaRefEntry { + SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} + PointerType source; + PointerType target; + const SchemaType** schema; + }; + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} + ~SchemaEntry() { + if (owned) { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; + + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + if (schema) + *schema = SchemaType::GetTypeless(); + + if (v.GetType() == kObjectType) { + const SchemaType* s = GetSchema(pointer); + if (!s) + CreateSchema(schema, pointer, v, document); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); + } + + void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + RAPIDJSON_ASSERT(pointer.IsValid()); + if (v.IsObject()) { + if (!HandleRefSchema(pointer, schema, v, document)) { + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); + new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_); + if (schema) + *schema = s; + } + } + } + + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) { + static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; + static const ValueType kRefValue(kRefString, 4); + + typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); + if (itr == v.MemberEnd()) + return false; + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len > 0) { + const Ch* s = itr->value.GetString(); + SizeType i = 0; + while (i < len && s[i] != '#') // Find the first # + i++; + + if (i > 0) { // Remote reference, resolve immediately + if (remoteProvider_) { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) { + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + return true; + } + } + } + } + } + else if (s[i] == '#') { // Local reference, defer resolution + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const ValueType* nv = pointer.Get(document)) + if (HandleRefSchema(source, schema, *nv, document)) + return true; + + new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_); + return true; + } + } + } + } + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target) + if (schema == target->schema) + return target->pointer; + return PointerType(); + } + + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. + internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas + internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument<Value> SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaValidator + +//! JSON Schema Validator. +/*! + A SAX style JSON schema validator. + It uses a \c GenericSchemaDocument to validate SAX events. + It delegates the incoming SAX events to an output handler. + The default output handler does nothing. + It can be reused multiple times by calling \c Reset(). + + \tparam SchemaDocumentType Type of schema document. + \tparam OutputHandler Type of output handler. Default handler does nothing. + \tparam StateAllocator Allocator for storing the internal validation states. +*/ +template < + typename SchemaDocumentType, + typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>, + public internal::ISchemaValidator +{ +public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + outputHandler_(GetNullHandler()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + OutputHandler& outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + outputHandler_(outputHandler), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Destructor. + ~GenericSchemaValidator() { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } + + //! Reset the internal states. + void Reset() { + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); + valid_ = true; + } + + //! Checks whether the current state is valid. + // Implementation of ISchemaValidator + virtual bool IsValid() const { return valid_; } + + //! Gets the JSON pointer pointed to the invalid schema. + PointerType GetInvalidSchemaPointer() const { + return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); + } + + //! Gets the keyword of invalid schema. + const Ch* GetInvalidSchemaKeyword() const { + return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword; + } + + //! Gets the JSON pointer pointed to the invalid value. + PointerType GetInvalidDocumentPointer() const { + return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch)); + } + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + *documentStack_.template Push<Ch>() = '\0';\ + documentStack_.template Pop<Ch>(1);\ + internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\ +RAPIDJSON_MULTILINEMACRO_END +#else +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() +#endif + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if (!BeginValue() || !CurrentSchema().method arg1) {\ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ + return valid_ = false;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\ + if (context->hasher)\ + static_cast<HasherType*>(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ + return valid_ = EndValue() && outputHandler_.method arg2 + +#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + + bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); } + bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } + bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } + bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } + bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } + bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } + bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool String(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + return valid_ = outputHandler_.StartObject(); + } + + bool Key(const Ch* str, SizeType len, bool copy) { + if (!valid_) return false; + AppendToken(str, len); + if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + return valid_ = outputHandler_.Key(str, len, copy); + } + + bool EndObject(SizeType memberCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + return valid_ = outputHandler_.StartArray(); + } + + bool EndArray(SizeType elementCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } + +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory<SchemaType> + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) { + return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, +#if RAPIDJSON_SCHEMA_VERBOSE + depth_ + 1, +#endif + &GetStateAllocator()); + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } + + virtual void* CreateHasher() { + return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } + + virtual uint64_t GetHashCode(void* hasher) { + return static_cast<HasherType*>(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast<HasherType*>(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + return StateAllocator::Free(p); + } + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray; + typedef internal::Hasher<EncodingType, StateAllocator> HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth, +#endif + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + outputHandler_(GetNullHandler()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(depth) +#endif + { + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator()); + return *stateAllocator_; + } + + bool BeginValue() { + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + + if (!CurrentSchema().BeginValue(CurrentContext())) + return false; + + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + if (CurrentContext().valueSchema) + PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count)); + for (SizeType i = 0; i < count; i++) + va[validatorCount++] = CreateSchemaValidator(*sa[i]); + } + + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } + + bool EndValue() { + if (!CurrentSchema().EndValue(CurrentContext())) + return false; + +#if RAPIDJSON_SCHEMA_VERBOSE + GenericStringBuffer<EncodingType> sb; + schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); + + *documentStack_.template Push<Ch>() = '\0'; + documentStack_.template Pop<Ch>(1); + internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>()); +#endif + + uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); + if (context.valueUniqueness) { + HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if (itr->GetUint64() == h) + RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString()); + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe<Ch>() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe<Ch>() = '~'; + *documentStack_.template PushUnsafe<Ch>() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe<Ch>() = '~'; + *documentStack_.template PushUnsafe<Ch>() = '1'; + } + else + *documentStack_.template PushUnsafe<Ch>() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop<Context>(1); + if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top<Context>(); } + const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); } + + static OutputHandler& GetNullHandler() { + static OutputHandler nullHandler; + return nullHandler; + } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + OutputHandler& outputHandler_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch) + bool valid_; +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth_; +#endif +}; + +typedef GenericSchemaValidator<SchemaDocument> SchemaValidator; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidatingReader + +//! A helper class for parsing with validation. +/*! + This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate(). + + \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam SourceEncoding Encoding of the input stream. + \tparam SchemaDocumentType Type of schema document. + \tparam StackAllocator Allocator type for stack. +*/ +template < + unsigned parseFlags, + typename InputStream, + typename SourceEncoding, + typename SchemaDocumentType = SchemaDocument, + typename StackAllocator = CrtAllocator> +class SchemaValidatingReader { +public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {} + + template <typename Handler> + bool operator()(Handler& handler) { + GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader; + GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler); + parseResult_ = reader.template Parse<parseFlags>(is_, validator); + + isValid_ = validator.IsValid(); + if (isValid_) { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + } + + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + bool IsValid() const { return isValid_; } + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + +private: + InputStream& is_; + const SchemaDocumentType& sd_; + + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + bool isValid_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_SCHEMA_H_ diff --git a/include/rapidjson/stream.h b/include/rapidjson/stream.h new file mode 100644 index 00000000..fef82c25 --- /dev/null +++ b/include/rapidjson/stream.h @@ -0,0 +1,179 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "rapidjson.h" + +#ifndef RAPIDJSON_STREAM_H_ +#define RAPIDJSON_STREAM_H_ + +#include "encodings.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template<typename Stream> +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits<StringStream>. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template<typename Stream> +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template<typename Stream> +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template<typename Stream, typename Ch> +inline void PutN(Stream& stream, Ch c, size_t n) { + PutReserve(stream, n); + for (size_t i = 0; i < n; i++) + PutUnsafe(stream, c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template <typename Encoding> +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast<size_t>(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template <typename Encoding> +struct StreamTraits<GenericStringStream<Encoding> > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream<UTF8<> > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template <typename Encoding> +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast<size_t>(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template <typename Encoding> +struct StreamTraits<GenericInsituStringStream<Encoding> > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream<UTF8<> > InsituStringStream; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STREAM_H_ diff --git a/include/rapidjson/stringbuffer.h b/include/rapidjson/stringbuffer.h new file mode 100644 index 00000000..78f34d20 --- /dev/null +++ b/include/rapidjson/stringbuffer.h @@ -0,0 +1,117 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include <utility> // std::move +#endif + +#include "internal/stack.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template <typename Encoding, typename Allocator = CrtAllocator> +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push<Ch>() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop<Ch>(1); + } + + void Reserve(size_t count) { stack_.template Reserve<Ch>(count); } + Ch* Push(size_t count) { return stack_.template Push<Ch>(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); } + void Pop(size_t count) { stack_.template Pop<Ch>(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push<Ch>() = '\0'; + stack_.template Pop<Ch>(1); + + return stack_.template Bottom<Ch>(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack<Allocator> stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer<UTF8<> > StringBuffer; + +template<typename Encoding, typename Allocator> +inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { + stream.Reserve(count); +} + +template<typename Encoding, typename Allocator> +inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) { + std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h new file mode 100644 index 00000000..94f22dd5 --- /dev/null +++ b/include/rapidjson/writer.h @@ -0,0 +1,610 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "stream.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include <new> // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include <intrin.h> +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include <nmmintrin.h> +#elif defined(RAPIDJSON_SSE2) +#include <emmintrin.h> +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags +#endif + +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + static const int kDefaultMaxDecimalPlaces = 324; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer<OutputStream> writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string<Ch>& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push<Level>()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push<Level>()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray); + level_stack_.template Pop<Level>(1); + return EndValue(WriteEndArray()); + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); } + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + static const size_t kDefaultLevelDepth = 32; + + bool WriteNull() { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); + } + else { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast<size_t>(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p)); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); + GenericStringStream<SourceEncoding> is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + return false; + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)])); + if (escape[static_cast<unsigned char>(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : + Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + for (size_t i = 0; i < length; i++) { + RAPIDJSON_ASSERT(json[i] != '\0'); + PutUnsafe(*os_, json[i]); + } + return true; + } + + void Prefix(Type type) { + (void)type; + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root + Level* level = level_stack_.template Top<Level>(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + os_->Flush(); + return ret; + } + + OutputStream* os_; + internal::Stack<StackAllocator> level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer<StringBuffer>::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast<size_t>(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast<size_t>(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast<size_t>(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast<size_t>(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer<StringBuffer>::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast<size_t>(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); + const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19 + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast<SizeType>(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast<char*>(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + +RAPIDJSON_NAMESPACE_END + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/include/smtp/SmtpMime b/include/smtp/SmtpMime new file mode 100644 index 00000000..940996b8 --- /dev/null +++ b/include/smtp/SmtpMime @@ -0,0 +1,31 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef SMTPMIME_H +#define SMTPMIME_H + +#include "smtpclient.h" +#include "mimepart.h" +#include "mimehtml.h" +#include "mimeattachment.h" +#include "mimemessage.h" +#include "mimetext.h" +#include "mimeinlinefile.h" +#include "mimefile.h" + +#endif // SMTPMIME_H diff --git a/include/smtp/emailaddress.h b/include/smtp/emailaddress.h new file mode 100644 index 00000000..90e4c1e9 --- /dev/null +++ b/include/smtp/emailaddress.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef EMAILADDRESS_H +#define EMAILADDRESS_H + +#include <QObject> + +#include "smtpexports.h" + +class SMTP_EXPORT EmailAddress : public QObject { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + EmailAddress() = default; + + explicit EmailAddress(const QString &address, const QString &name = ""); + + ~EmailAddress() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + void setName(const QString &name); + + void setAddress(const QString &address); + + [[nodiscard]] const QString &getName() const; + + [[nodiscard]] const QString &getAddress() const; + + /* [2] --- */ + + +private: + + /* [3] Private members */ + + QString name; + QString address; + + /* [3] --- */ +}; + +#endif // EMAILADDRESS_H diff --git a/include/smtp/mimeattachment.h b/include/smtp/mimeattachment.h new file mode 100644 index 00000000..6b98a65a --- /dev/null +++ b/include/smtp/mimeattachment.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEATTACHMENT_H +#define MIMEATTACHMENT_H + +#include <QFile> +#include "mimepart.h" +#include "mimefile.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeAttachment : public MimeFile { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + explicit MimeAttachment(QFile *file); + + MimeAttachment(const QByteArray &stream, const QString &fileName); + + ~MimeAttachment() override; + + /* [1] --- */ + +protected: + + /* [2] Protected methods */ + + void prepare() override; + + /* [2] --- */ +}; + +#endif // MIMEATTACHMENT_H diff --git a/include/smtp/mimecontentformatter.h b/include/smtp/mimecontentformatter.h new file mode 100644 index 00000000..e6e3637f --- /dev/null +++ b/include/smtp/mimecontentformatter.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMECONTENTFORMATTER_H +#define MIMECONTENTFORMATTER_H + +#include <QObject> +#include <QByteArray> + +#include "smtpexports.h" + +class SMTP_EXPORT MimeContentFormatter : public QObject { +Q_OBJECT +public: + explicit MimeContentFormatter(int max_length = 76); + + void setMaxLength(int l); + + [[nodiscard]] int getMaxLength() const; + + [[nodiscard]] QString format(const QString &content, bool quotedPrintable = false) const; + +protected: + int max_length; + +}; + +#endif // MIMECONTENTFORMATTER_H diff --git a/include/smtp/mimefile.h b/include/smtp/mimefile.h new file mode 100644 index 00000000..46903da9 --- /dev/null +++ b/include/smtp/mimefile.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEFILE_H +#define MIMEFILE_H + +#include "mimepart.h" +#include <QFile> + +#include "smtpexports.h" + +class SMTP_EXPORT MimeFile : public MimePart { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + MimeFile(const QByteArray &stream, const QString &fileName); + + explicit MimeFile(QFile *f); + + ~MimeFile() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + QFile *file; + + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ + +}; + +#endif // MIMEFILE_H diff --git a/include/smtp/mimehtml.h b/include/smtp/mimehtml.h new file mode 100644 index 00000000..8ce8c454 --- /dev/null +++ b/include/smtp/mimehtml.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEHTML_H +#define MIMEHTML_H + +#include "mimetext.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeHtml : public MimeText { +Q_OBJECT +public: + + /* [1] Constructors and Destructors */ + + explicit MimeHtml(const QString &html = ""); + + ~MimeHtml() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + void setHtml(const QString &html); + + [[nodiscard]] const QString &getHtml() const; + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ +}; + +#endif // MIMEHTML_H diff --git a/include/smtp/mimeinlinefile.h b/include/smtp/mimeinlinefile.h new file mode 100644 index 00000000..916f7b76 --- /dev/null +++ b/include/smtp/mimeinlinefile.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEINLINEFILE_H +#define MIMEINLINEFILE_H + +#include "mimefile.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeInlineFile : public MimeFile { +public: + + /* [1] Constructors and Destructors */ + + explicit MimeInlineFile(QFile *f); + + ~MimeInlineFile() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ +}; + +#endif // MIMEINLINEFILE_H diff --git a/include/smtp/mimemessage.h b/include/smtp/mimemessage.h new file mode 100644 index 00000000..24e4f108 --- /dev/null +++ b/include/smtp/mimemessage.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEMESSAGE_H +#define MIMEMESSAGE_H + +#include "mimepart.h" +#include "mimemultipart.h" +#include "emailaddress.h" +#include <QList> + +#include "smtpexports.h" + +class SMTP_EXPORT MimeMessage : public QObject { +public: + + enum RecipientType { + To, // primary + Cc, // carbon copy + Bcc // blind carbon copy + }; + + /* [1] Constructors and Destructors */ + + explicit MimeMessage(bool createAutoMimeConent = true); + + ~MimeMessage() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + void setSender(EmailAddress *e); + + void addRecipient(EmailAddress *rcpt, RecipientType type = To); + + void addTo(EmailAddress *rcpt); + + void addCc(EmailAddress *rcpt); + + void addBcc(EmailAddress *rcpt); + + void setSubject(const QString &subject); + + void addPart(MimePart *part); + + void setReplyTo(EmailAddress *rto); + + void setInReplyTo(const QString &inReplyTo); + + void setHeaderEncoding(MimePart::Encoding); + + [[nodiscard]] const EmailAddress &getSender() const; + + [[nodiscard]] const QList<EmailAddress *> &getRecipients(RecipientType type = To) const; + + [[nodiscard]] const QString &getSubject() const; + + [[nodiscard]] const QList<MimePart *> &getParts() const; + + [[nodiscard]] const EmailAddress *getReplyTo() const; + + MimePart &getContent(); + + void setContent(MimePart *content); + /* [2] --- */ + + + /* [3] Public methods */ + + virtual QString toString(); + + /* [3] --- */ + +protected: + + /* [4] Protected members */ + + EmailAddress *sender{}; + EmailAddress *replyTo; + QList<EmailAddress *> recipientsTo, recipientsCc, recipientsBcc; + QString subject; + QString mInReplyTo; + MimePart *content; + bool autoMimeContentCreated; + + MimePart::Encoding hEncoding; + + /* [4] --- */ + + +}; + +#endif // MIMEMESSAGE_H diff --git a/include/smtp/mimemultipart.h b/include/smtp/mimemultipart.h new file mode 100644 index 00000000..b829a66f --- /dev/null +++ b/include/smtp/mimemultipart.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEMULTIPART_H +#define MIMEMULTIPART_H + +#include "mimepart.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeMultiPart : public MimePart { +Q_OBJECT +public: + /* [0] Enums */ + enum MultiPartType { + Mixed = 0, // RFC 2046, section 5.1.3 + Digest = 1, // RFC 2046, section 5.1.5 + Alternative = 2, // RFC 2046, section 5.1.4 + Related = 3, // RFC 2387 + Report = 4, // RFC 6522 + Signed = 5, // RFC 1847, section 2.1 + Encrypted = 6 // RFC 1847, section 2.2 + }; + + /* [0] --- */ + + /* [1] Constructors and Destructors */ + explicit MimeMultiPart(MultiPartType type = Related); + + /* [1] --- */ + + /* [2] Getters and Setters */ + + void setMimeType(MultiPartType type); + + [[nodiscard]] MultiPartType getMimeType() const; + + [[nodiscard]] const QList<MimePart *> &getParts() const; + + /* [2] --- */ + + /* [3] Public methods */ + + void addPart(MimePart *part); + + void prepare() override; + + /* [3] --- */ + +protected: + QList<MimePart *> parts; + + MultiPartType type; +}; + +#endif // MIMEMULTIPART_H diff --git a/include/smtp/mimepart.h b/include/smtp/mimepart.h new file mode 100644 index 00000000..1a1386de --- /dev/null +++ b/include/smtp/mimepart.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMEPART_H +#define MIMEPART_H + +#include "mimecontentformatter.h" +#include <QObject> + +#include "smtpexports.h" + +class SMTP_EXPORT MimePart : public QObject { +Q_OBJECT +public: + /* [0] Enumerations */ + enum Encoding { + _7Bit, _8Bit, Base64, QuotedPrintable + }; + + /* [0] --- */ + + /* [1] Constructors and Destructors */ + + MimePart(); + + ~MimePart() = default; + + /* [1] --- */ + + /* [2] Getters and Setters */ + + [[nodiscard]] const QString &getHeader() const; + + [[nodiscard]] const QByteArray &getContent() const; + + void setContent(const QByteArray &content); + + void setHeader(const QString &header); + + void addHeaderLine(const QString &line); + + void setContentId(const QString &cId); + + [[nodiscard]] const QString &getContentId() const; + + void setContentName(const QString &cName); + + [[nodiscard]] const QString &getContentName() const; + + void setContentType(const QString &cType); + + [[nodiscard]] const QString &getContentType() const; + + void setCharset(const QString &charset); + + [[nodiscard]] const QString &getCharset() const; + + void setEncoding(Encoding enc); + + [[nodiscard]] Encoding getEncoding() const; + + MimeContentFormatter &getContentFormatter(); + + /* [2] --- */ + + /* [3] Public methods */ + + virtual QString toString(); + + virtual void prepare(); + + /* [3] --- */ + +protected: + /* [4] Protected members */ + + QString header; + QByteArray content; + + QString cId; + QString cName; + QString cType; + QString cCharset; + QString cBoundary; + Encoding cEncoding; + + QString mimeString; + bool prepared; + + MimeContentFormatter formatter; + + /* [4] --- */ +}; + +#endif // MIMEPART_H diff --git a/include/smtp/mimetext.h b/include/smtp/mimetext.h new file mode 100644 index 00000000..c21a1c5e --- /dev/null +++ b/include/smtp/mimetext.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef MIMETEXT_H +#define MIMETEXT_H + +#include "mimepart.h" + +#include "smtpexports.h" + +class SMTP_EXPORT MimeText : public MimePart { +public: + + /* [1] Constructors and Destructors */ + + explicit MimeText(const QString &text = ""); + + ~MimeText() override; + + /* [1] --- */ + + + /* [2] Getters and Setters*/ + + void setText(const QString &text); + + [[nodiscard]] const QString &getText() const; + + /* [2] --- */ + +protected: + + /* [3] Protected members */ + + QString text; + /* [3] --- */ + + + /* [4] Protected methods */ + + void prepare() override; + + /* [4] --- */ + +}; + +#endif // MIMETEXT_H diff --git a/include/smtp/quotedprintable.h b/include/smtp/quotedprintable.h new file mode 100644 index 00000000..00ca3cf8 --- /dev/null +++ b/include/smtp/quotedprintable.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef QUOTEDPRINTABLE_H +#define QUOTEDPRINTABLE_H + +#include <QObject> +#include <QByteArray> + +#include "smtpexports.h" + +class SMTP_EXPORT QuotedPrintable : public QObject { +Q_OBJECT +public: + + static QString encode(const QByteArray &input); + + static QByteArray decode(const QString &input); + +private: + QuotedPrintable(); +}; + +#endif // QUOTEDPRINTABLE_H diff --git a/include/smtp/smtpclient.h b/include/smtp/smtpclient.h new file mode 100644 index 00000000..29c507dc --- /dev/null +++ b/include/smtp/smtpclient.h @@ -0,0 +1,197 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#ifndef SMTPCLIENT_H +#define SMTPCLIENT_H + +#include <QObject> +#include <QtNetwork/QSslSocket> + +#include "mimemessage.h" +#include "smtpexports.h" + +class SMTP_EXPORT SmtpClient : public QObject { +Q_OBJECT +public: + + /* [0] Enumerations */ + + enum AuthMethod { + AuthPlain, + AuthLogin + }; + + enum SmtpError { + ConnectionTimeoutError, + ResponseTimeoutError, + SendDataTimeoutError, + AuthenticationFailedError, + ServerError, // 4xx smtp error + ClientError // 5xx smtp error + }; + + enum ConnectionType { + TcpConnection, + SslConnection, + TlsConnection // STARTTLS + }; + + /* [0] --- */ + + + /* [1] Constructors and Destructors */ + + explicit SmtpClient(const QString &host = "localhost", int port = 25, ConnectionType ct = TcpConnection); + + ~SmtpClient() override; + + /* [1] --- */ + + + /* [2] Getters and Setters */ + + [[nodiscard]] const QString &getHost() const; + + void setHost(const QString &host); + + [[nodiscard]] int getPort() const; + + void setPort(int port); + + [[nodiscard]] const QString &getName() const; + + void setName(const QString &name); + + [[nodiscard]] ConnectionType getConnectionType() const; + + void setConnectionType(ConnectionType ct); + + [[nodiscard]] const QString &getUser() const; + + void setUser(const QString &user); + + [[nodiscard]] const QString &getPassword() const; + + void setPassword(const QString &password); + + [[nodiscard]] SmtpClient::AuthMethod getAuthMethod() const; + + void setAuthMethod(AuthMethod method); + + [[nodiscard]] const QString &getResponseText() const; + + [[nodiscard]] int getResponseCode() const; + + [[nodiscard]] int getConnectionTimeout() const; + + void setConnectionTimeout(int msec); + + [[nodiscard]] int getResponseTimeout() const; + + void setResponseTimeout(int msec); + + [[nodiscard]] int getSendMessageTimeout() const; + + void setSendMessageTimeout(int msec); + + QTcpSocket *getSocket(); + + + /* [2] --- */ + + + /* [3] Public methods */ + + bool connectToHost(); + + bool login(); + + bool login(const QString &user, const QString &password, AuthMethod method = AuthLogin); + + bool sendMail(MimeMessage &email); + + void quit(); + + + /* [3] --- */ + +protected: + + /* [4] Protected members */ + + QTcpSocket *socket; + + QString host; + int port; + ConnectionType connectionType; + QString name; + + QString user; + QString password; + AuthMethod authMethod; + + int connectionTimeout; + int responseTimeout; + int sendMessageTimeout; + + + QString responseText; + int responseCode; + + + class ResponseTimeoutException : public std::exception { + }; + + class SendMessageTimeoutException : public std::exception { + }; + + /* [4] --- */ + + + /* [5] Protected methods */ + + void waitForResponse(); + + void sendMessage(const QString &text); + + /* [5] --- */ + +protected slots: + + /* [6] Protected slots */ + + void socketStateChanged(QAbstractSocket::SocketState state); + + void socketError(QAbstractSocket::SocketError error); + + void socketReadyRead(); + + /* [6] --- */ + + +signals: + + /* [7] Signals */ + + void smtpError(SmtpClient::SmtpError e); + + /* [7] --- */ + +}; + +#endif // SMTPCLIENT_H diff --git a/include/smtp/smtpexports.h b/include/smtp/smtpexports.h new file mode 100644 index 00000000..9ca12bae --- /dev/null +++ b/include/smtp/smtpexports.h @@ -0,0 +1,10 @@ +#ifndef SMTPEXPORTS_H
+#define SMTPEXPORTS_H
+
+#ifdef SMTP_BUILD
+#define SMTP_EXPORT
+#else
+#define SMTP_EXPORT
+#endif
+
+#endif // SMTPEXPORTS_H
diff --git a/include/ui/AttachmentTableModel.h b/include/ui/AttachmentTableModel.h deleted file mode 100644 index 9bc22cea..00000000 --- a/include/ui/AttachmentTableModel.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#ifndef __ATTACHMENTTABLEMODEL_H__ -#define __ATTACHMENTTABLEMODEL_H__ - -#include "Mime.h" - -class AttachmentTableModel : public QAbstractTableModel { -Q_OBJECT - -public: - explicit AttachmentTableModel(QObject *parent = nullptr); - - explicit AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent = nullptr); - - int rowCount(const QModelIndex &parent) const override; - - int columnCount(const QModelIndex &parent) const override; - - [[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; - - [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - - void add(const MimePart& mp); - - MimePart getSelectedMimePart(QModelIndex index); - - MimePart getMimePart(int index); - //QList<MimePart> getSelectedMimeParts(QModelIndexList indexes); - -private: - QList<MimePart> listOfMimeparts; -}; - -#endif // __ATTACHMENTTABLEMODEL_H__ diff --git a/include/ui/QuitDialog.h b/include/ui/QuitDialog.h index 8d69cfd2..19af7534 100755 --- a/include/ui/QuitDialog.h +++ b/include/ui/QuitDialog.h @@ -1,22 +1,25 @@ -/* - * keymgmt.h +/** + * This file is part of GPGFrontend. * - * Copyright 2008 gpg4usb-team <[email protected]> + * GPGFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This file is part of gpg4usb. + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Gpg4usb is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <https://www.gnu.org/licenses/>. * - * Gpg4usb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. * - * You should have received a copy of the GNU General Public License - * along with gpg4usb. If not, see <http://www.gnu.org/licenses/> */ #ifndef __QUITDIALOG_H__ @@ -30,7 +33,7 @@ Q_OBJECT public: QuitDialog(QWidget *parent, const QHash<int, QString>& unsavedDocs); - bool isDiscarded() const; + [[nodiscard]] bool isDiscarded() const; QList<int> getTabIdsToSave(); diff --git a/include/ui/SendMailDialog.h b/include/ui/SendMailDialog.h new file mode 100644 index 00000000..e01802d3 --- /dev/null +++ b/include/ui/SendMailDialog.h @@ -0,0 +1,66 @@ +/** + * This file is part of GPGFrontend. + * + * GPGFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + +#ifndef GPGFRONTEND_SENDMAILDIALOG_H +#define GPGFRONTEND_SENDMAILDIALOG_H + +#include "GpgFrontend.h" + +class SendMailDialog : public QDialog { +Q_OBJECT +public: + explicit SendMailDialog(QString text, QWidget *parent = nullptr); + +private slots: + + void slotConfirm(); + +private: + + QString appPath; + QSettings settings; + + QLineEdit *senderEdit; + QTextEdit *recipientEdit; + QLineEdit *subjectEdit; + QPushButton *confirmButton; + + QLabel *errorLabel; + QString mText; + + QString smtpAddress = settings.value("sendMail/smtpAddress", QString()).toString(); + QString username = settings.value("sendMail/username", QString()).toString(); + QString password = settings.value("sendMail/password", QString()).toString(); + QString defaultSender = settings.value("sendMail/defaultSender", QString()).toString(); + QString connectionTypeSettings = settings.value("sendMail/connectionType", QString()).toString(); + int port = settings.value("sendMail/port", QString()).toInt(); + + QRegularExpression re_email{ + R"((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))"}; + + bool check_email_address(const QString &str); +}; + + +#endif //GPGFRONTEND_SENDMAILDIALOG_H diff --git a/include/ui/SettingsDialog.h b/include/ui/SettingsDialog.h index f1a2863c..133a8ec7 100755 --- a/include/ui/SettingsDialog.h +++ b/include/ui/SettingsDialog.h @@ -66,24 +66,37 @@ signals: }; -class MimeTab : public QWidget { +class SendMailTab : public QWidget { Q_OBJECT public: - explicit MimeTab(QWidget *parent = nullptr); + explicit SendMailTab(QWidget *parent = nullptr); void setSettings(); void applySettings(); +private slots: + + void slotCheckConnection(); + + void slotCheckBoxSetEnableDisable(int state); + private: QString appPath; QSettings settings; - QCheckBox *mimeParseCheckBox; - QCheckBox *mimeQPCheckBox; - QCheckBox *mimeOpenAttachmentCheckBox; + QCheckBox *enableCheckBox; + + QLineEdit *smtpAddress; + QLineEdit *username; + QLineEdit *password; + QSpinBox *portSpin; + QComboBox *connectionTypeComboBox; + QLineEdit *defaultSender; + + QPushButton *checkConnectionButton; signals: @@ -115,6 +128,7 @@ private: QRadioButton *iconTextButton; QRadioButton *iconIconsButton; QRadioButton *iconAllButton; + QSpinBox *infoBoardFontSizeSpin; QCheckBox *windowSizeCheckBox; signals: @@ -208,7 +222,7 @@ public: explicit SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent = nullptr); GeneralTab *generalTab; - MimeTab *mimeTab; + SendMailTab *sendMailTab; AppearanceTab *appearanceTab; KeyserverTab *keyserverTab; AdvancedTab *advancedTab; diff --git a/include/ui/WaitingDialog.h b/include/ui/WaitingDialog.h index 64c77ad9..df781073 100644 --- a/include/ui/WaitingDialog.h +++ b/include/ui/WaitingDialog.h @@ -28,7 +28,7 @@ class WaitingDialog : public QDialog { Q_OBJECT public: - WaitingDialog(QWidget *parent = nullptr); + WaitingDialog(const QString &title, QWidget *parent); public slots: diff --git a/include/ui/AboutDialog.h b/include/ui/help/AboutDialog.h index b7d54544..74391b5a 100644 --- a/include/ui/AboutDialog.h +++ b/include/ui/help/AboutDialog.h @@ -52,6 +52,29 @@ public: }; /** + * @brief Class containing the main tab of about dialog + * + */ +class UpdateTab : public QWidget { +Q_OBJECT + + QLabel *currentVersionLabel; + + QLabel *latestVersionLabel; + + QLabel *upgradeLabel; + + QProgressBar *pb; + + QString currentVersion; + +public: + explicit UpdateTab(QWidget *parent = nullptr); + + void getLatestVersion(); +}; + +/** * @brief Class for handling the about dialog * */ @@ -59,7 +82,7 @@ class AboutDialog : public QDialog { Q_OBJECT public: - explicit AboutDialog(QWidget *parent = nullptr); + explicit AboutDialog(int defaultIndex, QWidget *parent); }; #endif // __ABOUTDIALOG_H__ diff --git a/include/ui/help/VersionCheckThread.h b/include/ui/help/VersionCheckThread.h new file mode 100644 index 00000000..10c9da87 --- /dev/null +++ b/include/ui/help/VersionCheckThread.h @@ -0,0 +1,32 @@ +// +// Created by Administrator on 2021/7/12. +// + +#ifndef GPGFRONTEND_VERSIONCHECKTHREAD_H +#define GPGFRONTEND_VERSIONCHECKTHREAD_H + +#include "GpgFrontend.h" + +class VersionCheckThread : public QThread { +Q_OBJECT + +public: + + VersionCheckThread(QNetworkReply *networkReply); + +signals: + + void upgradeVersion(const QString ¤tVersion, const QString &latestVersion); + +protected: + + void run() override; + +private: + + QNetworkReply* mNetworkReply; + +}; + + +#endif //GPGFRONTEND_VERSIONCHECKTHREAD_H diff --git a/include/ui/keypair_details/KeyPairDetailTab.h b/include/ui/keypair_details/KeyPairDetailTab.h index 6d041f97..bb364718 100644 --- a/include/ui/keypair_details/KeyPairDetailTab.h +++ b/include/ui/keypair_details/KeyPairDetailTab.h @@ -36,10 +36,10 @@ class KeyPairDetailTab : public QWidget { Q_OBJECT /** - * @details Return QString with a space inserted at every fourth character - * - * @param fingerprint The fingerprint to be beautified - */ + * @details Return QString with a space inserted at every fourth character + * + * @param fingerprint The fingerprint to be beautified + */ static QString beautifyFingerprint(QString fingerprint); void createKeyServerOperaMenu(); @@ -64,6 +64,8 @@ private slots: void slotUpdateKeyToServer(); + void slotGenRevokeCert(); + private: QString *keyid; /** The id of the key the details should be shown for */ diff --git a/include/ui/widgets/Attachments.h b/include/ui/widgets/Attachments.h deleted file mode 100644 index 00433028..00000000 --- a/include/ui/widgets/Attachments.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#ifndef __ATTACHMENTS_H__ -#define __ATTACHMENTS_H__ - -#include "ui/AttachmentTableModel.h" - -class Attachments : public QWidget { -Q_OBJECT - -public slots: - - void slotSaveFile(); - - void slotOpenFile(); - -public: - explicit Attachments(QWidget *parent = nullptr); - - void addMimePart(MimePart *mp); - -private: - void createActions(); - - void saveByteArrayToFile(QByteArray outBuffer, QString filename); - - QAction *saveFileAct{}; - QAction *openFileAct{}; - AttachmentTableModel *table; - QTableView *tableView; - QSettings settings; - -protected: - void contextMenuEvent(QContextMenuEvent *event) override; -}; - -#endif // __ATTACHMENTS_H__ diff --git a/include/ui/widgets/FilePage.h b/include/ui/widgets/FilePage.h index 3d2c8e72..45d638fa 100644 --- a/include/ui/widgets/FilePage.h +++ b/include/ui/widgets/FilePage.h @@ -57,6 +57,10 @@ private slots: void onCustomContextMenu(const QPoint &point); +protected: + + void keyPressEvent(QKeyEvent *event) override; + private: @@ -64,6 +68,7 @@ private: QTreeView *dirTreeView; QLineEdit *pathEdit; QString mPath; + QString selectedPath; QPushButton *upLevelButton; QPushButton *goPathButton; diff --git a/include/ui/widgets/InfoBoardWidget.h b/include/ui/widgets/InfoBoardWidget.h index f487b72c..2e5f9034 100644 --- a/include/ui/widgets/InfoBoardWidget.h +++ b/include/ui/widgets/InfoBoardWidget.h @@ -95,6 +95,10 @@ public slots: void slotRefresh(const QString &text, InfoBoardStatus status); private: + + QString appPath; + QSettings settings; + QMenu *detailMenu; /** Menu for te Button in verfiyNotification */ QAction *importFromKeyserverAct; /** Action for importing keys from keyserver which are notin keylist */ QTextEdit *infoBoard; diff --git a/include/ui/widgets/KeyList.h b/include/ui/widgets/KeyList.h index 413d0969..231255b6 100644 --- a/include/ui/widgets/KeyList.h +++ b/include/ui/widgets/KeyList.h @@ -73,6 +73,8 @@ public: void addMenuAction(QAction *act); + void addSeparator(); + QStringList *getChecked(); void getCheckedKeys(QVector<GpgKey> &keys); diff --git a/resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml b/resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml new file mode 100644 index 00000000..49d409e5 --- /dev/null +++ b/resource/gpgfrontend/usr/share/metainfo/pub.gpgfrontend.gpgfrontend.metainfo.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2013 First Lastname <[email protected]> --> +<component type="desktop-application"> + <id>pub.gpgfrontend.gpgfrontend</id> + <metadata_license>FSFAP</metadata_license> + <project_license>GPL-3.0+</project_license> + <name>GpgFrontend</name> + <summary>Take the initiative to protect privacy in your own hands</summary> + + <description> + <p> + GpgFrontend is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool. + </p> + <p> + By using GpgFrontend, you can quickly encrypt and decrypt text or files. + Or at the same time as the above operations, you can add your own signature + to let others know that this document or this paragraph of text was issued by you. + </p> + <p>For moew information visit https://gpgfrontend.pub/</p> + + </description> + + <launchable type="desktop-id">gpgfrontend.desktop</launchable> + + <screenshots> + <screenshot type="default"> + <caption>Main Window</caption> + <image>https://raw.githubusercontent.com/saturneric/Blob/master/screenshots/keygen_ubuntu.png</image> + </screenshot> + </screenshots> + + <url type="homepage">https://gpgfrontend.pub/</url> + <project_group>GNOME</project_group> + <developer_name>Saturneric</developer_name> +</component>
\ No newline at end of file diff --git a/resource/icons/refresh.png b/resource/icons/refresh.png Binary files differnew file mode 100644 index 00000000..54745560 --- /dev/null +++ b/resource/icons/refresh.png diff --git a/resource/icons/up.png b/resource/icons/up.png Binary files differnew file mode 100644 index 00000000..46c47c70 --- /dev/null +++ b/resource/icons/up.png diff --git a/resource/ts/gpgfrontend_en_us.ts b/resource/ts/gpgfrontend_en_us.ts index c718def2..0042e061 100644 --- a/resource/ts/gpgfrontend_en_us.ts +++ b/resource/ts/gpgfrontend_en_us.ts @@ -4,30 +4,35 @@ <context> <name>AboutDialog</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="29"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/> <source>About </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="35"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/> <source>General</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="36"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/> <source>Translators</source> <translation type="unfinished"></translation> </message> + <message> + <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/> + <source>Update</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>AdvancedTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="580"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="679"/> <source>Show Steganography Options [Advanced]</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="582"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="681"/> <source>Show Steganographic Options.</source> <translation type="unfinished"></translation> </message> @@ -35,179 +40,159 @@ <context> <name>AppearanceTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="368"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="444"/> <source>Iconsize</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="370"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="446"/> <source>small</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="371"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="447"/> <source>medium</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="372"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="448"/> <source>large</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="388"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="464"/> <source>Iconstyle</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="390"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="466"/> <source>just text</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="391"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="467"/> <source>just icons</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="392"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="468"/> <source>text and icons</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="484"/> <source>Windowstate</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="411"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="487"/> <source>Save window size and position on exit.</source> <translation type="unfinished"></translation> </message> -</context> -<context> - <name>AttachmentTableModel</name> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> + <location filename="../../src/ui/SettingsDialog.cpp" line="495"/> + <source>Information Board</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> + <location filename="../../src/ui/SettingsDialog.cpp" line="501"/> + <source> Front Size</source> <translation type="unfinished"></translation> </message> </context> <context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> + <name>ChoosePage</name> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> + <location filename="../../src/ui/Wizard.cpp" line="165"/> + <source>Choose your action...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> + <location filename="../../src/ui/Wizard.cpp" line="166"/> + <source>...by clicking on the appropriate link.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> + <location filename="../../src/ui/Wizard.cpp" line="168"/> + <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> + <location filename="../../src/ui/Wizard.cpp" line="170"/> + <source>Generate Key</source> <translation type="unfinished"></translation> </message> -</context> -<context> - <name>ChoosePage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="161"/> - <source>Choose your action...</source> + <location filename="../../src/ui/Wizard.cpp" line="176"/> + <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="162"/> - <source>...by clicking on the appropriate link.</source> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <source>Encrypt & Decrypt Text</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="164"/> - <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>or</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="172"/> - <source>If you want to learn how to encrypt and decrypt text, you can read </source> + <location filename="../../src/ui/Wizard.cpp" line="180"/> + <source>Sign & Verify Text</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="174"/> - <location filename="../../src/ui/Wizard.cpp" line="183"/> - <source>this document</source> + <location filename="../../src/ui/Wizard.cpp" line="188"/> + <source>If you want to operate file, you can read </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="181"/> - <source>If you want to sign and verify text, you can read </source> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>Encrypt & Sign File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="166"/> - <source>create a new keypair</source> + <location filename="../../src/ui/Wizard.cpp" line="192"/> + <source>Sign & Verify File</source> <translation type="unfinished"></translation> </message> </context> <context> <name>ConclusionPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="397"/> + <location filename="../../src/ui/Wizard.cpp" line="407"/> <source>Ready.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="398"/> + <location filename="../../src/ui/Wizard.cpp" line="408"/> <source>Have fun with GPGFrontend!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="400"/> + <location filename="../../src/ui/Wizard.cpp" line="410"/> <source>You are ready to use GPGFrontend now.<br><br></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="402"/> + <location filename="../../src/ui/Wizard.cpp" line="412"/> <source>The Online Document</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="403"/> + <location filename="../../src/ui/Wizard.cpp" line="413"/> <source> will get you started with GPGFrontend. It will open in the main window.<br></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="410"/> + <location filename="../../src/ui/Wizard.cpp" line="420"/> <source>Open offline help.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="413"/> + <location filename="../../src/ui/Wizard.cpp" line="423"/> <source>Dont show the wizard again.</source> <translation type="unfinished"></translation> </message> @@ -267,23 +252,45 @@ </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> <source>Couldn't open file</source> <translation type="unfinished"></translation> </message> <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/> + <source>Error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/> + <source>Error Occurred During Encryption</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/> + <source>Error Occurred During Decryption</source> + <translation type="unfinished"></translation> + </message> + <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> + <source>Error Occurred During Signature</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/> <source>File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/> <source>File exists! Do you want to overwrite it?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/> <source>Cannot write file %1: %2.</source> <translation type="unfinished"></translation> @@ -292,52 +299,52 @@ <context> <name>FilePage</name> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/> <source>Open</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/> <source>Delete</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/> <source>Encrypt and Sign</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/> <source>Decrypt and Verify</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/> <source>Only Sign</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/> <source>Only Verify</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/> <source>Warning</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/> <source>Are you sure you want to delete it?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/> <source>Error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/> <source>Unable to delete the file or folder.</source> <translation type="unfinished"></translation> </message> @@ -353,57 +360,57 @@ <context> <name>GeneralTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="135"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="137"/> <source>Remember Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="138"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="140"/> <source>Remember password until closing gpg4usb</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="145"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="147"/> <source>Save Checked Keys</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="148"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="150"/> <source>Save checked private keys on exit and restore them on next start.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="157"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="159"/> <source>Confirm drag'n'drop key import</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="160"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="162"/> <source>Import files dropped on the keylist without confirmation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="167"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="169"/> <source>Language</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="176"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="178"/> <source><b>NOTE: </b> GpgFrontend will restart automatically if you change the language!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="185"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="187"/> <source>Own key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="193"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="195"/> <source><none></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="207"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="209"/> <source>Key pair for synchronization and identity authentication</source> <translation type="unfinished"></translation> </message> @@ -411,42 +418,32 @@ <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="90"/> - <source>ENV Loading Failed</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="91"/> - <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="577"/> + <location filename="../../src/gpg/GpgContext.cpp" line="528"/> <source>Wrong password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="585"/> + <location filename="../../src/gpg/GpgContext.cpp" line="536"/> <source>Enter Password for</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="589"/> + <location filename="../../src/gpg/GpgContext.cpp" line="540"/> <source>Enter Password</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>Key Selection</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>No Private Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="804"/> + <location filename="../../src/gpg/GpgContext.cpp" line="746"/> <source>Error in signing:</source> <translation type="unfinished"></translation> </message> @@ -454,22 +451,22 @@ <context> <name>GpgPathsTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="612"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="711"/> <source>Relative path to keydb</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="625"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="724"/> <source>Current keydb path: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="630"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="729"/> <source><b>NOTE: </b> Gpg4usb will restart automatically if you change the keydb path!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="659"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="758"/> <source>Choose keydb directory</source> <translation type="unfinished"></translation> </message> @@ -477,32 +474,32 @@ <context> <name>ImportFromGnupgPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="292"/> + <location filename="../../src/ui/Wizard.cpp" line="302"/> <source>Import keys...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="293"/> + <location filename="../../src/ui/Wizard.cpp" line="303"/> <source>...from existing GnuPG installation</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="295"/> + <location filename="../../src/ui/Wizard.cpp" line="305"/> <source>You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="299"/> + <location filename="../../src/ui/Wizard.cpp" line="309"/> <source>Import keys from GnuPG</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Import Error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Couldn't locate GnuPG home directory</source> <translation type="unfinished"></translation> </message> @@ -510,47 +507,47 @@ <context> <name>ImportFromGpg4usbPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="215"/> + <location filename="../../src/ui/Wizard.cpp" line="225"/> <source>Import from...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="216"/> + <location filename="../../src/ui/Wizard.cpp" line="226"/> <source>...existing GPGFrontend</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="218"/> + <location filename="../../src/ui/Wizard.cpp" line="228"/> <source>You can import keys and/or settings from existing GPGFrontend. <br><br>Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="225"/> + <location filename="../../src/ui/Wizard.cpp" line="235"/> <source>Keys</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="229"/> + <location filename="../../src/ui/Wizard.cpp" line="239"/> <source>Configuration</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="231"/> + <location filename="../../src/ui/Wizard.cpp" line="241"/> <source>Import from GPGFrontend</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="246"/> + <location filename="../../src/ui/Wizard.cpp" line="256"/> <source>Other GPGFrontend directory</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="265"/> + <location filename="../../src/ui/Wizard.cpp" line="275"/> <source>Configuration Imported</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="266"/> + <location filename="../../src/ui/Wizard.cpp" line="276"/> <source>Imported Configuration from old GPGFrontend.<br>Will now restart to activate the configuration.</source> <translation type="unfinished"></translation> </message> @@ -558,30 +555,35 @@ <context> <name>InfoBoardWidget</name> <message> - <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/> <source>Import missing key from Keyserver</source> <translation type="unfinished"></translation> </message> + <message> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/> + <source>Optional Actions Menu</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>InfoTab</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="55"/> - <source><br><center>GPGFrontend is an easy-to-use, compact, <br>cross-platform, and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/> + <source><br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="63"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/> <source><br><br> Built with Qt </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="64"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/> <source> and GPGME </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="65"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/> <source><br>Built at </source> <translation type="unfinished"></translation> </message> @@ -590,7 +592,7 @@ <name>IntroPage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="111"/> - <source>Getting started...</source> + <source>Getting Started...</source> <translation type="unfinished"></translation> </message> <message> @@ -600,11 +602,31 @@ </message> <message> <location filename="../../src/ui/Wizard.cpp" line="114"/> - <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br></source> + <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="116"/> + <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="117"/> + <source>For brief information have a look at the</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="118"/> + <source>Overview</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="123"/> + <location filename="../../src/ui/Wizard.cpp" line="119"/> + <source>by clicking the link, the page will open in the web browser</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="127"/> <source>Choose a Language</source> <translation type="unfinished"></translation> </message> @@ -652,17 +674,18 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/> - <source> Expiration time no more than 2 years. </source> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/> + <source> Expiration time no more than 2 years. +</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/> <source>Generating Key...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/> <source>Collecting random data for key generation. This may take a while. To speed up the process use your computer @@ -670,87 +693,92 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/> + <source>Key Usage</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/> <source>Encryption</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/> <source>Signing</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/> <source>Certification</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/> <source>Authentication</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>Success</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>The new key pair has been generated.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>Failure</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>An error occurred during key generation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/> <source>Name:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> <source>Email Address:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> <source>Comment:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> <source>Expiration Date:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> <source>Never Expire</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> <source>KeySize (in Bit):</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> <source>Key Type:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> <source>Non Pass Phrase</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/> <source>Basic Information</source> <translation type="unfinished"></translation> </message> @@ -758,27 +786,27 @@ <context> <name>KeyGenPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="356"/> + <location filename="../../src/ui/Wizard.cpp" line="366"/> <source>Create a keypair...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="357"/> + <location filename="../../src/ui/Wizard.cpp" line="367"/> <source>...for decrypting and signing messages</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="358"/> + <location filename="../../src/ui/Wizard.cpp" line="368"/> <source>You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window):</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="365"/> + <location filename="../../src/ui/Wizard.cpp" line="375"/> <source>Offline tutorial</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="372"/> + <location filename="../../src/ui/Wizard.cpp" line="382"/> <source>Create New Key</source> <translation type="unfinished"></translation> </message> @@ -941,23 +969,23 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> <source>Import Keys</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/> <source>You've dropped something on the table. GpgFrontend will now try to import key(s).</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/> <source>Always import without bothering.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/> <source>Couldn't Open File: </source> <translation type="unfinished"></translation> </message> @@ -966,7 +994,7 @@ <name>KeyMgmt</name> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="81"/> - <source>KeyPairs Management</source> + <source>Key Pair Management</source> <translation type="unfinished"></translation> </message> <message> @@ -1251,166 +1279,205 @@ <context> <name>KeyPairDetailTab</name> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> <source>Owner</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> <source>Master Key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/> <source>Fingerprint</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/> <source>Additional UIDs</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Exists</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Not Exists</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> <source>Name:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/> <source>Email Address:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/> <source>Comment:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> <source>Key ID: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> <source>Algorithm: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> <source>Key Size:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> <source>Nominal Usage: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> <source>Actual Usage: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> <source>Expires on: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/> <source>Last Update: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/> <source>Secret Key Existence: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> <source>Copy</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/> <source>copy fingerprint to clipboard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/> <source>Operations</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/> - <source>Export Private Key (Include Subkeys)</source> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/> + <source>Export Private Key (Include Subkey)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/> + <source>You are about to export your</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/> + <source>PRIVATE KEY</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/> + <source>This is NOT your Public Key, so DON'T give it away.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/> + <source>Do you REALLY want to export your PRIVATE KEY?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/> <source>Modify Expiration Datetime (Master Key)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/> <source>Key Server Operation (Pubkey)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/> - <source>Warning: The Master Key has expired.</source> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/> + <source>Generate Revoke Certificate</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/> - <source>Warning: The Master Key has been revoked</source> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/> + <source>Warning: The Master Key has expired.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/> - <source>Exporting private Key</source> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/> + <source>Warning: The Master Key has been revoked</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/> - <source><h3>You are about to export your <font color="red">PRIVATE KEY</font>!</h3> -This is NOT your Public Key, so DON'T give it away.<br />Do you REALLY want to export your PRIVATE KEY?</source> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/> + <source>Exporting private Key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/> <source>Export Key To File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/> <source>Key Files</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Export Error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Couldn't open %1 for writing</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/> <source>Never Expire</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/> - <source>Upload Key Pair</source> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/> + <source>Upload Key Pair to Key Server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/> <source>Update Key Pair</source> <translation type="unfinished"></translation> </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/> + <source>Generate revocation certificate</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/> + <source>Revocation Certificates</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>KeyPairSubkeyTab</name> @@ -1420,82 +1487,82 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> <source>Key ID: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> <source>Algorithm: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> <source>Key Size:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> <source>Usage: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> <source>Expires On </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> <source>Last Update: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> <source>Existence: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/> <source>Fingerprint: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Subkey ID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Key Size</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Algo</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Create Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Expire Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/> <source>Never Expire</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/> <source>Never Expires</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/> <source>Edit Expire Date</source> <translation type="unfinished"></translation> </message> @@ -1513,182 +1580,192 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/> + <source>UIDs</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/> + <source>Signature of Selected UID</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Select</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Name</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Email</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Comment</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Key ID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Create Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Expired Date</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/> <source>Never Expires</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/> <source>Invalid Operation</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/> <source>Please select one or more UIDs before doing this operation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/> <source>Sign Selected UID(s)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/> <source>Delete Selected UID(s)</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/> <source>Successful Operation</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> <source>Successfully added a new UID.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/> <source>Operation Failed</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/> <source>An error occurred during the operation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/> <source>Deleting UIDs</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/> <source>Are you sure that you want to delete the following uids?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/> <source>The action can not be undone.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/> <source>Set Primary UID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/> <source>Are you sure that you want to set the Primary UID to?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/> <source>Set As Primary</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/> <source>Sign UID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/> <source>Delete UID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/> <source>Please select one UID before doing this operation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/> <source>Deleting UID</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/> <source>Are you sure that you want to delete the following uid?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/> <source>Delete(Revoke) Key Signature</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/> <source>Please select one Key Signature before doing this operation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/> <source>To delete the signature, you need to have its corresponding public key in the local database.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/> <source>Deleting Key Signature</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/> <source>Are you sure that you want to delete the following signature?</source> <translation type="unfinished"></translation> </message> @@ -1752,50 +1829,50 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/> - <source><h4>Text is empty.</h4></source> + <source>Text is empty.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/> - <source>Not Key Found</source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> + <source>Too many responses from keyserver!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/> - <source>Timeout</source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> + <source>No keys found, input may be kexId, retrying search with 0x.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/> - <source>Key Server Not Found</source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> + <source>No keys found containing the search string!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/> - <source>Connection Error</source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> + <source>Insufficiently specific search string!</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> - <source><h4>CToo many responses from keyserver!</h4></source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/> + <source>Not Key Found</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> - <source><h4>No keys found, input may be kexId, retrying search with 0x.</h4></source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/> + <source>Timeout</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> - <source><h4>No keys found containing the search string!</h4></source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/> + <source>Key Server Not Found</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> - <source><h4>Insufficiently specific search string!</h4></source> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/> + <source>Connection Error</source> <translation type="unfinished"></translation> </message> <message> @@ -1893,27 +1970,27 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <context> <name>KeyUploadDialog</name> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/> <source>Uploading Public Key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/> <source>Key Not Found</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/> <source>Timeout</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/> <source>Key Server Not Found</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/> <source>Connection Error</source> <translation type="unfinished"></translation> </message> @@ -1921,12 +1998,12 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <context> <name>KeyserverTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="508"/> - <source>Default Keyserver for import:</source> + <location filename="../../src/ui/SettingsDialog.cpp" line="607"/> + <source>Default Key Server for import:</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="525"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="624"/> <source>Add</source> <translation type="unfinished"></translation> </message> @@ -1934,189 +2011,277 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <context> <name>MainWindow</name> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/> + <location filename="../../src/MainWindow.cpp" line="35"/> + <source>Loading Gnupg</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="62"/> + <source>ENV Loading Failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="63"/> + <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/> <source>No Key Selected</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/> <source>Invalid Operation</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/> <source>The selected key contains a key that does not actually have a encrypt usage.<br/></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/> + <source><br/>For example the Following Key: <br/></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/> + <source>Encrypting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/> + <source>Function Disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/> + <source>Please go to the settings interface to enable and configure this function.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/> <source>The selected key contains a key that does not actually have a signature usage.<br/></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/> + <source>Signing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/> + <source>Decrypting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/> + <source>Verifying</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/> <source>Invalid KeyPair</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/> <source>The selected keypair cannot be used for signing and encryption at the same time.<br/></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/> <source>Incomplete Operation</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/> <source>None of the selected key pairs can provide the encryption function.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/> <source>None of the selected key pairs can provide the signature function.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/> + <source>Encrypting and Signing</source> + <translation type="unfinished"></translation> + </message> + <message> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/> + <source>Decrypting and Verifying</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>Error</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <source>Select a file before doing it.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> <source>No permission to read this file.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> <source>No permission to create file.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/> <source>Warning</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/> <source>The target file already exists, do you need to overwrite it?</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>An error occurred during operation.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/> <source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> <source>No permission to read target file.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> <source>No permission to read signature file.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> <source>Select a file(.gpg/.asc) before doing it.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/> - <source><br/>For example the Following Key: <br/></source> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/> + <source>Outdated Version</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> - <source>Select a file before doing it.</source> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/> + <source>This version(%1) is out of date, please update the latest version in time. </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/> + <source>You can download the latest version(%1) on Github Releases Page.<br/></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/> + <source>Unreleased Version</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/> + <source>This version(%1) has not been officially released and is not recommended for use in a production environment. <br/></source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/> <source>There is one unencrypted file in attachment folder</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source>There are </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source> unencrypted files in attachment folder</source> <translation type="unfinished"></translation> </message> @@ -2422,7 +2587,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/> - <source>Manage &keys</source> + <source>Manage &Keys</source> <translation type="unfinished"></translation> </message> <message> @@ -2431,233 +2596,200 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/> <source>&About</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/> <source>Show the application's About box</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/> + <source>&Check for Updates</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <source>Check for updates</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/> <source>Open &Wizard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> <source>Open the wizard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> <source>Append Selected Key(s) To Text</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> <source>Append The Selected Keys To Text in Editor</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> - <source>Copy EMail-address</source> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <source>Copy Email</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/> - <source>Copy selected EMailaddress to clipboard</source> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <source>Copy selected Email to clipboard</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> <source>Show Key Details</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/> <source>Show Details for this Key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/> <source>Refresh Key From Key Server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/> <source>Refresh key from default key server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/> <source>Upload Public Key(s) To Server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/> <source>Upload The Selected Public Keys To Server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/> <source>Remove PGP Header</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/> <source>Add PGP Header</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/> <source>&File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/> <source>&Edit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/> <source>&File...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/> <source>&Crypt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> <source>&Keys</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/> <source>&Import Key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/> <source>&Steganography</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> <source>&View</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/> <source>&Help</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/> <source>File</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/> <source>Crypt</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/> <source>Key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/> <source>Edit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/> <source>Special Edit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/> <source>Import key from...</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/> <source>Import key</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/> <source>Browser to view and operate file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/> <source>Browser</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/> <source>Ready</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/> <source>Key ToolBox</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/> <source>Information Board</source> <translation type="unfinished"></translation> </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>MimeTab</name> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> - <source>Decode quoted printable</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="292"/> - <source>Try to recognize quoted printable.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="296"/> - <source>Parse PGP/MIME (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="299"/> - <source>Try to split attachments from PGP-MIME ecrypted messages.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="304"/> - <source>Open with external application (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="306"/> - <source>Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> - <source>Enable opening with external applications.</source> - <translation type="unfinished"></translation> - </message> </context> <context> <name>QApplication</name> @@ -2776,7 +2908,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="77"/> - <source><h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3></source> + <source>%1 files contain unsaved information.<br/>Save the changes before closing?</source> <translation type="unfinished"></translation> </message> <message> @@ -2791,39 +2923,172 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL </message> </context> <context> + <name>SendMailDialog</name> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="35"/> + <source>Incomplete configuration</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="36"/> + <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="86"/> + <source> Recipient cannot be empty +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="91"/> + <source> One or more Recipient's Email Address is invalid +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="97"/> + <source> Sender cannot be empty +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="99"/> + <source> Sender's Email Address is invalid +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <source>Fail to Connect SMTP Server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <source>Fail to Login into SMTP Server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail to Send Mail to SMTP Server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Success</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Succeed in Sending Mail to SMTP Server</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>SendMailTab</name> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> + <source>Enable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="311"/> + <source>SMTP Address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="313"/> + <source>Username</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> + <source>Password</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="317"/> + <source>Port</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="319"/> + <source>Connection Security</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="322"/> + <source>Default Sender</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <source>Fail to Connect SMTP Server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail to Login</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Success</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Succeed in connecting and login</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>SettingsDialog</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="38"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> <source>General</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="39"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> <source>Appearance</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> - <source>PGP/Mime</source> + <location filename="../../src/ui/SettingsDialog.cpp" line="42"/> + <source>Send Mail</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> <source>Key Server</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="45"/> <source>Advanced</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="56"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="58"/> <source>Settings</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="101"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="103"/> <source>System Default</source> <translation type="unfinished"></translation> </message> @@ -2922,63 +3187,97 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <context> <name>TextEdit</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/> <source>untitled</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/> <source>Warning</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/> + <source>Cannot read file %1: +%2.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/> <source>Open file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/> + <source>File</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/> + <source>Cannot write file %1: +%2.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> <source>Save file</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/> + <source>Unsaved document</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/> + <source>The document "%1" has been modified. Do you want to save your changes?<br/></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/> + <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/> <source>Application</source> <translation type="unfinished"></translation> </message> +</context> +<context> + <name>UpdateTab</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/> - <source>Cannot read file %1: -%2.</source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/> + <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/> - <source>File</source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/> + <source>New versions not only represent new features, but also often represent functional and security fixes.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/> - <source>Cannot write file %1: -%2.</source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/> + <source>Current Version: </source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/> - <source>Unsaved document</source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/> + <source>The current version is inconsistent with the latest version on github.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/> - <source><h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3></source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/> + <source>Please click <a href="https://github.com/saturneric/GpgFrontend/releases">here</a> to download the latest version.</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> - <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/> + <source>Latest Version From Github: </source> <translation type="unfinished"></translation> </message> </context> diff --git a/resource/ts/gpgfrontend_zh_cht.ts b/resource/ts/gpgfrontend_es.ts index 7bf4bd62..a3f8dd53 100644 --- a/resource/ts/gpgfrontend_zh_cht.ts +++ b/resource/ts/gpgfrontend_es.ts @@ -1,215 +1,198 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE TS> -<TS version="2.1" language="zh_CN"> +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="es_ES"> <context> <name>AboutDialog</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="29"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/> <source>About </source> - <translation type="unfinished"></translation> + <translation type="finished">Acerca de</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="35"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/> <source>General</source> - <translation type="unfinished"></translation> + <translation type="finished">General</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="36"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/> <source>Translators</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> + </message> + <message> + <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/> + <source>Update</source> + <translation type="finished">Actualizar</translation> </message> </context> <context> <name>AdvancedTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="580"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="679"/> <source>Show Steganography Options [Advanced]</source> - <translation type="unfinished"></translation> + <translation type="finished">Mostrar opciones de steganography [Avanzado]</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="582"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="681"/> <source>Show Steganographic Options.</source> - <translation type="unfinished"></translation> + <translation type="finished">Mostrar opciones de STANGANOGRÁFICA.</translation> </message> </context> <context> <name>AppearanceTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="368"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="444"/> <source>Iconsize</source> - <translation type="unfinished"></translation> + <translation type="finished">Tamaño de ícono.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="370"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="446"/> <source>small</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="371"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="447"/> <source>medium</source> - <translation type="unfinished"></translation> + <translation type="finished">medio</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="372"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="448"/> <source>large</source> - <translation type="unfinished"></translation> + <translation type="finished">grande</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="388"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="464"/> <source>Iconstyle</source> - <translation type="unfinished"></translation> + <translation type="finished">IconStyle</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="390"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="466"/> <source>just text</source> - <translation type="unfinished"></translation> + <translation type="finished">Solo texto</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="391"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="467"/> <source>just icons</source> - <translation type="unfinished"></translation> + <translation type="finished">solo iconos</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="392"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="468"/> <source>text and icons</source> - <translation type="unfinished"></translation> + <translation type="finished">Texto e Iconos</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="484"/> <source>Windowstate</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado de ventanas</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="411"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="487"/> <source>Save window size and position on exit.</source> - <translation type="unfinished"></translation> + <translation type="finished">Guardar el tamaño de la ventana y la posición en la salida.</translation> </message> -</context> -<context> - <name>AttachmentTableModel</name> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="495"/> + <source>Information Board</source> + <translation type="finished">Tarjeta de la información</translation> </message> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="501"/> + <source> Front Size</source> + <translation type="finished">Tamaño delantero</translation> </message> </context> <context> - <name>Attachments</name> + <name>ChoosePage</name> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="165"/> + <source>Choose your action...</source> + <translation type="finished">Elige tu acción ...</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="166"/> + <source>...by clicking on the appropriate link.</source> + <translation type="finished">... haciendo clic en el enlace apropiado.</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="168"/> + <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> + <translation type="finished">Si nunca ha usado GPGFRontend antes y tampoco tiene una clave GPG, pero posiblemente quiera leer cómo leer</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="170"/> + <source>Generate Key</source> + <translation type="finished">Generar clave</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="176"/> + <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source> + <translation type="finished">Si desea aprender cómo cifrar, descifrar, firmar y verificar el texto, puede leer</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <source>Encrypt & Decrypt Text</source> + <translation type="finished">Cifrar y descifrar texto</translation> </message> -</context> -<context> - <name>ChoosePage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="161"/> - <source>Choose your action...</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>or</source> + <translation type="finished">o</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="162"/> - <source>...by clicking on the appropriate link.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="180"/> + <source>Sign & Verify Text</source> + <translation type="finished">Firmar y verificar el texto</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="164"/> - <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="188"/> + <source>If you want to operate file, you can read </source> + <translation type="finished">Si desea operar el archivo, puede leer</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="172"/> - <source>If you want to learn how to encrypt and decrypt text, you can read </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>Encrypt & Sign File</source> + <translation type="finished">Cifrar y firmar archivo</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="174"/> - <location filename="../../src/ui/Wizard.cpp" line="183"/> - <source>this document</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/Wizard.cpp" line="181"/> - <source>If you want to sign and verify text, you can read </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/Wizard.cpp" line="166"/> - <source>create a new keypair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="192"/> + <source>Sign & Verify File</source> + <translation type="finished">Firmar y verificar el archivo</translation> </message> </context> <context> <name>ConclusionPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="397"/> + <location filename="../../src/ui/Wizard.cpp" line="407"/> <source>Ready.</source> - <translation type="unfinished"></translation> + <translation type="finished">Listo.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="398"/> + <location filename="../../src/ui/Wizard.cpp" line="408"/> <source>Have fun with GPGFrontend!</source> - <translation type="unfinished"></translation> + <translation type="finished">¡Diviértete con GPGFRontend!</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="400"/> + <location filename="../../src/ui/Wizard.cpp" line="410"/> <source>You are ready to use GPGFrontend now.<br><br></source> - <translation type="unfinished"></translation> + <translation type="finished">Estás listo para usar GPGFRontend ahora. <br> <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="402"/> + <location filename="../../src/ui/Wizard.cpp" line="412"/> <source>The Online Document</source> - <translation type="unfinished"></translation> + <translation type="finished">El documento en línea</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="403"/> + <location filename="../../src/ui/Wizard.cpp" line="413"/> <source> will get you started with GPGFrontend. It will open in the main window.<br></source> - <translation type="unfinished"></translation> + <translation type="finished">Te harás comenzar con GPGFRontend.Se abrirá en la ventana principal. <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="410"/> + <location filename="../../src/ui/Wizard.cpp" line="420"/> <source>Open offline help.</source> - <translation type="unfinished"></translation> + <translation type="finished">Ayuda fuera de línea abierta.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="413"/> + <location filename="../../src/ui/Wizard.cpp" line="423"/> <source>Dont show the wizard again.</source> - <translation type="unfinished"></translation> + <translation type="finished">No vuelvas a mostrar al asistente.</translation> </message> </context> <context> @@ -217,129 +200,152 @@ <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de descifrado</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation type="finished">Cifrar archivo</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de firma</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation type="finished">Verificar archivo</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/> <source>Input Parameters</source> - <translation type="unfinished"></translation> + <translation type="finished">Parámetros de entrada</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/> <source>Target File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de destino</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/> <source>Output File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de salida</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/> <source>Signature File(.sig) Path</source> - <translation type="unfinished"></translation> + <translation type="finished">Ruta del archivo de firma (.sig)</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/> <source>Open File</source> - <translation type="unfinished"></translation> + <translation type="finished">Abrir documento</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/> <source>Save File</source> - <translation type="unfinished"></translation> + <translation type="finished">Guardar el archivo</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/> - <source>Couldn't open file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> + <source>Couldn't open file</source> + <translation type="finished">No se pudo abrir el archivo</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/> + <source>Error</source> + <translation type="finished">Error</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/> + <source>Error Occurred During Encryption</source> + <translation type="finished">Se produjo un error durante el cifrado</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/> + <source>Error Occurred During Decryption</source> + <translation type="finished">Se produjo un error durante la descifrado.</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> + <source>Error Occurred During Signature</source> + <translation type="finished">Se produjo un error durante la firma</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/> <source>File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/> <source>File exists! Do you want to overwrite it?</source> - <translation type="unfinished"></translation> + <translation type="finished">¡El archivo existe! ¿Quieres sobreescribirlo?</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/> <source>Cannot write file %1: %2.</source> - <translation type="unfinished"></translation> + <translation type="finished">No se puede escribir archivo% 1: +% 2.</translation> </message> </context> <context> <name>FilePage</name> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/> <source>Open</source> - <translation type="unfinished"></translation> + <translation type="finished">Abierto</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/> <source>Delete</source> - <translation type="unfinished"></translation> + <translation type="finished">Borrar</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/> <source>Encrypt and Sign</source> - <translation type="unfinished"></translation> + <translation type="finished">Cifrar y firmar</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/> <source>Decrypt and Verify</source> - <translation type="unfinished"></translation> + <translation type="finished">Descifrar y verificar</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/> <source>Only Sign</source> - <translation type="unfinished"></translation> + <translation type="finished">Solo signo</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/> <source>Only Verify</source> - <translation type="unfinished"></translation> + <translation type="finished">Solo verificar</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation type="finished">Advertencia</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/> <source>Are you sure you want to delete it?</source> - <translation type="unfinished"></translation> + <translation type="finished">¿Estás seguro de que quieres borrarlo?</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/> <source>Unable to delete the file or folder.</source> - <translation type="unfinished"></translation> + <translation type="finished">No se puede eliminar el archivo o la carpeta.</translation> </message> </context> <context> @@ -347,266 +353,281 @@ <message> <location filename="../../src/ui/FindWidget.cpp" line="38"/> <source>Find:</source> - <translation type="unfinished"></translation> + <translation type="finished">Encontrar:</translation> </message> </context> <context> <name>GeneralTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="135"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="137"/> <source>Remember Password</source> - <translation type="unfinished"></translation> + <translation type="finished">Recordar contraseña</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="138"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="140"/> <source>Remember password until closing gpg4usb</source> - <translation type="unfinished"></translation> + <translation type="finished">Recuerde la contraseña hasta que cierre GPG4USB</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="145"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="147"/> <source>Save Checked Keys</source> - <translation type="unfinished"></translation> + <translation type="finished">Guardar las llaves revisadas</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="148"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="150"/> <source>Save checked private keys on exit and restore them on next start.</source> - <translation type="unfinished"></translation> + <translation type="finished">Guarda las llaves privadas revisadas en la salida y restaurándolas en el próximo inicio.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="157"/> - <source>Confirm drag'n'drop key import</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="159"/> + <source>Confirm drag'n'drop key import</source> + <translation type="finished">Confirmar la tecla Drag'n'n'Drop Import</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="160"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="162"/> <source>Import files dropped on the keylist without confirmation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar archivos cayeron en el keylist sin confirmación.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="167"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="169"/> <source>Language</source> - <translation type="unfinished"></translation> + <translation type="finished">Idioma</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="176"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="178"/> <source><b>NOTE: </b> GpgFrontend will restart automatically if you change the language!</source> - <translation type="unfinished"></translation> + <translation type="finished"><B> Nota: </ b> GPGFRontend se reiniciará automáticamente si cambia el idioma!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="185"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="187"/> <source>Own key</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="193"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="195"/> <source><none></source> - <translation type="unfinished"></translation> + <translation type="finished"><ninguno></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="207"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="209"/> <source>Key pair for synchronization and identity authentication</source> - <translation type="unfinished"></translation> + <translation type="finished">Pareja de llaves para la autenticación de sincronización e identidad</translation> </message> </context> <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="90"/> - <source>ENV Loading Failed</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="91"/> - <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="577"/> + <location filename="../../src/gpg/GpgContext.cpp" line="528"/> <source>Wrong password</source> - <translation type="unfinished"></translation> + <translation type="finished">Contraseña incorrecta</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="585"/> + <location filename="../../src/gpg/GpgContext.cpp" line="536"/> <source>Enter Password for</source> - <translation type="unfinished"></translation> + <translation type="finished">Ingrese la contraseña para</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="589"/> + <location filename="../../src/gpg/GpgContext.cpp" line="540"/> <source>Enter Password</source> - <translation type="unfinished"></translation> + <translation type="finished">Introducir la contraseña</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>Key Selection</source> - <translation type="unfinished"></translation> + <translation type="finished">Selección de claves</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>No Private Key Selected</source> - <translation type="unfinished"></translation> + <translation type="finished">No hay llave privada seleccionada</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="804"/> + <location filename="../../src/gpg/GpgContext.cpp" line="746"/> <source>Error in signing:</source> - <translation type="unfinished"></translation> + <translation type="finished">Error en la firma:</translation> </message> </context> <context> <name>GpgPathsTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="612"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="711"/> <source>Relative path to keydb</source> - <translation type="unfinished"></translation> + <translation type="finished">Camino relativo a KeyDB</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="625"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="724"/> <source>Current keydb path: </source> - <translation type="unfinished"></translation> + <translation type="finished">Ruta de KeyDB actual:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="630"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="729"/> <source><b>NOTE: </b> Gpg4usb will restart automatically if you change the keydb path!</source> - <translation type="unfinished"></translation> + <translation type="finished"><B> Nota: </ b> gpg4usb se reiniciará automáticamente si cambia la ruta KeyDB!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="659"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="758"/> <source>Choose keydb directory</source> - <translation type="unfinished"></translation> + <translation type="finished">Elija el directorio de KeyDB</translation> </message> </context> <context> <name>ImportFromGnupgPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="292"/> + <location filename="../../src/ui/Wizard.cpp" line="302"/> <source>Import keys...</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar teclas ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="293"/> + <location filename="../../src/ui/Wizard.cpp" line="303"/> <source>...from existing GnuPG installation</source> - <translation type="unfinished"></translation> + <translation type="finished">... de la instalación de GNUPG existente</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="295"/> + <location filename="../../src/ui/Wizard.cpp" line="305"/> <source>You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br></source> - <translation type="unfinished"></translation> + <translation type="finished">Puede importar claves desde un GNUPG instalado localmente. <br> <br> La ubicación se lee desde el registro en Windows o se supone que es la carpeta .GNUPG en el directorio de su casa en Linux. <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="299"/> + <location filename="../../src/ui/Wizard.cpp" line="309"/> <source>Import keys from GnuPG</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar claves de gnupg</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error de importación</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> - <source>Couldn't locate GnuPG home directory</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="323"/> + <source>Couldn't locate GnuPG home directory</source> + <translation type="finished">No se pudo localizar el directorio de inicio de gnupg</translation> </message> </context> <context> <name>ImportFromGpg4usbPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="215"/> + <location filename="../../src/ui/Wizard.cpp" line="225"/> <source>Import from...</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar de...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="216"/> + <location filename="../../src/ui/Wizard.cpp" line="226"/> <source>...existing GPGFrontend</source> - <translation type="unfinished"></translation> + <translation type="finished">... gpgfrontend existente</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="218"/> + <location filename="../../src/ui/Wizard.cpp" line="228"/> <source>You can import keys and/or settings from existing GPGFrontend. <br><br>Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source> - <translation type="unfinished"></translation> + <translation type="finished">Puede importar claves y / o configuraciones desde GPGFrontend existente.<br> <br> Simplemente compruebe lo que desea importar, haga clic en el botón Importar y elija el directorio de su otro GPGFrontend en el cuadro de diálogo de archivo de apariencia.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="225"/> + <location filename="../../src/ui/Wizard.cpp" line="235"/> <source>Keys</source> - <translation type="unfinished"></translation> + <translation type="finished">Llaves</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="229"/> + <location filename="../../src/ui/Wizard.cpp" line="239"/> <source>Configuration</source> - <translation type="unfinished"></translation> + <translation type="finished">Configuración</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="231"/> + <location filename="../../src/ui/Wizard.cpp" line="241"/> <source>Import from GPGFrontend</source> - <translation type="unfinished"></translation> + <translation type="finished">Importación de GPGFRontend</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="246"/> + <location filename="../../src/ui/Wizard.cpp" line="256"/> <source>Other GPGFrontend directory</source> - <translation type="unfinished"></translation> + <translation type="finished">Otro GPGFrontend Directorio</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="265"/> + <location filename="../../src/ui/Wizard.cpp" line="275"/> <source>Configuration Imported</source> - <translation type="unfinished"></translation> + <translation type="finished">Configuración importada</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="266"/> + <location filename="../../src/ui/Wizard.cpp" line="276"/> <source>Imported Configuration from old GPGFrontend.<br>Will now restart to activate the configuration.</source> - <translation type="unfinished"></translation> + <translation type="finished">Configuración importada desde el antiguo GPGFrontend. Se reiniciará ahora para activar la configuración.</translation> </message> </context> <context> <name>InfoBoardWidget</name> <message> - <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/> <source>Import missing key from Keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar la tecla faltante de Keyserver</translation> + </message> + <message> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/> + <source>Optional Actions Menu</source> + <translation type="finished">MENÚ DE ACCIONES OPCIONALES</translation> </message> </context> <context> <name>InfoTab</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="55"/> - <source><br><center>GPGFrontend is an easy-to-use, compact, <br>cross-platform, and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/> + <source><br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> + <translation type="finished"><br> <Centre> GPGFRontend es una herramienta de front-end de GPG de fácil uso, compacta, compacta, compacta y sin instalación. <br> Se visualiza la mayoría de las operaciones comunes de los comandos GPG. <BR> Está licenciado bajo el GPL V3 <br> <br> <B> Desarrollador: </ b> <br> Saturnérico <br> <br> Si tiene alguna pregunta o sugerencia, plantee un problema <br/> a <Ahref = "https://github.com/saturnic/gpgfrontend"> github </a> o envíe un correo a mi lista de correo en <a href="mailto [email protected]"> [email protected] </ a>.</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="63"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/> <source><br><br> Built with Qt </source> - <translation type="unfinished"></translation> + <translation type="finished"><br> <br> construido con qt</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="64"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/> <source> and GPGME </source> - <translation type="unfinished"></translation> + <translation type="finished">y gpgme</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="65"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/> <source><br>Built at </source> - <translation type="unfinished"></translation> + <translation type="finished"><br> construido en</translation> </message> </context> <context> <name>IntroPage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="111"/> - <source>Getting started...</source> - <translation type="unfinished"></translation> + <source>Getting Started...</source> + <translation type="finished">Empezando...</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="112"/> <source>... with GPGFrontend</source> - <translation type="unfinished"></translation> + <translation type="finished">... con gpgfrontend</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="114"/> - <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br></source> - <translation type="unfinished"></translation> + <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source> + <translation type="finished">¡Bienvenido a usar GPGFRontend para descifrar y firmar texto o archivo!</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="123"/> + <location filename="../../src/ui/Wizard.cpp" line="116"/> + <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source> + <translation type="finished">Es una herramienta CRYPTO OpenPGP Potente, fácil de usar, compacta, multiplataforma y sin instalación.</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="117"/> + <source>For brief information have a look at the</source> + <translation type="finished">Para obtener información breve, eche un vistazo a la</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="118"/> + <source>Overview</source> + <translation type="finished">Descripción general</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="119"/> + <source>by clicking the link, the page will open in the web browser</source> + <translation type="finished">Al hacer clic en el enlace, la página se abrirá en el navegador web.</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="127"/> <source>Choose a Language</source> - <translation type="unfinished"></translation> + <translation type="finished">Elegir un idioma</translation> </message> </context> <context> @@ -614,22 +635,22 @@ <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/> <source>KeyPair</source> - <translation type="unfinished"></translation> + <translation type="finished">Par de claves</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/> <source>UIDs</source> - <translation type="unfinished"></translation> + <translation type="finished">Uids</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/> <source>Subkeys</source> - <translation type="unfinished"></translation> + <translation type="finished">Subcecheras</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/> <source>Key Details</source> - <translation type="unfinished"></translation> + <translation type="finished">Detalles clave</translation> </message> </context> <context> @@ -637,150 +658,159 @@ <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/> <source>Generate Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar clave</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation type="finished">El nombre debe contener al menos cinco caracteres.</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation type="finished">Por favor, proporcione una dirección de correo electrónico.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/> - <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/> + <source> Expiration time no more than 2 years. +</source> + <translation type="finished">Tiempo de vencimiento No más de 2 años.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/> <source>Generating Key...</source> - <translation type="unfinished"></translation> + <translation type="finished">Generando llave ...</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/> <source>Collecting random data for key generation. This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation type="finished">Recogiendo datos aleatorios para la generación de claves. + Esto puede tardar un rato. + Para acelerar el proceso, use su computadora. + (Por ejemplo, navega por la red, escucha música, ...)</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/> + <source>Key Usage</source> + <translation type="finished">Uso clave</translation> + </message> + <message> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation type="finished">Firma</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation type="finished">Certificación</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation type="finished">Autenticación</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation type="finished">Éxito</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>The new key pair has been generated.</source> - <translation type="unfinished"></translation> + <translation type="finished">Se ha generado el nuevo par de llaves.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation type="finished">Falla</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>An error occurred during key generation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Se produjo un error durante la generación de claves.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation type="finished">Dirección de correo electrónico:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation type="finished">Comentario:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de caducidad:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation type="finished">Keysize (en bit):</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation type="finished">Tipo de llave:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> <source>Non Pass Phrase</source> - <translation type="unfinished"></translation> + <translation type="finished">Frase sin paso</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation type="finished">Información básica</translation> </message> </context> <context> <name>KeyGenPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="356"/> + <location filename="../../src/ui/Wizard.cpp" line="366"/> <source>Create a keypair...</source> - <translation type="unfinished"></translation> + <translation type="finished">Crea un keypair ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="357"/> + <location filename="../../src/ui/Wizard.cpp" line="367"/> <source>...for decrypting and signing messages</source> - <translation type="unfinished"></translation> + <translation type="finished">... para descifrar y firmar mensajes</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="358"/> + <location filename="../../src/ui/Wizard.cpp" line="368"/> <source>You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window):</source> - <translation type="unfinished"></translation> + <translation type="finished">Debe crear un nuevo teclado. El par consiste en una clave pública y privada. Otros usuarios pueden usar la clave pública para cifrar mensajes para usted y verificar los mensajes firmados por usted. Puede usar la clave privada para descifrar y firmarMensajes. Para más información, eche un vistazo al tutorial fuera de línea (que luego se muestra en la ventana principal):</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="365"/> + <location filename="../../src/ui/Wizard.cpp" line="375"/> <source>Offline tutorial</source> - <translation type="unfinished"></translation> + <translation type="finished">Tutorial fuera de línea</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="372"/> + <location filename="../../src/ui/Wizard.cpp" line="382"/> <source>Create New Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Crear nueva llave</translation> </message> </context> <context> @@ -789,118 +819,118 @@ <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/> <source>Key Update Details</source> - <translation type="unfinished"></translation> + <translation type="finished">Detalles de actualización clave</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <source>No keys found</source> - <translation type="unfinished"></translation> + <translation type="finished">No se han encontrado llaves</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/> <source>Key Import Details</source> - <translation type="unfinished"></translation> + <translation type="finished">Detalles de importación clave</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <source>No keys found to import</source> - <translation type="unfinished"></translation> + <translation type="finished">No se han encontrado llaves para importar</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/> <source>General key info</source> - <translation type="unfinished"></translation> + <translation type="finished">Información general de clave</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/> <source>Considered:</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/> <source>Public unchanged:</source> - <translation type="unfinished"></translation> + <translation type="finished">Público sin cambios:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/> <source>Imported:</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/> <source>Not imported:</source> - <translation type="unfinished"></translation> + <translation type="finished">No importado:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/> <source>Private read:</source> - <translation type="unfinished"></translation> + <translation type="finished">LEER PRIVADO:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/> <source>Private imported:</source> - <translation type="unfinished"></translation> + <translation type="finished">Importado privado:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/> <source>Private unchanged:</source> - <translation type="unfinished"></translation> + <translation type="finished">Privado sin cambios:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation type="finished">Correo electrónico</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Status</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation type="finished">Huella dactilar</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/> <source>private</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="138"/> <source>public</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="141"/> <source>unchanged</source> - <translation type="unfinished"></translation> + <translation type="finished">sin alterar</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/> <source>new key</source> - <translation type="unfinished"></translation> + <translation type="finished">nueva llave</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/> <source>new subkey</source> - <translation type="unfinished"></translation> + <translation type="finished">Nueva Subkey</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/> <source>new signature</source> - <translation type="unfinished"></translation> + <translation type="finished">nueva firma</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/> <source>new uid</source> - <translation type="unfinished"></translation> + <translation type="finished">Nuevo uid</translation> </message> </context> <context> @@ -908,309 +938,310 @@ <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccione</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Type</source> - <translation type="unfinished"></translation> + <translation type="finished">Tipo</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Email Address</source> - <translation type="unfinished"></translation> + <translation type="finished">Dirección de correo electrónico</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Usage</source> - <translation type="unfinished"></translation> + <translation type="finished">Uso</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Validity</source> - <translation type="unfinished"></translation> + <translation type="finished">Validez</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Finger Print</source> - <translation type="unfinished"></translation> + <translation type="finished">Huella dactilar</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> <source>Import Keys</source> - <translation type="unfinished"></translation> + <translation type="finished">Teclas de importación</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/> - <source>You've dropped something on the table. + <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/> + <source>You've dropped something on the table. GpgFrontend will now try to import key(s).</source> - <translation type="unfinished"></translation> + <translation type="finished">Has dejado caer algo sobre la mesa. + GPGFRontend ahora intentará importar la (s) clave (s).</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/> <source>Always import without bothering.</source> - <translation type="unfinished"></translation> + <translation type="finished">Siempre importar sin molestarse.</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/> - <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/> + <source>Couldn't Open File: </source> + <translation type="finished">No se pudo abrir el archivo:</translation> </message> </context> <context> <name>KeyMgmt</name> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="81"/> - <source>KeyPairs Management</source> - <translation type="unfinished"></translation> + <source>Key Pair Management</source> + <translation type="finished">Gestión de pares clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="88"/> <source>&Open</source> - <translation type="unfinished"></translation> + <translation type="finished">&Abierto</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="89"/> <source>Ctrl+O</source> - <translation type="unfinished"></translation> + <translation type="finished">Ctrl + o</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="90"/> <source>Open Key File</source> - <translation type="unfinished"></translation> + <translation type="finished">Abrir archivo de clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="93"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation type="finished">&Cerca</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="94"/> <source>Ctrl+Q</source> - <translation type="unfinished"></translation> + <translation type="finished">Ctrl + Q</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="96"/> <source>Close</source> - <translation type="unfinished"></translation> + <translation type="finished">Cerca</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="99"/> <source>New Keypair</source> - <translation type="unfinished"></translation> + <translation type="finished">Nuevo llave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="100"/> <source>Ctrl+N</source> - <translation type="unfinished"></translation> + <translation type="finished">Ctrl + n</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="102"/> <source>Generate KeyPair</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar par de claves</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="105"/> <source>New Subkey</source> - <translation type="unfinished"></translation> + <translation type="finished">Nueva Subkey</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="106"/> <source>Ctrl+Shift+N</source> - <translation type="unfinished"></translation> + <translation type="finished">CTRL + MAYÚS + N</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="108"/> <source>Generate Subkey For Selected KeyPair</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar subclave para la tecla seleccionada.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="111"/> <location filename="../../src/ui/KeyMgmt.cpp" line="152"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation type="finished">&Archivo</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="113"/> <source>Import New Key From File</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar nueva llave desde el archivo</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="116"/> <source>&Clipboard</source> - <translation type="unfinished"></translation> + <translation type="finished">&Portapapeles</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="118"/> <source>Import New Key From Clipboard</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar nueva llave desde el portapapeles</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="121"/> <source>&Keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">& Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="123"/> <source>Import New Key From Keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar nueva llave de Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="126"/> <source>Export To &Clipboard</source> - <translation type="unfinished"></translation> + <translation type="finished">Exportar al portapapeles</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="128"/> <source>Export Selected Key(s) To Clipboard</source> - <translation type="unfinished"></translation> + <translation type="finished">Exportar la (s) clave (s) seleccionada (s) al portapapeles</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="131"/> <source>Export To &File</source> - <translation type="unfinished"></translation> + <translation type="finished">Exportar a & Archivo</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="133"/> <source>Export Selected Key(s) To File</source> - <translation type="unfinished"></translation> + <translation type="finished">Exportar clave seleccionada (s) para archivar</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="136"/> <source>Delete Selected Key(s)</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar la (s) clave seleccionada (s)</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="137"/> <source>Delete the Selected keys</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar las teclas seleccionadas</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="140"/> <source>Delete Checked Key(s)</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar la (s) clave de verificación (s)</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="141"/> <source>Delete the Checked keys</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar las teclas marcadas</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="145"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation type="finished">Mostrar detalles clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="146"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Mostrar detalles para esta clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="156"/> <source>&Key</source> - <translation type="unfinished"></translation> + <translation type="finished">&Clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="157"/> <source>&Generate Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="161"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation type="finished">E importar clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="173"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="181"/> <source>Generate</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="182"/> <source>Generate A New Keypair or Subkey</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar un nuevo teclado o suba.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="191"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation type="finished">Tecla de importación</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="192"/> <source>Import Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Tecla de importación</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Open Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Llave abierta</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivos clave</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Keyring files</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivos de llavero</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="218"/> - <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <source>Couldn't Open File: </source> + <translation type="finished">No se pudo abrir el archivo:</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="268"/> <source>Deleting Keys</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar llaves</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="269"/> <source>Are you sure that you want to delete the following keys?</source> - <translation type="unfinished"></translation> + <translation type="finished">¿Está seguro de que desea eliminar las siguientes teclas?</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="270"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation type="finished">La acción no se puede deshacer.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave de exportación a archivo</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="309"/> <source>key(s) exported</source> - <translation type="unfinished"></translation> + <translation type="finished">llave (s) exportada</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="338"/> <location filename="../../src/ui/KeyMgmt.cpp" line="345"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación inválida</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="339"/> <source>Please select one KeyPair before doing this operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Por favor seleccione una tecla antes de hacer esta operación.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="346"/> <source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source> - <translation type="unfinished"></translation> + <translation type="finished">Si un par de claves no tiene una clave privada, no podrá generar sub-llaves.</translation> </message> </context> <context> @@ -1218,198 +1249,237 @@ <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation type="finished">Correo electrónico</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation type="finished">Comentario</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/> <source>Create New UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Crear nuevo uid</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation type="finished">El nombre debe contener al menos cinco caracteres.</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation type="finished">Por favor, proporcione una dirección de correo electrónico.</translation> </message> </context> <context> <name>KeyPairDetailTab</name> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> <source>Owner</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> <source>Master Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Llave maestra</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation type="finished">Huella dactilar</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/> <source>Additional UIDs</source> - <translation type="unfinished"></translation> + <translation type="finished">UIDS adicionales</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Exists</source> + <translation type="finished">Existe</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Not Exists</source> + <translation type="finished">No existe</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation type="finished">Dirección de correo electrónico:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation type="finished">Comentario:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation type="finished">ID clave:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation type="finished">Algoritmo:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation type="finished">Tamaño de la llave:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> <source>Nominal Usage: </source> - <translation type="unfinished"></translation> + <translation type="finished">Uso nominal:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> <source>Actual Usage: </source> - <translation type="unfinished"></translation> + <translation type="finished">Uso actual:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> <source>Expires on: </source> - <translation type="unfinished"></translation> + <translation type="finished">Expira el:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation type="finished">Última actualización:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/> <source>Secret Key Existence: </source> - <translation type="unfinished"></translation> + <translation type="finished">Existencia clave secreta:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> <source>Copy</source> - <translation type="unfinished"></translation> + <translation type="finished">Dupdo</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/> <source>copy fingerprint to clipboard</source> - <translation type="unfinished"></translation> + <translation type="finished">Copia la huella digital al portapapeles</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/> <source>Operations</source> - <translation type="unfinished"></translation> + <translation type="finished">Operaciones</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/> - <source>Export Private Key (Include Subkeys)</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/> + <source>Export Private Key (Include Subkey)</source> + <translation type="finished">Clave privada de exportación (incluir subclave)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/> <source>Modify Expiration Datetime (Master Key)</source> - <translation type="unfinished"></translation> + <translation type="finished">Modificar fecha de vencimiento (clave maestra)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/> <source>Key Server Operation (Pubkey)</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación del servidor clave (Pubkey)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/> + <source>Generate Revoke Certificate</source> + <translation type="finished">Genera revocar certificado</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/> <source>Warning: The Master Key has expired.</source> - <translation type="unfinished"></translation> + <translation type="finished">Advertencia: la clave maestra ha caducado.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/> <source>Warning: The Master Key has been revoked</source> - <translation type="unfinished"></translation> + <translation type="finished">Advertencia: la clave maestra ha sido revocada</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/> <source>Exporting private Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Exportación de clave privada</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/> + <source>You are about to export your</source> + <translation type="finished">Estás a punto de exportar tu</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/> + <source>PRIVATE KEY</source> + <translation type="finished">LLAVE PRIVADA</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/> + <source>This is NOT your Public Key, so DON'T give it away.</source> + <translation type="finished">Esta no es su clave pública, así que no lo desye.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/> - <source><h3>You are about to export your <font color="red">PRIVATE KEY</font>!</h3> -This is NOT your Public Key, so DON'T give it away.<br />Do you REALLY want to export your PRIVATE KEY?</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/> + <source>Do you REALLY want to export your PRIVATE KEY?</source> + <translation type="finished">¿Realmente quieres exportar tu clave privada?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave de exportación a archivo</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivos clave</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Export Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error de exportación</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> - <source>Couldn't open %1 for writing</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> + <source>Couldn't open %1 for writing</source> + <translation type="finished">No se pudo abrir% 1 por escrito.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/> - <source>Upload Key Pair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/> + <source>Upload Key Pair to Key Server</source> + <translation type="finished">Cargar un par de claves para clave del servidor</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/> <source>Update Key Pair</source> - <translation type="unfinished"></translation> + <translation type="finished">Actualizar par de claves</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/> + <source>Generate revocation certificate</source> + <translation type="finished">Generar certificado de revocación</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/> + <source>Revocation Certificates</source> + <translation type="finished">Certificados de revocación</translation> </message> </context> <context> @@ -1417,87 +1487,87 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/> <source>Generate A New Subkey</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar una nueva subclave</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation type="finished">ID clave:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation type="finished">Algoritmo:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation type="finished">Tamaño de la llave:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> <source>Usage: </source> - <translation type="unfinished"></translation> + <translation type="finished">Uso:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> <source>Expires On </source> - <translation type="unfinished"></translation> + <translation type="finished">Expira el</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation type="finished">Última actualización:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> <source>Existence: </source> - <translation type="unfinished"></translation> + <translation type="finished">Existencia:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation type="finished">Huella dactilar:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Subkey ID</source> - <translation type="unfinished"></translation> + <translation type="finished">ID de suba</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Key Size</source> - <translation type="unfinished"></translation> + <translation type="finished">Tamaño de la llave</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Algo</source> - <translation type="unfinished"></translation> + <translation type="finished">Algo</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de Creación</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de caducidad</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/> <source>Edit Expire Date</source> - <translation type="unfinished"></translation> + <translation type="finished">Editar fecha de vencimiento</translation> </message> </context> <context> @@ -1505,192 +1575,202 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/> <source>New UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Nuevo uid</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/> <source>UID Management</source> - <translation type="unfinished"></translation> + <translation type="finished">Gestión UID</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/> + <source>UIDs</source> + <translation type="finished">Uids</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/> + <source>Signature of Selected UID</source> + <translation type="finished">Firma de UID seleccionado</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccione</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation type="finished">Correo electrónico</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation type="finished">Comentario</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Key ID</source> - <translation type="unfinished"></translation> + <translation type="finished">ID clave</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de Creación</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Expired Date</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de vencimiento</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación inválida</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/> <source>Please select one or more UIDs before doing this operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccione uno o más UID antes de hacer esta operación.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/> <source>Sign Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation type="finished">Signo de uid seleccionado (s)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/> <source>Delete Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar UID seleccionado (s)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/> <source>Successful Operation</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación exitosa</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> <source>Successfully added a new UID.</source> - <translation type="unfinished"></translation> + <translation type="finished">Agregó con éxito un nuevo UID.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación fallida</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Se produjo un error durante la operación.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/> <source>Deleting UIDs</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar UIDS</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/> <source>Are you sure that you want to delete the following uids?</source> - <translation type="unfinished"></translation> + <translation type="finished">¿Está seguro de que desea eliminar los siguientes uids?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation type="finished">La acción no se puede deshacer.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/> <source>Set Primary UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Establecer uid primario</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/> <source>Are you sure that you want to set the Primary UID to?</source> - <translation type="unfinished"></translation> + <translation type="finished">¿Está seguro de que desea configurar el UID primario para?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/> <source>Set As Primary</source> - <translation type="unfinished"></translation> + <translation type="finished">Establecer como primario</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/> <source>Sign UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Muestra uid</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/> <source>Delete UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar uid</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/> <source>Please select one UID before doing this operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Por favor, seleccione una UID antes de hacer esta operación.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/> <source>Deleting UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar uid</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/> <source>Are you sure that you want to delete the following uid?</source> - <translation type="unfinished"></translation> + <translation type="finished">¿Está seguro de que desea eliminar el siguiente UID?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/> <source>Delete(Revoke) Key Signature</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar (revocar) Firma clave</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/> <source>Please select one Key Signature before doing this operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccione una firma clave antes de hacer esta operación.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/> <source>To delete the signature, you need to have its corresponding public key in the local database.</source> - <translation type="unfinished"></translation> + <translation type="finished">Para eliminar la firma, debe tener su clave pública correspondiente en la base de datos local.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/> <source>Deleting Key Signature</source> - <translation type="unfinished"></translation> + <translation type="finished">Eliminar la firma clave</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/> <source>Are you sure that you want to delete the following signature?</source> - <translation type="unfinished"></translation> + <translation type="finished">¿Está seguro de que desea eliminar la siguiente firma?</translation> </message> </context> <context> @@ -1698,140 +1778,140 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation type="finished">&Cerca</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/> <source>&Import ALL</source> - <translation type="unfinished"></translation> + <translation type="finished">E importar todos</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/> <source>&Search</source> - <translation type="unfinished"></translation> + <translation type="finished">&Buscar</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/> <source>Search String:</source> - <translation type="unfinished"></translation> + <translation type="finished">Cadena de búsqueda:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/> <source>Key Server:</source> - <translation type="unfinished"></translation> + <translation type="finished">Servidor de teclas:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/> <source>Update Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">Actualizar las teclas de Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/> <source>Import Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar claves de Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>UID</source> - <translation type="unfinished"></translation> + <translation type="finished">Uid</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Creation date</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de creación</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>KeyID</source> - <translation type="unfinished"></translation> + <translation type="finished">Keyid</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Tag</source> - <translation type="unfinished"></translation> + <translation type="finished">Etiqueta</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/> - <source><h4>Text is empty.</h4></source> - <translation type="unfinished"></translation> + <source>Text is empty.</source> + <translation type="finished">El texto está vacío.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/> <source>Not Key Found</source> - <translation type="unfinished"></translation> + <translation type="finished">No se encuentra clave</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation type="finished">Se acabó el tiempo</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation type="finished">Servidor de teclas no encontrado</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error de conexión</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> - <source><h4>CToo many responses from keyserver!</h4></source> - <translation type="unfinished"></translation> + <source>Too many responses from keyserver!</source> + <translation type="finished">Demasiadas respuestas de Keyserver!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> - <source><h4>No keys found, input may be kexId, retrying search with 0x.</h4></source> - <translation type="unfinished"></translation> + <source>No keys found, input may be kexId, retrying search with 0x.</source> + <translation type="finished">No se han encontrado llaves, la entrada puede ser kexid, volviendo a intentar la búsqueda con 0x.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> - <source><h4>No keys found containing the search string!</h4></source> - <translation type="unfinished"></translation> + <source>No keys found containing the search string!</source> + <translation type="finished">¡No se han encontrado llaves que contengan la cadena de búsqueda!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> - <source><h4>Insufficiently specific search string!</h4></source> - <translation type="unfinished"></translation> + <source>Insufficiently specific search string!</source> + <translation type="finished">Insuficientemente específica de la cadena de búsqueda!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/> <source>revoked</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/> <source>disabled</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/> <source><h4>%1 keys found. Double click a key to import it.</h4></source> - <translation type="unfinished"></translation> + <translation type="finished"><h4>% 1 llaves encontradas.Haga doble clic en una tecla para importarlo. </ H4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave no encontrada</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/> <source><h4>Key Updated</h4></source> - <translation type="unfinished"></translation> + <translation type="finished"><H4> Tecla actualizada </ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/> <source><h4>Key Imported</h4></source> - <translation type="unfinished"></translation> + <translation type="finished"><H4> Clave importado </ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/> <source>Upload Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">Subir claves de Keyserver</translation> </message> </context> <context> @@ -1839,22 +1919,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/> <source>Confirm</source> - <translation type="unfinished"></translation> + <translation type="finished">Confirmar</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación fallida</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Se produjo un error durante la operación.</translation> </message> </context> <context> @@ -1862,801 +1942,856 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de caducidad</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/> - <source>Sign For Key's UID(s)</source> - <translation type="unfinished"></translation> + <source>Sign For Key's UID(s)</source> + <translation type="finished">Signo para uid (s) de clave (s)</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/> <source>Unsuccessful Operation</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación fallida</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/> <source>Signature operation failed for UID </source> - <translation type="unfinished"></translation> + <translation type="finished">La operación de la firma falló por UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/> <source>Operation Complete</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación completa</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/> <source>The signature operation of the UID is complete</source> - <translation type="unfinished"></translation> + <translation type="finished">El funcionamiento de la firma del UID está completo.</translation> </message> </context> <context> <name>KeyUploadDialog</name> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/> <source>Uploading Public Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Subiendo la clave pública</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave no encontrada</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation type="finished">Se acabó el tiempo</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation type="finished">Servidor de teclas no encontrado</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error de conexión</translation> </message> </context> <context> <name>KeyserverTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="508"/> - <source>Default Keyserver for import:</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="607"/> + <source>Default Key Server for import:</source> + <translation type="finished">Servidor de tecla predeterminado para importar:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="525"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="624"/> <source>Add</source> - <translation type="unfinished"></translation> + <translation type="finished">Agregar</translation> </message> </context> <context> <name>MainWindow</name> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/> + <location filename="../../src/MainWindow.cpp" line="35"/> + <source>Loading Gnupg</source> + <translation type="finished">Cargando gnupg</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="62"/> + <source>ENV Loading Failed</source> + <translation type="finished">Enviando env falla</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="63"/> + <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> + <translation type="finished">GNUPG no está instalado correctamente, siga las instrucciones de README para instalar GNUPG y luego abrir GPGFRontend.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/> <source>No Key Selected</source> - <translation type="unfinished"></translation> + <translation type="finished">Sin llave seleccionada</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación inválida</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/> <source>The selected key contains a key that does not actually have a encrypt usage.<br/></source> - <translation type="unfinished"></translation> + <translation type="finished">La clave seleccionada contiene una clave que en realidad no tiene un uso de cifrado. <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/> + <source><br/>For example the Following Key: <br/></source> + <translation type="finished"><br/> Por ejemplo, la siguiente clave: <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/> + <source>Encrypting</source> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/> + <source>Function Disabled</source> + <translation type="finished">Función desactivada</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/> + <source>Please go to the settings interface to enable and configure this function.</source> + <translation type="finished">Por favor, vaya a la interfaz de configuración para habilitar y configurar esta función.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/> <source>The selected key contains a key that does not actually have a signature usage.<br/></source> - <translation type="unfinished"></translation> + <translation type="finished">La clave seleccionada contiene una clave que en realidad no tiene un uso de la firma. <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/> + <source>Signing</source> + <translation type="finished">Firma</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/> + <source>Decrypting</source> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/> + <source>Verifying</source> + <translation type="finished">Verificar</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/> <source>Invalid KeyPair</source> - <translation type="unfinished"></translation> + <translation type="finished">Teclado no válido</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/> <source>The selected keypair cannot be used for signing and encryption at the same time.<br/></source> - <translation type="unfinished"></translation> + <translation type="finished">El teclado seleccionado no se puede utilizar para la firma y el cifrado al mismo tiempo. <br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/> <source>Incomplete Operation</source> - <translation type="unfinished"></translation> + <translation type="finished">Operación incompleta</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/> <source>None of the selected key pairs can provide the encryption function.</source> - <translation type="unfinished"></translation> + <translation type="finished">Ninguno de los pares de teclas seleccionados puede proporcionar la función de cifrado.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/> <source>None of the selected key pairs can provide the signature function.</source> - <translation type="unfinished"></translation> + <translation type="finished">Ninguno de los pares de teclas seleccionados puede proporcionar la función de firma.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/> + <source>Encrypting and Signing</source> + <translation type="finished">Cifrado y firma</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/> + <source>Decrypting and Verifying</source> + <translation type="finished">Descifrar y verificar</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <source>Select a file before doing it.</source> + <translation type="finished">Seleccione un archivo antes de hacerlo.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> <source>No permission to read this file.</source> - <translation type="unfinished"></translation> + <translation type="finished">No hay permiso para leer este archivo.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> <source>No permission to create file.</source> - <translation type="unfinished"></translation> + <translation type="finished">No hay permiso para crear un archivo.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation type="finished">Advertencia</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/> <source>The target file already exists, do you need to overwrite it?</source> - <translation type="unfinished"></translation> + <translation type="finished">El archivo objetivo ya existe, ¿necesita sobrescribirlo?</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>An error occurred during operation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Se produjo un error durante la operación.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/> <source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source> - <translation type="unfinished"></translation> + <translation type="finished">Por favor, seleccione el archivo de destino o firma apropiado.Asegúrese de que ambos estén en este directorio.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> <source>No permission to read target file.</source> - <translation type="unfinished"></translation> + <translation type="finished">No hay permiso para leer el archivo de destino.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> <source>No permission to read signature file.</source> - <translation type="unfinished"></translation> + <translation type="finished">No hay permiso para leer el archivo de firma.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> <source>Select a file(.gpg/.asc) before doing it.</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccione un archivo (.gpg / .asc) antes de hacerlo.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/> - <source><br/>For example the Following Key: <br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/> + <source>Outdated Version</source> + <translation type="finished">Versión desactualizada</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> - <source>Select a file before doing it.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/> + <source>This version(%1) is out of date, please update the latest version in time. </source> + <translation type="finished">Esta versión (% 1) está desactualizada, actualice la última versión en el tiempo.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/> + <source>You can download the latest version(%1) on Github Releases Page.<br/></source> + <translation type="finished">Puede descargar la última versión (% 1) en la página de lanzamientos GitHub. <br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/> + <source>Unreleased Version</source> + <translation type="finished">Versión inédita</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/> + <source>This version(%1) has not been officially released and is not recommended for use in a production environment. <br/></source> + <translation type="finished">Esta versión (% 1) no se ha liberado oficialmente y no se recomienda para su uso en un entorno de producción.<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/> <source>There is one unencrypted file in attachment folder</source> - <translation type="unfinished"></translation> + <translation type="finished">Hay un archivo sin cifrado en la carpeta de archivos adjuntos</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source>There are </source> - <translation type="unfinished"></translation> + <translation type="finished">Existen</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source> unencrypted files in attachment folder</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivos sin cifrar en la carpeta ADJUNTO</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/> <source>&New</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/> <source>Open a new file</source> - <translation type="unfinished"></translation> + <translation type="finished">Abrir un nuevo archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/> <source>&Open...</source> - <translation type="unfinished"></translation> + <translation type="finished">&Abierto...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/> <source>Open an existing file</source> - <translation type="unfinished"></translation> + <translation type="finished">Abra un archivo existente</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/> <source>&Browser</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/> <source>Open a file browser</source> - <translation type="unfinished"></translation> + <translation type="finished">Abra un navegador de archivos</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/> <source>&Save</source> - <translation type="unfinished"></translation> + <translation type="finished">&Ahorrar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/> <source>Save the current File</source> - <translation type="unfinished"></translation> + <translation type="finished">Guarda el archivo actual</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/> <source>Save &As</source> - <translation type="unfinished"></translation> + <translation type="finished">Guardar como</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/> <source>Save the current File as...</source> - <translation type="unfinished"></translation> + <translation type="finished">Guarde el archivo actual como ...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/> <source>&Print</source> - <translation type="unfinished"></translation> + <translation type="finished">&Impresión</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/> <source>Print Document</source> - <translation type="unfinished"></translation> + <translation type="finished">Imprimir documento</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation type="finished">&Cerca</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/> <source>Close file</source> - <translation type="unfinished"></translation> + <translation type="finished">Cerrar el archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/> <source>&Quit</source> - <translation type="unfinished"></translation> + <translation type="finished">&Dejar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/> <source>Quit Program</source> - <translation type="unfinished"></translation> + <translation type="finished">Programa de dejar de fumar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/> <source>&Undo</source> - <translation type="unfinished"></translation> + <translation type="finished">&Deshacer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/> <source>Undo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation type="finished">Deshacer Última edición de acción</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/> <source>&Redo</source> - <translation type="unfinished"></translation> + <translation type="finished">&Rehacer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/> <source>Redo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation type="finished">Rehacer la última acción de edición</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/> <source>Zoom In</source> - <translation type="unfinished"></translation> + <translation type="finished">Acercarse</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/> <source>Zoom Out</source> - <translation type="unfinished"></translation> + <translation type="finished">Disminuir el zoom</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/> <source>&Paste</source> - <translation type="unfinished"></translation> + <translation type="finished">&Pegar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/> <source>Paste Text From Clipboard</source> - <translation type="unfinished"></translation> + <translation type="finished">Pegar texto del portapapeles</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/> <source>Cu&t</source> - <translation type="unfinished"></translation> + <translation type="finished">Con & t.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/> - <source>Cut the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <source>Cut the current selection's contents to the clipboard</source> + <translation type="finished">Cortar los contenidos de la selección actual al portapapeles.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/> <source>&Copy</source> - <translation type="unfinished"></translation> + <translation type="finished">&Dupdo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/> - <source>Copy the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <source>Copy the current selection's contents to the clipboard</source> + <translation type="finished">Copia los contenidos de la selección actual al portapapeles.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/> <source>&Quote</source> - <translation type="unfinished"></translation> + <translation type="finished">& quot</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/> <source>Quote whole text</source> - <translation type="unfinished"></translation> + <translation type="finished">Cita todo el texto</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/> <source>Select &All</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccionar todo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/> <source>Select the whole text</source> - <translation type="unfinished"></translation> + <translation type="finished">Seleccione todo el texto</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/> <source>&Find</source> - <translation type="unfinished"></translation> + <translation type="finished">&Encontrar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/> <source>Find a word</source> - <translation type="unfinished"></translation> + <translation type="finished">Encontrar una palabra</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/> <source>Remove &spacing</source> - <translation type="unfinished"></translation> + <translation type="finished">Retirar y espaciar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/> <source>Remove double linebreaks, e.g. in pasted text from webmailer</source> - <translation type="unfinished"></translation> + <translation type="finished">Retire las letras dobles, por ejemplo.En texto pegado desde Webmailer.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/> <source>Se&ttings</source> - <translation type="unfinished"></translation> + <translation type="finished">Y tutting</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/> <source>Open settings dialog</source> - <translation type="unfinished"></translation> + <translation type="finished">Abrir configuración de diálogo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/> <source>&Encrypt</source> - <translation type="unfinished"></translation> + <translation type="finished">Y cifrar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/> <source>Encrypt Message</source> - <translation type="unfinished"></translation> + <translation type="finished">Cifrar mensaje</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/> <source>&Encrypt &Sign</source> - <translation type="unfinished"></translation> + <translation type="finished">& Cifrar y firmar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/> <source>Encrypt and Sign Message</source> - <translation type="unfinished"></translation> + <translation type="finished">Cifrar y firmar mensaje</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/> <source>&Decrypt</source> - <translation type="unfinished"></translation> + <translation type="finished">Y descifrar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/> <source>Decrypt Message</source> - <translation type="unfinished"></translation> + <translation type="finished">Mensaje de descifra</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/> <source>&Decrypt &Verify</source> - <translation type="unfinished"></translation> + <translation type="finished">Y descifrar y verificar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/> <source>Decrypt and Verify Message</source> - <translation type="unfinished"></translation> + <translation type="finished">Descifrar y verificar el mensaje</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/> <source>&Encrypt File</source> - <translation type="unfinished"></translation> + <translation type="finished">Cifrar archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation type="finished">Cifrar archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/> <source>&Decrypt File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de descifrado</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de descifrado</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/> <source>&Sign File</source> - <translation type="unfinished"></translation> + <translation type="finished">Y firmar archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo de firma</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/> <source>&Verify File</source> - <translation type="unfinished"></translation> + <translation type="finished">Y verificar el archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation type="finished">Verificar archivo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/> <source>&Sign</source> - <translation type="unfinished"></translation> + <translation type="finished">&Firmar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/> <source>Sign Message</source> - <translation type="unfinished"></translation> + <translation type="finished">Mensaje de signo</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/> <source>&Verify</source> - <translation type="unfinished"></translation> + <translation type="finished">&Verificar</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/> <source>Verify Message</source> - <translation type="unfinished"></translation> + <translation type="finished">Verificar mensaje</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/> <source>&Editor</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/> <source>Import New Key From Editor</source> - <translation type="unfinished"></translation> + <translation type="finished">Importar nueva clave del editor</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/> - <source>Manage &keys</source> - <translation type="unfinished"></translation> + <source>Manage &Keys</source> + <translation type="finished">Gestión y llaves</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/> <source>Open Keymanagement</source> - <translation type="unfinished"></translation> + <translation type="finished">MANIFICACIÓN ABIERTA</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/> <source>&About</source> - <translation type="unfinished"></translation> + <translation type="finished">&Acerca de</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/> + <source>Show the application's About box</source> + <translation type="finished">Muestra la siguiente aplicación</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/> - <source>Show the application's About box</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/> + <source>&Check for Updates</source> + <translation type="finished">Compruebe las actualizaciones</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <source>Check for updates</source> + <translation type="finished">Compruebe las actualizaciones</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/> <source>Open &Wizard</source> - <translation type="unfinished"></translation> + <translation type="finished">Abierto y asistente</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> <source>Open the wizard</source> - <translation type="unfinished"></translation> + <translation type="finished">Abrir el asistente</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> <source>Append Selected Key(s) To Text</source> - <translation type="unfinished"></translation> + <translation type="finished">Anexar la (s) clave (s) seleccionada (s) al texto</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> <source>Append The Selected Keys To Text in Editor</source> - <translation type="unfinished"></translation> + <translation type="finished">Anexar las teclas seleccionadas al texto en el editor</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> - <source>Copy EMail-address</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <source>Copy Email</source> + <translation type="finished">Copiar el correo electrónico</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/> - <source>Copy selected EMailaddress to clipboard</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <source>Copy selected Email to clipboard</source> + <translation type="finished">Copia el correo electrónico seleccionado al portapapeles.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation type="finished">Mostrar detalles clave</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Mostrar detalles para esta clave</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/> <source>Refresh Key From Key Server</source> - <translation type="unfinished"></translation> + <translation type="finished">Actualizar la llave del servidor clave</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/> <source>Refresh key from default key server</source> - <translation type="unfinished"></translation> + <translation type="finished">Actualizar la tecla del servidor de clave predeterminado</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/> <source>Upload Public Key(s) To Server</source> - <translation type="unfinished"></translation> + <translation type="finished">Cargar la (s) clave pública al servidor</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/> <source>Upload The Selected Public Keys To Server</source> - <translation type="unfinished"></translation> + <translation type="finished">Sube las claves públicas seleccionadas para el servidor</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/> <source>Remove PGP Header</source> - <translation type="unfinished"></translation> + <translation type="finished">Retire el encabezado PGP</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/> <source>Add PGP Header</source> - <translation type="unfinished"></translation> + <translation type="finished">Añadir PGP Encabezado</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation type="finished">&Archivo</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/> <source>&Edit</source> - <translation type="unfinished"></translation> + <translation type="finished">&Editar</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/> <source>&File...</source> - <translation type="unfinished"></translation> + <translation type="finished">&Archivo...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/> <source>&Crypt</source> - <translation type="unfinished"></translation> + <translation type="finished">&Cripta</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> <source>&Keys</source> - <translation type="unfinished"></translation> + <translation type="finished">&Llaves</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation type="finished">E importar clave</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/> <source>&Steganography</source> - <translation type="unfinished"></translation> + <translation type="finished">Steganography</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> <source>&View</source> - <translation type="unfinished"></translation> + <translation type="finished">&Vista</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/> <source>&Help</source> - <translation type="unfinished"></translation> + <translation type="finished">&Ayudar</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/> <source>File</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivo</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/> <source>Crypt</source> - <translation type="unfinished"></translation> + <translation type="finished">Cripta</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/> <source>Edit</source> - <translation type="unfinished"></translation> + <translation type="finished">Editar</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/> <source>Special Edit</source> - <translation type="unfinished"></translation> + <translation type="finished">Edición especial</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/> <source>Import key from...</source> - <translation type="unfinished"></translation> + <translation type="finished">Clave de importación de ...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation type="finished">Tecla de importación</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/> <source>Browser to view and operate file</source> - <translation type="unfinished"></translation> + <translation type="finished">Navegador para ver y operar el archivo</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/> <source>Browser</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/> <source>Ready</source> - <translation type="unfinished"></translation> + <translation type="finished">Listo</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/> <source>Key ToolBox</source> - <translation type="unfinished"></translation> + <translation type="finished">Caja de herramientas clave</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/> <source>Information Board</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>MimeTab</name> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> - <source>Decode quoted printable</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="292"/> - <source>Try to recognize quoted printable.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="296"/> - <source>Parse PGP/MIME (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="299"/> - <source>Try to split attachments from PGP-MIME ecrypted messages.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="304"/> - <source>Open with external application (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="306"/> - <source>Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> - <source>Enable opening with external applications.</source> - <translation type="unfinished"></translation> + <translation type="finished">Tarjeta de la información</translation> </message> </context> <context> @@ -2664,107 +2799,107 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/> <source>>Recipient: </source> - <translation type="unfinished"></translation> + <translation type="finished">> Recipiente:</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/> <source>One or More Bad Signatures.</source> - <translation type="unfinished"></translation> + <translation type="finished">Una o más firmas malas.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/> <source>A </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation type="finished">Bien</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/> - <source>Missing Key's </source> - <translation type="unfinished"></translation> + <source>Missing Key's </source> + <translation type="finished">Llaves perdidas</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/> - <source>Revoked Key's </source> - <translation type="unfinished"></translation> + <source>Revoked Key's </source> + <translation type="finished">Clave revocada</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/> - <source>Expired Key's </source> - <translation type="unfinished"></translation> + <source>Expired Key's </source> + <translation type="finished">Key caducado</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/> - <source>Missing CRL's </source> - <translation type="unfinished"></translation> + <source>Missing CRL's </source> + <translation type="finished">Falta CRL</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/> <source>Signature Fully Valid.</source> - <translation type="unfinished"></translation> + <translation type="finished">Firma totalmente válida.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/> <source>Signature NOT Fully Valid.</source> - <translation type="unfinished"></translation> + <translation type="finished">Firma no completamente válida.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/> <source>Key is NOT present with ID 0x</source> - <translation type="unfinished"></translation> + <translation type="finished">La llave no está presente con ID 0x</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/> <source>A signature could NOT be verified due to a Missing Key </source> - <translation type="unfinished"></translation> + <translation type="finished">No se pudo verificar una firma debido a una llave faltante.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/> <source>A signature is valid but the key used to verify the signature has been revoked </source> - <translation type="unfinished"></translation> + <translation type="finished">Una firma es válida, pero la clave utilizada para verificar la firma ha sido revocada</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/> <source>A signature is valid but expired </source> - <translation type="unfinished"></translation> + <translation type="finished">Una firma es válida pero caducada.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/> <source>A signature is valid but the key used to verify the signature has expired. </source> - <translation type="unfinished"></translation> + <translation type="finished">Una firma es válida, pero la clave utilizada para verificar la firma ha caducado.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/> <source>There was some other error which prevented the signature verification. </source> - <translation type="unfinished"></translation> + <translation type="finished">Hubo algún otro error que impidió la verificación de la firma.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/> <source>Error for key with fingerprint </source> - <translation type="unfinished"></translation> + <translation type="finished">Error a la llave con la huella digital</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/> <source>Signed By: </source> - <translation type="unfinished"></translation> + <translation type="finished">Firmado por:</translation> </message> </context> <context> @@ -2772,60 +2907,193 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/QuitDialog.cpp" line="29"/> <source>Unsaved Files</source> - <translation type="unfinished"></translation> + <translation type="finished">Archivos no guardados</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="77"/> - <source><h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3></source> - <translation type="unfinished"></translation> + <source>%1 files contain unsaved information.<br/>Save the changes before closing?</source> + <translation type="finished">% 1 Los archivos contienen información no guardada. <br/> ¡Guarda los cambios antes de cerrar?</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="88"/> <source>Check the files you want to save:</source> - <translation type="unfinished"></translation> + <translation type="finished">Compruebe los archivos que desea guardar:</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="89"/> - <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <translation type="finished"><b> Nota: </ b> Si no guarda estos archivos, todos los cambios se pierden. <br/></translation> + </message> +</context> +<context> + <name>SendMailDialog</name> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="35"/> + <source>Incomplete configuration</source> + <translation type="finished">Configuración incompleta</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="36"/> + <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source> + <translation type="finished">La dirección SMTP está vacía, vaya a la interfaz de configuración para completar la configuración.</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="86"/> + <source> Recipient cannot be empty +</source> + <translation type="finished">El destinatario no puede estar vacío</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="91"/> + <source> One or more Recipient's Email Address is invalid +</source> + <translation type="finished">Una o más dirección de correo electrónico del destinatario no es válida</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="97"/> + <source> Sender cannot be empty +</source> + <translation type="finished">El remitente no puede estar vacío</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="99"/> + <source> Sender's Email Address is invalid +</source> + <translation type="finished">La dirección de correo electrónico del remitente no es válida</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail</source> + <translation type="finished">Fallar</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <source>Fail to Connect SMTP Server</source> + <translation type="finished">Falla en conectar el servidor SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <source>Fail to Login into SMTP Server</source> + <translation type="finished">No iniciar sesión en el servidor SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail to Send Mail to SMTP Server</source> + <translation type="finished">No enviar correo al servidor SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Success</source> + <translation type="finished">Éxito</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Succeed in Sending Mail to SMTP Server</source> + <translation type="finished">Tener éxito en enviar correo al servidor SMTP</translation> + </message> +</context> +<context> + <name>SendMailTab</name> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> + <source>Enable</source> + <translation type="finished">Permitir</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="311"/> + <source>SMTP Address</source> + <translation type="finished">Dirección SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="313"/> + <source>Username</source> + <translation type="finished">Nombre de usuario</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> + <source>Password</source> + <translation type="finished">Contraseña</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="317"/> + <source>Port</source> + <translation type="finished">Puerto</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="319"/> + <source>Connection Security</source> + <translation type="finished">Seguridad de la conexión</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="322"/> + <source>Default Sender</source> + <translation type="finished">Remitente predeterminado</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail</source> + <translation type="finished">Fallar</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <source>Fail to Connect SMTP Server</source> + <translation type="finished">Falla en conectar el servidor SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail to Login</source> + <translation type="finished">Falla en iniciar sesión</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Success</source> + <translation type="finished">Éxito</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Succeed in connecting and login</source> + <translation type="finished">Tener éxito en la conexión e inicio de sesión</translation> </message> </context> <context> <name>SettingsDialog</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="38"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> <source>General</source> - <translation type="unfinished"></translation> + <translation type="finished">General</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="39"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> <source>Appearance</source> - <translation type="unfinished"></translation> + <translation type="finished">Apariencia</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> - <source>PGP/Mime</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="42"/> + <source>Send Mail</source> + <translation type="finished">Enviar correo</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> <source>Key Server</source> - <translation type="unfinished"></translation> + <translation type="finished">Servidor clave</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="45"/> <source>Advanced</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="56"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="58"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation type="finished">Ajustes</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="101"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="103"/> <source>System Default</source> - <translation type="unfinished"></translation> + <translation type="finished">Sistema por defecto</translation> </message> </context> <context> @@ -2833,62 +3101,62 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/> <source>Generate New Subkey</source> - <translation type="unfinished"></translation> + <translation type="finished">Generar nueva subclave</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation type="finished">Firma</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation type="finished">Certificación</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation type="finished">Autenticación</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation type="finished">Fecha de caducidad:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation type="finished">Nunca expira</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation type="finished">Keysize (en bit):</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation type="finished">Tipo de llave:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation type="finished">Información básica</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/> <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <translation type="finished">Tiempo de vencimiento No más de 2 años.</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/> <source>Generating Subkey...</source> - <translation type="unfinished"></translation> + <translation type="finished">Generando Subkey ...</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/> @@ -2896,90 +3164,129 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation type="finished">Recogiendo datos aleatorios para la generación de suba. + Esto puede tardar un rato. + Para acelerar el proceso, use su computadora. + (Por ejemplo, navega por la red, escucha música, ...)</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation type="finished">Éxito</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>The new subkey has been generated.</source> - <translation type="unfinished"></translation> + <translation type="finished">La nueva subclave ha sido generada.</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation type="finished">Falla</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>An error occurred during subkey generation.</source> - <translation type="unfinished"></translation> + <translation type="finished">Se produjo un error durante la generación de sujetas.</translation> </message> </context> <context> <name>TextEdit</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/> <source>untitled</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation type="finished">Advertencia</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/> + <source>Cannot read file %1: +%2.</source> + <translation type="finished">No se puede leer el archivo% 1: +% 2.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/> <source>Open file</source> - <translation type="unfinished"></translation> + <translation type="finished">Abrir documento</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/> + <source>File</source> + <translation type="finished">Archivo</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/> + <source>Cannot write file %1: +%2.</source> + <translation type="finished">No se puede escribir archivo% 1: +% 2.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> <source>Save file</source> - <translation type="unfinished"></translation> + <translation type="finished">Guardar el archivo</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/> + <source>Unsaved document</source> + <translation type="finished">Documento no guardado</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/> + <source>The document "%1" has been modified. Do you want to save your changes?<br/></source> + <translation type="finished">El documento "% 1" ha sido modificado.¿Quieres guardar tus cambios? <br/></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/> + <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <translation type="finished"><b> Nota: </ b> Si no guarda estos archivos, todos los cambios se pierden. <br/></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/> <source>Application</source> - <translation type="unfinished"></translation> + <translation type="finished">Solicitud</translation> </message> +</context> +<context> + <name>UpdateTab</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/> - <source>Cannot read file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/> + <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source> + <translation type="finished">Se recomienda que siempre revise la versión de GPGFRontend y actualice a la última versión.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/> + <source>New versions not only represent new features, but also often represent functional and security fixes.</source> + <translation type="finished">Las nuevas versiones no solo representan nuevas características, sino que también representan correcciones funcionales y de seguridad.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/> + <source>Current Version: </source> + <translation type="finished">Versión actual:</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/> - <source>Unsaved document</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/> + <source>The current version is inconsistent with the latest version on github.</source> + <translation type="finished">La versión actual es inconsistente con la última versión en GitHub.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/> - <source><h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/> + <source>Please click <a href="https://github.com/saturneric/GpgFrontend/releases">here</a> to download the latest version.</source> + <translation type="finished">Haga clic en <a href="https://github.com/saturnic/gpgfrontend/releseses"> aquí </a> para descargar la última versión.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> - <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/> + <source>Latest Version From Github: </source> + <translation type="finished">Última versión de GitHub:</translation> </message> </context> <context> @@ -2987,32 +3294,32 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/> <source>Signature Details</source> - <translation type="unfinished"></translation> + <translation type="finished">Detalles de la firma</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/> <source>Status: </source> - <translation type="unfinished"></translation> + <translation type="finished">Estado:</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/> <source>No valid input found</source> - <translation type="unfinished"></translation> + <translation type="finished">No se ha encontrado ninguna entrada válida</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/> <source>Error Validating signature</source> - <translation type="unfinished"></translation> + <translation type="finished">Error al validar la firma</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/> <source>File was signed on %1 <br/> It Contains:<br/><br/></source> - <translation type="unfinished"></translation> + <translation type="finished">El archivo se firmó en% 1 <br/>, contiene: <br/> <br/></translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/> <source>Signed on %1 <br/> It Contains:<br /><br/></source> - <translation type="unfinished"></translation> + <translation type="finished">Firmado en% 1 <br/> contiene: <br /> <br/></translation> </message> </context> <context> @@ -3020,22 +3327,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/> <source>Import from keyserver</source> - <translation type="unfinished"></translation> + <translation type="finished">Import desde Keyserver</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/> <source>Key not present with id 0x</source> - <translation type="unfinished"></translation> + <translation type="finished">Llave no presente con id 0x</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/> <source>Status:</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/> <source>Key not present in keylist</source> - <translation type="unfinished"></translation> + <translation type="finished">Llave no presente en el keylist</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/> @@ -3045,7 +3352,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/> <source>Key Information is NOT Available</source> - <translation type="unfinished"></translation> + <translation type="finished">La información clave no está disponible</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/> @@ -3055,103 +3362,103 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation type="finished">Huella dactilar:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/> <source>Status: Cert Revoked</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado: CERT REVOCED</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/> <source>Status: Signature Expired</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado: Firma expiró</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/> <source>Status: Key Expired</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado: clave expirada</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/> <source>Status: General Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado: Error general</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/> <source>Status: Unknown Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Estado: error desconocido</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/> <source>Signer Name:</source> - <translation type="unfinished"></translation> + <translation type="finished">Nombre del firmante:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/> <source>Signer Email:</source> - <translation type="unfinished"></translation> + <translation type="finished">Correo electrónico del firmante:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/> - <source>Key's Fingerprint:</source> - <translation type="unfinished"></translation> + <source>Key's Fingerprint:</source> + <translation type="finished">Huella digital de la llave:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/> <source>Valid:</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/> <source>Flags:</source> - <translation type="unfinished"></translation> + <translation type="finished">Banderas:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/> <source>Fully Valid</source> - <translation type="unfinished"></translation> + <translation type="finished">Completamente válido</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/> <source>NOT Fully Valid</source> - <translation type="unfinished"></translation> + <translation type="finished">No completamente válido</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation type="finished">Bien</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/> <source>Missing Key </source> - <translation type="unfinished"></translation> + <translation type="finished">Llave faltante</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/> <source>Revoked Key </source> - <translation type="unfinished"></translation> + <translation type="finished">Clave revocada</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/> <source>Expired Key </source> - <translation type="unfinished"></translation> + <translation type="finished">Clave caducada</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/> <source>Missing CRL </source> - <translation type="unfinished"></translation> + <translation type="finished">Falta CRL</translation> </message> </context> <context> @@ -3159,33 +3466,33 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/Wizard.cpp" line="46"/> <source>First Start Wizard</source> - <translation type="unfinished"></translation> + <translation type="finished">Asistente de primer inicio</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error de importación</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> - <source>Couldn't locate any keyring file in %1</source> - <translation type="unfinished"></translation> + <source>Couldn't locate any keyring file in %1</source> + <translation type="finished">No se pudo localizar ningún archivo de llaves en% 1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="84"/> <location filename="../../src/ui/Wizard.cpp" line="95"/> <source>Import error</source> - <translation type="unfinished"></translation> + <translation type="finished">Error de importación</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="85"/> - <source>Couldn't open private keyringfile: %1</source> - <translation type="unfinished"></translation> + <source>Couldn't open private keyringfile: %1</source> + <translation type="finished">No se pudo abrir el archivo de llavero privado:% 1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="96"/> - <source>Couldn't open public keyringfile: %1</source> - <translation type="unfinished"></translation> + <source>Couldn't open public keyringfile: %1</source> + <translation type="finished">No se pudo abrir el archivo de llavero público:% 1</translation> </message> </context> -</TS> +</TS>
\ No newline at end of file diff --git a/resource/ts/gpg_frontend_fr.ts b/resource/ts/gpgfrontend_fr.ts index a32fcc56..fe49011a 100644 --- a/resource/ts/gpg_frontend_fr.ts +++ b/resource/ts/gpgfrontend_fr.ts @@ -4,212 +4,197 @@ <context> <name>AboutDialog</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="29"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/> <source>About </source> - <translation type="unfinished"></translation> + <translation>À propos</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="35"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/> <source>General</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="36"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/> <source>Translators</source> <translation type="unfinished"></translation> </message> + <message> + <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/> + <source>Update</source> + <translation>Mettre à jour</translation> + </message> </context> <context> <name>AdvancedTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="580"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="679"/> <source>Show Steganography Options [Advanced]</source> - <translation type="unfinished"></translation> + <translation>Afficher les options de la stéganographie [avancée]</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="582"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="681"/> <source>Show Steganographic Options.</source> - <translation type="unfinished"></translation> + <translation>Afficher les options stéganographiques.</translation> </message> </context> <context> <name>AppearanceTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="368"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="444"/> <source>Iconsize</source> - <translation type="unfinished"></translation> + <translation>Isoniser.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="370"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="446"/> <source>small</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="371"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="447"/> <source>medium</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="372"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="448"/> <source>large</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="388"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="464"/> <source>Iconstyle</source> - <translation type="unfinished"></translation> + <translation>Iconstyle</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="390"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="466"/> <source>just text</source> - <translation type="unfinished"></translation> + <translation>juste du texte</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="391"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="467"/> <source>just icons</source> - <translation type="unfinished"></translation> + <translation>juste des icônes</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="392"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="468"/> <source>text and icons</source> - <translation type="unfinished"></translation> + <translation>Texte et icônes</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="484"/> <source>Windowstate</source> - <translation type="unfinished"></translation> + <translation>Windowstate</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="411"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="487"/> <source>Save window size and position on exit.</source> - <translation type="unfinished"></translation> + <translation>Enregistrer la taille de la fenêtre et la position à la sortie.</translation> </message> -</context> -<context> - <name>AttachmentTableModel</name> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="495"/> + <source>Information Board</source> + <translation>Tableau d'information</translation> </message> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="501"/> + <source> Front Size</source> + <translation>Taille avant</translation> </message> </context> <context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> + <name>ChoosePage</name> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="165"/> + <source>Choose your action...</source> + <translation>Choisissez votre action ...</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="166"/> + <source>...by clicking on the appropriate link.</source> + <translation>... En cliquant sur le lien approprié.</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="168"/> + <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> + <translation>Si vous n'avez jamais utilisé GPGFRontend avant et que vous ne possédez pas encore une clé GPG, vous pouvez éventuellement vouloir lire comment</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="170"/> + <source>Generate Key</source> + <translation>Générer une clé</translation> </message> -</context> -<context> - <name>ChoosePage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="161"/> - <source>Choose your action...</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="176"/> + <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source> + <translation>Si vous souhaitez apprendre à crypter, déchiffrer, signer et vérifier le texte, vous pouvez lire</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="162"/> - <source>...by clicking on the appropriate link.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <source>Encrypt & Decrypt Text</source> + <translation>Texte de chiffrement et de déchiffrement</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="164"/> - <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>or</source> + <translation>ou alors</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="172"/> - <source>If you want to learn how to encrypt and decrypt text, you can read </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="180"/> + <source>Sign & Verify Text</source> + <translation>Signer et vérifier le texte</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="174"/> - <location filename="../../src/ui/Wizard.cpp" line="183"/> - <source>this document</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="188"/> + <source>If you want to operate file, you can read </source> + <translation>Si vous souhaitez utiliser un fichier, vous pouvez lire</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="181"/> - <source>If you want to sign and verify text, you can read </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>Encrypt & Sign File</source> + <translation>Crypypt et fichier de signe</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="166"/> - <source>create a new keypair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="192"/> + <source>Sign & Verify File</source> + <translation>Signez et vérifiez le fichier</translation> </message> </context> <context> <name>ConclusionPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="397"/> + <location filename="../../src/ui/Wizard.cpp" line="407"/> <source>Ready.</source> - <translation type="unfinished"></translation> + <translation>Prêt.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="398"/> + <location filename="../../src/ui/Wizard.cpp" line="408"/> <source>Have fun with GPGFrontend!</source> - <translation type="unfinished"></translation> + <translation>Amusez-vous avec GPGFrontend!</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="400"/> + <location filename="../../src/ui/Wizard.cpp" line="410"/> <source>You are ready to use GPGFrontend now.<br><br></source> - <translation type="unfinished"></translation> + <translation>Vous êtes prêt à utiliser GPGFronTend maintenant. <br> <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="402"/> + <location filename="../../src/ui/Wizard.cpp" line="412"/> <source>The Online Document</source> - <translation type="unfinished"></translation> + <translation>Le document en ligne</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="403"/> + <location filename="../../src/ui/Wizard.cpp" line="413"/> <source> will get you started with GPGFrontend. It will open in the main window.<br></source> - <translation type="unfinished"></translation> + <translation>vous fera commencer par GPGFronTend.Il s'ouvrira dans la fenêtre principale. <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="410"/> + <location filename="../../src/ui/Wizard.cpp" line="420"/> <source>Open offline help.</source> - <translation type="unfinished"></translation> + <translation>Aide ouverte hors ligne.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="413"/> + <location filename="../../src/ui/Wizard.cpp" line="423"/> <source>Dont show the wizard again.</source> - <translation type="unfinished"></translation> + <translation>Ne montrez pas à nouveau l'assistant.</translation> </message> </context> <context> @@ -217,129 +202,152 @@ <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation>Dossier de déchiffrement</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation>Chiffrer</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation>Fichier de signe</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation>Vérifier le fichier</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/> <source>Input Parameters</source> - <translation type="unfinished"></translation> + <translation>Paramètres d'entrée</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/> <source>Target File</source> - <translation type="unfinished"></translation> + <translation>Fichier cible</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/> <source>Output File</source> - <translation type="unfinished"></translation> + <translation>Fichier de sortie</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/> <source>Signature File(.sig) Path</source> - <translation type="unfinished"></translation> + <translation>Signature Fichier (.sig) chemin</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/> <source>Open File</source> - <translation type="unfinished"></translation> + <translation>Fichier ouvert</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/> <source>Save File</source> - <translation type="unfinished"></translation> + <translation>Enregistrer le fichier</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> <source>Couldn't open file</source> - <translation type="unfinished"></translation> + <translation>Impossible d'ouvrir le fichier</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/> + <source>Error</source> + <translation>Erreur</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/> + <source>Error Occurred During Encryption</source> + <translation>Une erreur s'est produite lors du cryptage</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/> + <source>Error Occurred During Decryption</source> + <translation>Une erreur s'est produite lors du déchiffrement</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> + <source>Error Occurred During Signature</source> + <translation>Une erreur s'est produite lors de la signature</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Déposer</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/> <source>File exists! Do you want to overwrite it?</source> - <translation type="unfinished"></translation> + <translation>Le fichier existe!Voulez-vous vous écraser?</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/> <source>Cannot write file %1: %2.</source> - <translation type="unfinished"></translation> + <translation>Impossible d'écrire le fichier% 1: +% 2.</translation> </message> </context> <context> <name>FilePage</name> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/> <source>Open</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/> <source>Delete</source> - <translation type="unfinished"></translation> + <translation>Effacer</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/> <source>Encrypt and Sign</source> - <translation type="unfinished"></translation> + <translation>Chiffrer et signer</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/> <source>Decrypt and Verify</source> - <translation type="unfinished"></translation> + <translation>Déchiffrer et vérifier</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/> <source>Only Sign</source> - <translation type="unfinished"></translation> + <translation>Seulement signe</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/> <source>Only Verify</source> - <translation type="unfinished"></translation> + <translation>Vérifiez seulement</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>Avertissement</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/> <source>Are you sure you want to delete it?</source> - <translation type="unfinished"></translation> + <translation>Es-tu sûr de vouloir le supprimer?</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation>Erreur</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/> <source>Unable to delete the file or folder.</source> - <translation type="unfinished"></translation> + <translation>Impossible de supprimer le fichier ou le dossier.</translation> </message> </context> <context> @@ -347,266 +355,281 @@ <message> <location filename="../../src/ui/FindWidget.cpp" line="38"/> <source>Find:</source> - <translation type="unfinished"></translation> + <translation>Trouve:</translation> </message> </context> <context> <name>GeneralTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="135"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="137"/> <source>Remember Password</source> - <translation type="unfinished"></translation> + <translation>Se souvenir du mot de passe</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="138"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="140"/> <source>Remember password until closing gpg4usb</source> - <translation type="unfinished"></translation> + <translation>Rappelez-vous le mot de passe jusqu'à la fermeture GPG4USB</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="145"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="147"/> <source>Save Checked Keys</source> - <translation type="unfinished"></translation> + <translation>Sauvegarder les clés cochées</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="148"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="150"/> <source>Save checked private keys on exit and restore them on next start.</source> - <translation type="unfinished"></translation> + <translation>Enregistrez des clés privées cochées sur sortie et restaurez-les au prochain démarrage.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="157"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="159"/> <source>Confirm drag'n'drop key import</source> - <translation type="unfinished"></translation> + <translation>Confirmer l'importation principale de Drag'N'Drop</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="160"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="162"/> <source>Import files dropped on the keylist without confirmation.</source> - <translation type="unfinished"></translation> + <translation>Les fichiers d'importation ont chuté sur la frappe sans confirmation.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="167"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="169"/> <source>Language</source> - <translation type="unfinished"></translation> + <translation>Langue</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="176"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="178"/> <source><b>NOTE: </b> GpgFrontend will restart automatically if you change the language!</source> - <translation type="unfinished"></translation> + <translation><B> REMARQUE: </ B> GPGFRontend redémarrera automatiquement si vous changez la langue!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="185"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="187"/> <source>Own key</source> - <translation type="unfinished"></translation> + <translation>Clé propre</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="193"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="195"/> <source><none></source> - <translation type="unfinished"></translation> + <translation><aucun></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="207"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="209"/> <source>Key pair for synchronization and identity authentication</source> - <translation type="unfinished"></translation> + <translation>Paire de clé pour la synchronisation et l'authentification d'identité</translation> </message> </context> <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="90"/> - <source>ENV Loading Failed</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="91"/> - <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="577"/> + <location filename="../../src/gpg/GpgContext.cpp" line="528"/> <source>Wrong password</source> - <translation type="unfinished"></translation> + <translation>Mauvais mot de passe</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="585"/> + <location filename="../../src/gpg/GpgContext.cpp" line="536"/> <source>Enter Password for</source> - <translation type="unfinished"></translation> + <translation>Entrez le mot de passe pour</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="589"/> + <location filename="../../src/gpg/GpgContext.cpp" line="540"/> <source>Enter Password</source> - <translation type="unfinished"></translation> + <translation>Entrer le mot de passe</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>Key Selection</source> - <translation type="unfinished"></translation> + <translation>Sélection de clé</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>No Private Key Selected</source> - <translation type="unfinished"></translation> + <translation>Aucune clé privée sélectionnée</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="804"/> + <location filename="../../src/gpg/GpgContext.cpp" line="746"/> <source>Error in signing:</source> - <translation type="unfinished"></translation> + <translation>Erreur lors de la signature:</translation> </message> </context> <context> <name>GpgPathsTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="612"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="711"/> <source>Relative path to keydb</source> - <translation type="unfinished"></translation> + <translation>Chemin relatif de Keydb</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="625"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="724"/> <source>Current keydb path: </source> - <translation type="unfinished"></translation> + <translation>Chemin de Keydb actuel:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="630"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="729"/> <source><b>NOTE: </b> Gpg4usb will restart automatically if you change the keydb path!</source> - <translation type="unfinished"></translation> + <translation><B> REMARQUE: </ B> GPG4USB redémarrera automatiquement si vous modifiez le chemin Keydb!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="659"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="758"/> <source>Choose keydb directory</source> - <translation type="unfinished"></translation> + <translation>Choisissez le répertoire Keydb</translation> </message> </context> <context> <name>ImportFromGnupgPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="292"/> + <location filename="../../src/ui/Wizard.cpp" line="302"/> <source>Import keys...</source> - <translation type="unfinished"></translation> + <translation>Keys d'importation ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="293"/> + <location filename="../../src/ui/Wizard.cpp" line="303"/> <source>...from existing GnuPG installation</source> - <translation type="unfinished"></translation> + <translation>... de l'installation GNUPG existante</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="295"/> + <location filename="../../src/ui/Wizard.cpp" line="305"/> <source>You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br></source> - <translation type="unfinished"></translation> + <translation>Vous pouvez importer des clés à partir d'un GNUPG installé localement. <br> <br> <br> L'emplacement est lu depuis Registre sous Windows ou supposé être le dossier .gnupg dans votre annuaire de domicile sous Linux. <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="299"/> + <location filename="../../src/ui/Wizard.cpp" line="309"/> <source>Import keys from GnuPG</source> - <translation type="unfinished"></translation> + <translation>Keys d'importation de gnupg</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation>Erreur d'importation</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Couldn't locate GnuPG home directory</source> - <translation type="unfinished"></translation> + <translation>Ne pouvait pas localiser le répertoire de base gnupg</translation> </message> </context> <context> <name>ImportFromGpg4usbPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="215"/> + <location filename="../../src/ui/Wizard.cpp" line="225"/> <source>Import from...</source> - <translation type="unfinished"></translation> + <translation>Importer de...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="216"/> + <location filename="../../src/ui/Wizard.cpp" line="226"/> <source>...existing GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>... GPGFronTend existant</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="218"/> + <location filename="../../src/ui/Wizard.cpp" line="228"/> <source>You can import keys and/or settings from existing GPGFrontend. <br><br>Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source> - <translation type="unfinished"></translation> + <translation>Vous pouvez importer des clés et / ou des paramètres de GPGFronTend existant.<br> <br> Vérifiez simplement ce que vous souhaitez importer, cliquez sur le bouton Importer et choisissez le répertoire de votre autre GPGFronTend dans la boîte de dialogue de fichiers apparaissant.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="225"/> + <location filename="../../src/ui/Wizard.cpp" line="235"/> <source>Keys</source> - <translation type="unfinished"></translation> + <translation>Clés</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="229"/> + <location filename="../../src/ui/Wizard.cpp" line="239"/> <source>Configuration</source> - <translation type="unfinished"></translation> + <translation>Configuration</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="231"/> + <location filename="../../src/ui/Wizard.cpp" line="241"/> <source>Import from GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>Importer de GPGFrontend</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="246"/> + <location filename="../../src/ui/Wizard.cpp" line="256"/> <source>Other GPGFrontend directory</source> - <translation type="unfinished"></translation> + <translation>Autre répertoire GPGFRONTEND</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="265"/> + <location filename="../../src/ui/Wizard.cpp" line="275"/> <source>Configuration Imported</source> - <translation type="unfinished"></translation> + <translation>Configuration importée</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="266"/> + <location filename="../../src/ui/Wizard.cpp" line="276"/> <source>Imported Configuration from old GPGFrontend.<br>Will now restart to activate the configuration.</source> - <translation type="unfinished"></translation> + <translation>Configuration importée d'Old GPGFronTend. <br> va maintenant redémarrer pour activer la configuration.</translation> </message> </context> <context> <name>InfoBoardWidget</name> <message> - <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/> <source>Import missing key from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Importer la clé manquante de Keyserver</translation> + </message> + <message> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/> + <source>Optional Actions Menu</source> + <translation>Menu Actions optionnelles</translation> </message> </context> <context> <name>InfoTab</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="55"/> - <source><br><center>GPGFrontend is an easy-to-use, compact, <br>cross-platform, and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/> + <source><br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> + <translation><br> <centre> GPGFronTend est un outil facile à utiliser, compact, plate-forme, <br> et sans installation GPG GPG GPG. Il visualise la plupart des opérations communes des commandes GPG. <br> Il est sous licence sous la GPL V3 <br> <B> Développeur: </ B> <br> <br> Saturneric <br> <br> Si vous avez des questions ou des suggestions, soulevez un problème <br/> à <Ahref = "https://github.com/saturneric/gpgfrontend"> github </a> ou envoyer un mail à ma liste de diffusion à <a href="[email protected]"> [email protected] </ a>.</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="63"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/> <source><br><br> Built with Qt </source> - <translation type="unfinished"></translation> + <translation><br> <br> Construit avec QT</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="64"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/> <source> and GPGME </source> - <translation type="unfinished"></translation> + <translation>et gpgme</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="65"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/> <source><br>Built at </source> - <translation type="unfinished"></translation> + <translation><br> Construit à</translation> </message> </context> <context> <name>IntroPage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="111"/> - <source>Getting started...</source> - <translation type="unfinished"></translation> + <source>Getting Started...</source> + <translation>Commencer...</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="112"/> <source>... with GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>... avec GPGFrontend</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="114"/> - <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br></source> - <translation type="unfinished"></translation> + <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source> + <translation>Bienvenue à utiliser GPGFronTend pour le déchiffrement et la signature de texte ou de fichier!</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="123"/> + <location filename="../../src/ui/Wizard.cpp" line="116"/> + <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source> + <translation>est une puissante, facile à utiliser, compacte, plate-forme multiplate-forme et sans installation.</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="117"/> + <source>For brief information have a look at the</source> + <translation>Pour de brèves informations, regardez le</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="118"/> + <source>Overview</source> + <translation>Aperçu</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="119"/> + <source>by clicking the link, the page will open in the web browser</source> + <translation>En cliquant sur le lien, la page s'ouvrira dans le navigateur Web.</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="127"/> <source>Choose a Language</source> - <translation type="unfinished"></translation> + <translation>Choisissez une langue</translation> </message> </context> <context> @@ -614,22 +637,22 @@ <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/> <source>KeyPair</source> - <translation type="unfinished"></translation> + <translation>Clavier</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/> <source>UIDs</source> - <translation type="unfinished"></translation> + <translation>Uids</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/> <source>Subkeys</source> - <translation type="unfinished"></translation> + <translation>Souske</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/> <source>Key Details</source> - <translation type="unfinished"></translation> + <translation>Détails clés</translation> </message> </context> <context> @@ -637,150 +660,159 @@ <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/> <source>Generate Key</source> - <translation type="unfinished"></translation> + <translation>Générer une clé</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation>Le nom doit contenir au moins cinq caractères.</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation>S'il vous plaît donner une adresse email.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/> - <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/> + <source> Expiration time no more than 2 years. +</source> + <translation>Heure d'expiration Pas plus de 2 ans.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/> <source>Generating Key...</source> - <translation type="unfinished"></translation> + <translation>Clé génératrice ...</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/> <source>Collecting random data for key generation. This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation>Collecte de données aléatoires pour la génération de clé. + Cela peut prendre un peu de temps. + Pour accélérer le processus, utilisez votre ordinateur + (E.G. Parcourir le Net, écoutez de la musique, ...)</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/> + <source>Key Usage</source> + <translation>Usage de clé</translation> + </message> + <message> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation>Chiffrement</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation>Signature</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation>Certification</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation>Authentification</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation>Succès</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>The new key pair has been generated.</source> - <translation type="unfinished"></translation> + <translation>La nouvelle paire de clés a été générée.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation>Échec</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>An error occurred during key generation.</source> - <translation type="unfinished"></translation> + <translation>Une erreur s'est produite lors de la génération de clé.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation>Nom:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation>Adresse e-mail:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation>Commenter:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation>Date d'expiration:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation>Keysize (dans le bit):</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation>Type de clé:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> <source>Non Pass Phrase</source> - <translation type="unfinished"></translation> + <translation>Non Pass Phrase</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation>Informations de base</translation> </message> </context> <context> <name>KeyGenPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="356"/> + <location filename="../../src/ui/Wizard.cpp" line="366"/> <source>Create a keypair...</source> - <translation type="unfinished"></translation> + <translation>Créer un keypair ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="357"/> + <location filename="../../src/ui/Wizard.cpp" line="367"/> <source>...for decrypting and signing messages</source> - <translation type="unfinished"></translation> + <translation>... pour décrypter et signature des messages</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="358"/> + <location filename="../../src/ui/Wizard.cpp" line="368"/> <source>You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window):</source> - <translation type="unfinished"></translation> + <translation>Vous devriez créer un nouveau keypair.La Paire consiste en une clé publique et privée. <br> Les autres utilisateurs peuvent utiliser la clé publique pour chiffrer les messages pour vous et vérifier les messages signés par vous.Vous pouvez utiliser la clé privée pour déchiffrer et signerMessages. <br> Pour plus d'informations, consultez le tutoriel hors ligne (qui est ensuite affiché dans la fenêtre principale):</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="365"/> + <location filename="../../src/ui/Wizard.cpp" line="375"/> <source>Offline tutorial</source> - <translation type="unfinished"></translation> + <translation>Tutoriel hors ligne</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="372"/> + <location filename="../../src/ui/Wizard.cpp" line="382"/> <source>Create New Key</source> - <translation type="unfinished"></translation> + <translation>Créer une nouvelle clé</translation> </message> </context> <context> @@ -789,83 +821,83 @@ <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/> <source>Key Update Details</source> - <translation type="unfinished"></translation> + <translation>Détails de la mise à jour clés</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <source>No keys found</source> - <translation type="unfinished"></translation> + <translation>Pas de clés trouvées</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/> <source>Key Import Details</source> - <translation type="unfinished"></translation> + <translation>Détails des importations clés</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <source>No keys found to import</source> - <translation type="unfinished"></translation> + <translation>Aucune clé trouvée à l'importation</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/> <source>General key info</source> - <translation type="unfinished"></translation> + <translation>Info général de la clé</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/> <source>Considered:</source> - <translation type="unfinished"></translation> + <translation>Pris en considération:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/> <source>Public unchanged:</source> - <translation type="unfinished"></translation> + <translation>Public inchangé:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/> <source>Imported:</source> - <translation type="unfinished"></translation> + <translation>Importé:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/> <source>Not imported:</source> - <translation type="unfinished"></translation> + <translation>Non importé:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/> <source>Private read:</source> - <translation type="unfinished"></translation> + <translation>Lire privée:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/> <source>Private imported:</source> - <translation type="unfinished"></translation> + <translation>Privé importé:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/> <source>Private unchanged:</source> - <translation type="unfinished"></translation> + <translation>Privé inchangé:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Nom</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>E-mail</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Status</source> - <translation type="unfinished"></translation> + <translation>Statut</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation>Empreinte digitale</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/> @@ -885,22 +917,22 @@ <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/> <source>new key</source> - <translation type="unfinished"></translation> + <translation>nouvelle clé</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/> <source>new subkey</source> - <translation type="unfinished"></translation> + <translation>Nouvelle sous-clé</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/> <source>new signature</source> - <translation type="unfinished"></translation> + <translation>nouvelle signature</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/> <source>new uid</source> - <translation type="unfinished"></translation> + <translation>Nouveau UID</translation> </message> </context> <context> @@ -908,66 +940,67 @@ <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>Sélectionner</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Type</source> - <translation type="unfinished"></translation> + <translation>Taper</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Nom</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Email Address</source> - <translation type="unfinished"></translation> + <translation>Adresse e-mail</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Usage</source> - <translation type="unfinished"></translation> + <translation>Usage</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Validity</source> - <translation type="unfinished"></translation> + <translation>Validité</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Finger Print</source> - <translation type="unfinished"></translation> + <translation>Empreinte digitale</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> <source>Import Keys</source> - <translation type="unfinished"></translation> + <translation>Clés d'importation</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/> <source>You've dropped something on the table. GpgFrontend will now try to import key(s).</source> - <translation type="unfinished"></translation> + <translation>Vous avez laissé tomber quelque chose sur la table. + GPGFronTend va maintenant essayer d'importer des clés (s).</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/> <source>Always import without bothering.</source> - <translation type="unfinished"></translation> + <translation>Toujours importer sans déranger.</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/> <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <translation>Impossible d'ouvrir le fichier:</translation> </message> </context> <context> <name>KeyMgmt</name> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="81"/> - <source>KeyPairs Management</source> - <translation type="unfinished"></translation> + <source>Key Pair Management</source> + <translation>Gestion des paires de clés</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="88"/> @@ -977,240 +1010,240 @@ <message> <location filename="../../src/ui/KeyMgmt.cpp" line="89"/> <source>Ctrl+O</source> - <translation type="unfinished"></translation> + <translation>Ctrl + o</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="90"/> <source>Open Key File</source> - <translation type="unfinished"></translation> + <translation>Ouvrir le fichier de clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="93"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&Fermer</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="94"/> <source>Ctrl+Q</source> - <translation type="unfinished"></translation> + <translation>Ctrl + q</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="96"/> <source>Close</source> - <translation type="unfinished"></translation> + <translation>Fermer</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="99"/> <source>New Keypair</source> - <translation type="unfinished"></translation> + <translation>Nouveau keypair</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="100"/> <source>Ctrl+N</source> - <translation type="unfinished"></translation> + <translation>Ctrl + n</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="102"/> <source>Generate KeyPair</source> - <translation type="unfinished"></translation> + <translation>Générer une paire de clés</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="105"/> <source>New Subkey</source> - <translation type="unfinished"></translation> + <translation>Nouvelle sous-clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="106"/> <source>Ctrl+Shift+N</source> - <translation type="unfinished"></translation> + <translation>Ctrl + Maj + n</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="108"/> <source>Generate Subkey For Selected KeyPair</source> - <translation type="unfinished"></translation> + <translation>Générer de sous-clé pour sélectionner le clavier sélectionné</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="111"/> <location filename="../../src/ui/KeyMgmt.cpp" line="152"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation>&Déposer</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="113"/> <source>Import New Key From File</source> - <translation type="unfinished"></translation> + <translation>Importer une nouvelle clé à partir de fichier</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="116"/> <source>&Clipboard</source> - <translation type="unfinished"></translation> + <translation>& Presse-papiers</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="118"/> <source>Import New Key From Clipboard</source> - <translation type="unfinished"></translation> + <translation>Importer une nouvelle clé de Presse-papiers</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="121"/> <source>&Keyserver</source> - <translation type="unfinished"></translation> + <translation>& Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="123"/> <source>Import New Key From Keyserver</source> - <translation type="unfinished"></translation> + <translation>Importer une nouvelle clé de Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="126"/> <source>Export To &Clipboard</source> - <translation type="unfinished"></translation> + <translation>Exporter vers le presse-papier</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="128"/> <source>Export Selected Key(s) To Clipboard</source> - <translation type="unfinished"></translation> + <translation>Exporter des touches sélectionnées dans le presse-papier</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="131"/> <source>Export To &File</source> - <translation type="unfinished"></translation> + <translation>Exporter vers & Fichier</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="133"/> <source>Export Selected Key(s) To File</source> - <translation type="unfinished"></translation> + <translation>Exporter la ou les touches sélectionnées dans le fichier</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="136"/> <source>Delete Selected Key(s)</source> - <translation type="unfinished"></translation> + <translation>Supprimer la ou les touches sélectionnées</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="137"/> <source>Delete the Selected keys</source> - <translation type="unfinished"></translation> + <translation>Supprimer les touches sélectionnées</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="140"/> <source>Delete Checked Key(s)</source> - <translation type="unfinished"></translation> + <translation>Supprimer les touches vérifiées</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="141"/> <source>Delete the Checked keys</source> - <translation type="unfinished"></translation> + <translation>Supprimer les clés cochées</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="145"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation>Afficher les détails de la clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="146"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation>Afficher les détails de cette clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="156"/> <source>&Key</source> - <translation type="unfinished"></translation> + <translation>&Clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="157"/> <source>&Generate Key</source> - <translation type="unfinished"></translation> + <translation>Générer une clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="161"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation>Clé d'importation</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="173"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>Clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="181"/> <source>Generate</source> - <translation type="unfinished"></translation> + <translation>produire</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="182"/> <source>Generate A New Keypair or Subkey</source> - <translation type="unfinished"></translation> + <translation>Générer un nouveau clavier ou une nouvelle sous-clé</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="191"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation>Clé d'importation</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="192"/> <source>Import Key</source> - <translation type="unfinished"></translation> + <translation>Clé d'importation</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Open Key</source> - <translation type="unfinished"></translation> + <translation>Touche ouverte</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation>Fichiers clés</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Keyring files</source> - <translation type="unfinished"></translation> + <translation>Fichiers de porte-clés</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="218"/> <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <translation>Impossible d'ouvrir le fichier:</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="268"/> <source>Deleting Keys</source> - <translation type="unfinished"></translation> + <translation>Suppression des clés</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="269"/> <source>Are you sure that you want to delete the following keys?</source> - <translation type="unfinished"></translation> + <translation>Êtes-vous sûr de vouloir supprimer les clés suivantes?</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="270"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation>L'action ne peut pas être annulée.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation>Exporter la clé pour déposer</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="309"/> <source>key(s) exported</source> - <translation type="unfinished"></translation> + <translation>clé (s) exportée (s)</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="338"/> <location filename="../../src/ui/KeyMgmt.cpp" line="345"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>Opération invalide</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="339"/> <source>Please select one KeyPair before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Veuillez sélectionner un clavier avant de faire cette opération.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="346"/> <source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source> - <translation type="unfinished"></translation> + <translation>Si une paire de clés n'a pas de clé privée, elle ne pourra pas générer des sous-clés.</translation> </message> </context> <context> @@ -1218,198 +1251,237 @@ <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Nom</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>E-mail</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>Commenter</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/> <source>Create New UID</source> - <translation type="unfinished"></translation> + <translation>Créer de nouveaux uid</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation>Le nom doit contenir au moins cinq caractères.</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation>S'il vous plaît donner une adresse email.</translation> </message> </context> <context> <name>KeyPairDetailTab</name> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> <source>Owner</source> - <translation type="unfinished"></translation> + <translation>Propriétaire</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> <source>Master Key</source> - <translation type="unfinished"></translation> + <translation>La clef maitresse</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation>Empreinte digitale</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/> <source>Additional UIDs</source> - <translation type="unfinished"></translation> + <translation>UID supplémentaires</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Exists</source> + <translation>Existe</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Not Exists</source> + <translation>N'existe pas</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation>Nom:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation>Adresse e-mail:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation>Commenter:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation>ID de clé:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation>Algorithme:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation>Taille de la clé:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> <source>Nominal Usage: </source> - <translation type="unfinished"></translation> + <translation>Utilisation nominale:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> <source>Actual Usage: </source> - <translation type="unfinished"></translation> + <translation>Utilisation réelle:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> <source>Expires on: </source> - <translation type="unfinished"></translation> + <translation>Expire le:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation>Dernière mise à jour:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/> <source>Secret Key Existence: </source> - <translation type="unfinished"></translation> + <translation>Existence de clé secrète:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> <source>Copy</source> - <translation type="unfinished"></translation> + <translation>Copie</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/> <source>copy fingerprint to clipboard</source> - <translation type="unfinished"></translation> + <translation>Copier l'empreinte digitale dans le presse-papier</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/> <source>Operations</source> - <translation type="unfinished"></translation> + <translation>Exploitation</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/> - <source>Export Private Key (Include Subkeys)</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/> + <source>Export Private Key (Include Subkey)</source> + <translation>Exporter une clé privée (inclure la sous-clé)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/> <source>Modify Expiration Datetime (Master Key)</source> - <translation type="unfinished"></translation> + <translation>Modifier l'expiration DateTime (clé principale)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/> <source>Key Server Operation (Pubkey)</source> - <translation type="unfinished"></translation> + <translation>Fonctionnement du serveur clé (Pubkey)</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/> + <source>Generate Revoke Certificate</source> + <translation>Générer un certificat de révocation</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/> <source>Warning: The Master Key has expired.</source> - <translation type="unfinished"></translation> + <translation>AVERTISSEMENT: la clé principale a expiré.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/> <source>Warning: The Master Key has been revoked</source> - <translation type="unfinished"></translation> + <translation>AVERTISSEMENT: la clé principale a été révoquée</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/> <source>Exporting private Key</source> - <translation type="unfinished"></translation> + <translation>Exportation de la clé privée</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/> - <source><h3>You are about to export your <font color="red">PRIVATE KEY</font>!</h3> -This is NOT your Public Key, so DON'T give it away.<br />Do you REALLY want to export your PRIVATE KEY?</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/> + <source>You are about to export your</source> + <translation>Vous êtes sur le point d'exporter votre</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/> + <source>PRIVATE KEY</source> + <translation>CLÉ PRIVÉE</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/> + <source>This is NOT your Public Key, so DON'T give it away.</source> + <translation>Ce n'est pas votre clé publique, alors ne le donnez pas.</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/> + <source>Do you REALLY want to export your PRIVATE KEY?</source> + <translation>Voulez-vous vraiment exporter votre clé privée?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation>Exporter la clé pour déposer</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation>Fichiers clés</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Export Error</source> - <translation type="unfinished"></translation> + <translation>Erreur d'exportation</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Couldn't open %1 for writing</source> - <translation type="unfinished"></translation> + <translation>Ne pouvait pas ouvrir% 1 pour écrire</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/> - <source>Upload Key Pair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/> + <source>Upload Key Pair to Key Server</source> + <translation>Télécharger la paire de touches sur le serveur de clés</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/> <source>Update Key Pair</source> - <translation type="unfinished"></translation> + <translation>Mettre à jour la paire de clés</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/> + <source>Generate revocation certificate</source> + <translation>Générer un certificat de révocation</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/> + <source>Revocation Certificates</source> + <translation>Certificats de révocation</translation> </message> </context> <context> @@ -1417,87 +1489,87 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/> <source>Generate A New Subkey</source> - <translation type="unfinished"></translation> + <translation>Générer une nouvelle sous-clé</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation>ID de clé:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation>Algorithme:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation>Taille de la clé:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> <source>Usage: </source> - <translation type="unfinished"></translation> + <translation>Usage:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> <source>Expires On </source> - <translation type="unfinished"></translation> + <translation>Expire le</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation>Dernière mise à jour:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> <source>Existence: </source> - <translation type="unfinished"></translation> + <translation>Existence:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation>Empreinte digitale:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Subkey ID</source> - <translation type="unfinished"></translation> + <translation>Adresse de sous-clé</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Key Size</source> - <translation type="unfinished"></translation> + <translation>Taille de clé</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Algo</source> - <translation type="unfinished"></translation> + <translation>Quelque chose</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation>créer un rendez-vous</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation>Date d'expiration</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/> <source>Edit Expire Date</source> - <translation type="unfinished"></translation> + <translation>Modifier la date d'expire</translation> </message> </context> <context> @@ -1505,192 +1577,202 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/> <source>New UID</source> - <translation type="unfinished"></translation> + <translation>Nouveau UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/> <source>UID Management</source> - <translation type="unfinished"></translation> + <translation>Gestion UID</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/> + <source>UIDs</source> + <translation>Uids</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/> + <source>Signature of Selected UID</source> + <translation>Signature de l'UID sélectionné</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>Sélectionner</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Nom</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>E-mail</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>Commenter</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Key ID</source> - <translation type="unfinished"></translation> + <translation>Identifiant de clé</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation>créer un rendez-vous</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Expired Date</source> - <translation type="unfinished"></translation> + <translation>Date d'expiration</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>Opération invalide</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/> <source>Please select one or more UIDs before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Veuillez sélectionner un ou plusieurs UID avant de faire cette opération.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/> <source>Sign Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation>Signer des UID sélectionnés</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/> <source>Delete Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation>Supprimer l'UID sélectionné (s) sélectionné (s)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/> <source>Successful Operation</source> - <translation type="unfinished"></translation> + <translation>Exploitation réussie</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> <source>Successfully added a new UID.</source> - <translation type="unfinished"></translation> + <translation>A ajouté avec succès une nouvelle UID.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation>L'opération a échoué</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation>Une erreur s'est produite lors de l'opération.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/> <source>Deleting UIDs</source> - <translation type="unfinished"></translation> + <translation>Suppression des UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/> <source>Are you sure that you want to delete the following uids?</source> - <translation type="unfinished"></translation> + <translation>Êtes-vous sûr de vouloir supprimer les UID suivants?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation>L'action ne peut pas être annulée.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/> <source>Set Primary UID</source> - <translation type="unfinished"></translation> + <translation>Définir UID primaire</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/> <source>Are you sure that you want to set the Primary UID to?</source> - <translation type="unfinished"></translation> + <translation>Êtes-vous sûr de vouloir définir l'UID principal?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/> <source>Set As Primary</source> - <translation type="unfinished"></translation> + <translation>Définir comme principale</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/> <source>Sign UID</source> - <translation type="unfinished"></translation> + <translation>Signer uid</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/> <source>Delete UID</source> - <translation type="unfinished"></translation> + <translation>Supprimer UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/> <source>Please select one UID before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Veuillez sélectionner un UID avant de faire cette opération.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/> <source>Deleting UID</source> - <translation type="unfinished"></translation> + <translation>Supprimer UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/> <source>Are you sure that you want to delete the following uid?</source> - <translation type="unfinished"></translation> + <translation>Êtes-vous sûr de vouloir supprimer l'UID suivant?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/> <source>Delete(Revoke) Key Signature</source> - <translation type="unfinished"></translation> + <translation>Supprimer (révoquer) la signature de clé</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/> <source>Please select one Key Signature before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Veuillez sélectionner une signature de clé avant de faire cette opération.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/> <source>To delete the signature, you need to have its corresponding public key in the local database.</source> - <translation type="unfinished"></translation> + <translation>Pour supprimer la signature, vous devez avoir sa clé publique correspondante dans la base de données locale.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/> <source>Deleting Key Signature</source> - <translation type="unfinished"></translation> + <translation>Suppression de la signature de clé</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/> <source>Are you sure that you want to delete the following signature?</source> - <translation type="unfinished"></translation> + <translation>Êtes-vous sûr de vouloir supprimer la signature suivante?</translation> </message> </context> <context> @@ -1698,110 +1780,110 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&Fermer</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/> <source>&Import ALL</source> - <translation type="unfinished"></translation> + <translation>& Importer tout</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/> <source>&Search</source> - <translation type="unfinished"></translation> + <translation>&Rechercher</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/> <source>Search String:</source> - <translation type="unfinished"></translation> + <translation>String de recherche:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/> <source>Key Server:</source> - <translation type="unfinished"></translation> + <translation>Serveur clé:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/> <source>Update Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Mettre à jour les clés de Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/> <source>Import Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Keys d'importation de KeyServer</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>UID</source> - <translation type="unfinished"></translation> + <translation>Uid</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Creation date</source> - <translation type="unfinished"></translation> + <translation>Date de création</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>KeyID</source> - <translation type="unfinished"></translation> + <translation>Clés</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Tag</source> - <translation type="unfinished"></translation> + <translation>Étiqueter</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/> - <source><h4>Text is empty.</h4></source> - <translation type="unfinished"></translation> + <source>Text is empty.</source> + <translation>Le texte est vide.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/> <source>Not Key Found</source> - <translation type="unfinished"></translation> + <translation>Pas la clé trouvée</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation>Temps libre</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation>Server clé non trouvé</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation>Erreur de connexion</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> - <source><h4>CToo many responses from keyserver!</h4></source> - <translation type="unfinished"></translation> + <source>Too many responses from keyserver!</source> + <translation>Trop de réponses de KeyServer!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> - <source><h4>No keys found, input may be kexId, retrying search with 0x.</h4></source> - <translation type="unfinished"></translation> + <source>No keys found, input may be kexId, retrying search with 0x.</source> + <translation>Aucune clé trouvée, l'entrée peut être Kexid, réessayant la recherche avec 0x.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> - <source><h4>No keys found containing the search string!</h4></source> - <translation type="unfinished"></translation> + <source>No keys found containing the search string!</source> + <translation>Aucun clés trouvée contenant la chaîne de recherche!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> - <source><h4>Insufficiently specific search string!</h4></source> - <translation type="unfinished"></translation> + <source>Insufficiently specific search string!</source> + <translation>String de recherche insuffisamment spécifique!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/> <source>revoked</source> - <translation type="unfinished"></translation> + <translation>révoqué</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/> @@ -1811,27 +1893,27 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/> <source><h4>%1 keys found. Double click a key to import it.</h4></source> - <translation type="unfinished"></translation> + <translation><H4>% 1 clés trouvées.Double-cliquez sur une touche pour importer. </ H4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation>Clé introuvable</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/> <source><h4>Key Updated</h4></source> - <translation type="unfinished"></translation> + <translation><H4> Touche Mise à jour </ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/> <source><h4>Key Imported</h4></source> - <translation type="unfinished"></translation> + <translation><H4> Touche importée </ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/> <source>Upload Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Touches de téléchargement de KeyServer</translation> </message> </context> <context> @@ -1839,22 +1921,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/> <source>Confirm</source> - <translation type="unfinished"></translation> + <translation>Confirmer</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation>L'opération a échoué</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation>Une erreur s'est produite lors de l'opération.</translation> </message> </context> <context> @@ -1862,263 +1944,351 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation>Date d'expiration</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/> <source>Sign For Key's UID(s)</source> - <translation type="unfinished"></translation> + <translation>Signe pour UID (s) de la clé</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/> <source>Unsuccessful Operation</source> - <translation type="unfinished"></translation> + <translation>Opération infructueuse</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/> <source>Signature operation failed for UID </source> - <translation type="unfinished"></translation> + <translation>L'opération de signature a échoué pour UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/> <source>Operation Complete</source> - <translation type="unfinished"></translation> + <translation>Opération complète</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/> <source>The signature operation of the UID is complete</source> - <translation type="unfinished"></translation> + <translation>L'opération de signature de l'UID est complète</translation> </message> </context> <context> <name>KeyUploadDialog</name> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/> <source>Uploading Public Key</source> - <translation type="unfinished"></translation> + <translation>Téléchargement de clé publique</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation>Clé introuvable</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation>Temps libre</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation>Server clé non trouvé</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation>Erreur de connexion</translation> </message> </context> <context> <name>KeyserverTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="508"/> - <source>Default Keyserver for import:</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="607"/> + <source>Default Key Server for import:</source> + <translation>Server de clé par défaut pour importer:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="525"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="624"/> <source>Add</source> - <translation type="unfinished"></translation> + <translation>Ajouter</translation> </message> </context> <context> <name>MainWindow</name> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/> + <location filename="../../src/MainWindow.cpp" line="35"/> + <source>Loading Gnupg</source> + <translation>Chargement gnupg</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="62"/> + <source>ENV Loading Failed</source> + <translation>Échec du chargement env</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="63"/> + <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> + <translation>GNUPG n'est pas installé correctement, veuillez suivre les instructions README pour installer GNUPG, puis ouvrir GPGFontend.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/> <source>No Key Selected</source> - <translation type="unfinished"></translation> + <translation>Aucune clé sélectionnée</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>Opération invalide</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/> <source>The selected key contains a key that does not actually have a encrypt usage.<br/></source> - <translation type="unfinished"></translation> + <translation>La clé sélectionnée contient une clé qui ne dispose pas d'une utilisation en chiffrement. <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/> + <source><br/>For example the Following Key: <br/></source> + <translation><br/> Par exemple, la clé suivante: <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/> + <source>Encrypting</source> + <translation>Cryptage</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/> + <source>Function Disabled</source> + <translation>Fonction désactivée</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/> + <source>Please go to the settings interface to enable and configure this function.</source> + <translation>Veuillez vous rendre à l'interface des paramètres pour activer et configurer cette fonction.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/> <source>The selected key contains a key that does not actually have a signature usage.<br/></source> - <translation type="unfinished"></translation> + <translation>La clé sélectionnée contient une clé qui ne dispose pas d'une utilisation de signature. <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/> + <source>Signing</source> + <translation>Signature</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/> + <source>Decrypting</source> + <translation>Décalage</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/> + <source>Verifying</source> + <translation>Vérification</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/> <source>Invalid KeyPair</source> - <translation type="unfinished"></translation> + <translation>KeyPair non valide</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/> <source>The selected keypair cannot be used for signing and encryption at the same time.<br/></source> - <translation type="unfinished"></translation> + <translation>Le clavier sélectionné ne peut pas être utilisé pour la signature et le cryptage en même temps. <br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/> <source>Incomplete Operation</source> - <translation type="unfinished"></translation> + <translation>Opération incomplète</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/> <source>None of the selected key pairs can provide the encryption function.</source> - <translation type="unfinished"></translation> + <translation>Aucune des paires de touches sélectionnées ne peut fournir la fonction de cryptage.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/> <source>None of the selected key pairs can provide the signature function.</source> - <translation type="unfinished"></translation> + <translation>Aucune des paires de touches sélectionnées ne peut fournir la fonction de signature.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/> + <source>Encrypting and Signing</source> + <translation>Cryptage et signature</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/> + <source>Decrypting and Verifying</source> + <translation>Décrypter et vérifier</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation>Erreur</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <source>Select a file before doing it.</source> + <translation>Sélectionnez un fichier avant de le faire.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> <source>No permission to read this file.</source> - <translation type="unfinished"></translation> + <translation>Aucune autorisation de lire ce fichier.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> <source>No permission to create file.</source> - <translation type="unfinished"></translation> + <translation>Aucune autorisation de créer un fichier.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>Avertissement</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/> <source>The target file already exists, do you need to overwrite it?</source> - <translation type="unfinished"></translation> + <translation>Le fichier cible existe déjà, devez-vous vous écraser?</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>An error occurred during operation.</source> - <translation type="unfinished"></translation> + <translation>Une erreur s'est produite lors du fonctionnement.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/> <source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source> - <translation type="unfinished"></translation> + <translation>Veuillez sélectionner le fichier cible ou le fichier de signature approprié.Assurez-vous que les deux sont dans ce répertoire.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> <source>No permission to read target file.</source> - <translation type="unfinished"></translation> + <translation>Aucune autorisation de lire le fichier cible.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> <source>No permission to read signature file.</source> - <translation type="unfinished"></translation> + <translation>Aucune autorisation de lire le fichier de signature.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> <source>Select a file(.gpg/.asc) before doing it.</source> - <translation type="unfinished"></translation> + <translation>Sélectionnez un fichier (.gpg / .asc) avant de le faire.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/> - <source><br/>For example the Following Key: <br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/> + <source>Outdated Version</source> + <translation>Version obsolète</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> - <source>Select a file before doing it.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/> + <source>This version(%1) is out of date, please update the latest version in time. </source> + <translation>Cette version (% 1) est obsolète, veuillez mettre à jour la dernière version à temps.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/> + <source>You can download the latest version(%1) on Github Releases Page.<br/></source> + <translation>Vous pouvez télécharger la dernière version (% 1) sur la page Communiqués GitHub. <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/> + <source>Unreleased Version</source> + <translation>Version non sélectionnée</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/> + <source>This version(%1) has not been officially released and is not recommended for use in a production environment. <br/></source> + <translation>Cette version (% 1) n'a pas été officiellement libérée et n'est pas recommandée pour une utilisation dans un environnement de production.<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/> <source>There is one unencrypted file in attachment folder</source> - <translation type="unfinished"></translation> + <translation>Il y a un fichier non crypté dans le dossier de pièce jointe</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source>There are </source> - <translation type="unfinished"></translation> + <translation>Il y a</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source> unencrypted files in attachment folder</source> - <translation type="unfinished"></translation> + <translation>Fichiers non cryptés dans le dossier de pièce jointe</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/> @@ -2128,7 +2298,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/> <source>Open a new file</source> - <translation type="unfinished"></translation> + <translation>Ouvrir un nouveau fichier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/> @@ -2138,277 +2308,277 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/> <source>Open an existing file</source> - <translation type="unfinished"></translation> + <translation>Ouvrir un fichier existant</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/> <source>&Browser</source> - <translation type="unfinished"></translation> + <translation>&Le navigateur</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/> <source>Open a file browser</source> - <translation type="unfinished"></translation> + <translation>Ouvrez un navigateur de fichiers</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/> <source>&Save</source> - <translation type="unfinished"></translation> + <translation>&Sauvegarder</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/> <source>Save the current File</source> - <translation type="unfinished"></translation> + <translation>Enregistrez le fichier actuel</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/> <source>Save &As</source> - <translation type="unfinished"></translation> + <translation>Enregistrer sous</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/> <source>Save the current File as...</source> - <translation type="unfinished"></translation> + <translation>Enregistrez le fichier actuel comme ...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/> <source>&Print</source> - <translation type="unfinished"></translation> + <translation>&Imprimer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/> <source>Print Document</source> - <translation type="unfinished"></translation> + <translation>Document d'impression</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&Fermer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/> <source>Close file</source> - <translation type="unfinished"></translation> + <translation>Fermer le fichier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/> <source>&Quit</source> - <translation type="unfinished"></translation> + <translation>&Quitter</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/> <source>Quit Program</source> - <translation type="unfinished"></translation> + <translation>Quitter le programme</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/> <source>&Undo</source> - <translation type="unfinished"></translation> + <translation>&Annuler</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/> <source>Undo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation>Annuler la dernière action d'édition</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/> <source>&Redo</source> - <translation type="unfinished"></translation> + <translation>&Prêt</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/> <source>Redo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation>Refaire dernière action d'édition</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/> <source>Zoom In</source> - <translation type="unfinished"></translation> + <translation>Agrandir</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/> <source>Zoom Out</source> - <translation type="unfinished"></translation> + <translation>Dézoomer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/> <source>&Paste</source> - <translation type="unfinished"></translation> + <translation>&Pâte</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/> <source>Paste Text From Clipboard</source> - <translation type="unfinished"></translation> + <translation>Coller le texte du presse-papiers</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/> <source>Cu&t</source> - <translation type="unfinished"></translation> + <translation>Avec & T.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/> <source>Cut the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <translation>Couper le contenu de la sélection actuelle dans le presse-papiers</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/> <source>&Copy</source> - <translation type="unfinished"></translation> + <translation>&Copie</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/> <source>Copy the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <translation>Copiez le contenu de la sélection actuelle dans le Presse-papiers</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/> <source>&Quote</source> - <translation type="unfinished"></translation> + <translation>"</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/> <source>Quote whole text</source> - <translation type="unfinished"></translation> + <translation>Citer du texte entier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/> <source>Select &All</source> - <translation type="unfinished"></translation> + <translation>Tout sélectionner</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/> <source>Select the whole text</source> - <translation type="unfinished"></translation> + <translation>Sélectionnez le texte entier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/> <source>&Find</source> - <translation type="unfinished"></translation> + <translation>&Trouve</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/> <source>Find a word</source> - <translation type="unfinished"></translation> + <translation>Trouver un mot</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/> <source>Remove &spacing</source> - <translation type="unfinished"></translation> + <translation>Supprimer et espacer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/> <source>Remove double linebreaks, e.g. in pasted text from webmailer</source> - <translation type="unfinished"></translation> + <translation>Supprimer Double Ligneurs, par exemple.dans le texte collé de webmailer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/> <source>Se&ttings</source> - <translation type="unfinished"></translation> + <translation>Et tuttine</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/> <source>Open settings dialog</source> - <translation type="unfinished"></translation> + <translation>Dialogue des paramètres ouverts</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/> <source>&Encrypt</source> - <translation type="unfinished"></translation> + <translation>&Crypter</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/> <source>Encrypt Message</source> - <translation type="unfinished"></translation> + <translation>Chiffrer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/> <source>&Encrypt &Sign</source> - <translation type="unfinished"></translation> + <translation>& Chiffrer et signer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/> <source>Encrypt and Sign Message</source> - <translation type="unfinished"></translation> + <translation>Message de chiffrement et de signe</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/> <source>&Decrypt</source> - <translation type="unfinished"></translation> + <translation>& Déchiffrer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/> <source>Decrypt Message</source> - <translation type="unfinished"></translation> + <translation>Decrypt Message</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/> <source>&Decrypt &Verify</source> - <translation type="unfinished"></translation> + <translation>& Déchiffrer et vérifier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/> <source>Decrypt and Verify Message</source> - <translation type="unfinished"></translation> + <translation>Déchiffrer et vérifier le message</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/> <source>&Encrypt File</source> - <translation type="unfinished"></translation> + <translation>Chiffrer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation>Chiffrer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/> <source>&Decrypt File</source> - <translation type="unfinished"></translation> + <translation>Dossier de déchiffrement</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation>Dossier de déchiffrement</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/> <source>&Sign File</source> - <translation type="unfinished"></translation> + <translation>Et signe de signe</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation>Fichier de signe</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/> <source>&Verify File</source> - <translation type="unfinished"></translation> + <translation>Vérifier le fichier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation>Vérifier le fichier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/> <source>&Sign</source> - <translation type="unfinished"></translation> + <translation>&Signe</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/> <source>Sign Message</source> - <translation type="unfinished"></translation> + <translation>Message de signe</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/> <source>&Verify</source> - <translation type="unfinished"></translation> + <translation>&Vérifier</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/> <source>Verify Message</source> - <translation type="unfinished"></translation> + <translation>Vérifier le message</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/> @@ -2418,245 +2588,212 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/> <source>Import New Key From Editor</source> - <translation type="unfinished"></translation> + <translation>Importer une nouvelle clé de l'éditeur</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/> - <source>Manage &keys</source> - <translation type="unfinished"></translation> + <source>Manage &Keys</source> + <translation>Gérer et les clés</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/> <source>Open Keymanagement</source> - <translation type="unfinished"></translation> + <translation>Clés ouverte</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/> <source>&About</source> - <translation type="unfinished"></translation> + <translation>&À propos</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/> <source>Show the application's About box</source> - <translation type="unfinished"></translation> + <translation>Montrer l'application à propos de la boîte</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/> + <source>&Check for Updates</source> + <translation>Vérifier les mises à jour</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <source>Check for updates</source> + <translation>Vérifier les mises à jour</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/> <source>Open &Wizard</source> - <translation type="unfinished"></translation> + <translation>Open & Wizard</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> <source>Open the wizard</source> - <translation type="unfinished"></translation> + <translation>Ouvrir l'assistant</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> <source>Append Selected Key(s) To Text</source> - <translation type="unfinished"></translation> + <translation>Ajoutez la ou les touches sélectionnées sur le texte</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> <source>Append The Selected Keys To Text in Editor</source> - <translation type="unfinished"></translation> + <translation>Ajouter les touches sélectionnées sur Text In Editor</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> - <source>Copy EMail-address</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <source>Copy Email</source> + <translation>Copier le courrier électronique</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/> - <source>Copy selected EMailaddress to clipboard</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <source>Copy selected Email to clipboard</source> + <translation>Copier le courrier électronique sélectionné dans le presse-papiers</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation>Afficher les détails de la clé</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation>Afficher les détails de cette clé</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/> <source>Refresh Key From Key Server</source> - <translation type="unfinished"></translation> + <translation>Actualiser la clé de Key Server</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/> <source>Refresh key from default key server</source> - <translation type="unfinished"></translation> + <translation>Actualiser la clé à partir du serveur de clés par défaut</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/> <source>Upload Public Key(s) To Server</source> - <translation type="unfinished"></translation> + <translation>Télécharger des touches publiques sur le serveur</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/> <source>Upload The Selected Public Keys To Server</source> - <translation type="unfinished"></translation> + <translation>Téléchargez les touches publiques sélectionnées sur le serveur</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/> <source>Remove PGP Header</source> - <translation type="unfinished"></translation> + <translation>Supprimer l'en-tête PGP</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/> <source>Add PGP Header</source> - <translation type="unfinished"></translation> + <translation>Ajouter l'en-tête PGP</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation>&Déposer</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/> <source>&Edit</source> - <translation type="unfinished"></translation> + <translation>&Éditer</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/> <source>&File...</source> - <translation type="unfinished"></translation> + <translation>&Déposer...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/> <source>&Crypt</source> - <translation type="unfinished"></translation> + <translation>&Crypte</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> <source>&Keys</source> - <translation type="unfinished"></translation> + <translation>&Clés</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation>Clé d'importation</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/> <source>&Steganography</source> - <translation type="unfinished"></translation> + <translation>Stéganographie</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> <source>&View</source> - <translation type="unfinished"></translation> + <translation>&Vue</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/> <source>&Help</source> - <translation type="unfinished"></translation> + <translation>&Aider</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Déposer</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/> <source>Crypt</source> - <translation type="unfinished"></translation> + <translation>Crypte</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>Clé</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/> <source>Edit</source> - <translation type="unfinished"></translation> + <translation>Éditer</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/> <source>Special Edit</source> - <translation type="unfinished"></translation> + <translation>Édition spéciale</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/> <source>Import key from...</source> - <translation type="unfinished"></translation> + <translation>Importer la clé de ...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation>Clé d'importation</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/> <source>Browser to view and operate file</source> - <translation type="unfinished"></translation> + <translation>Navigateur pour voir et utiliser le fichier</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/> <source>Browser</source> - <translation type="unfinished"></translation> + <translation>Le navigateur</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/> <source>Ready</source> - <translation type="unfinished"></translation> + <translation>Prêt</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/> <source>Key ToolBox</source> - <translation type="unfinished"></translation> + <translation>Boîte à outils clé</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/> <source>Information Board</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>MimeTab</name> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> - <source>Decode quoted printable</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="292"/> - <source>Try to recognize quoted printable.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="296"/> - <source>Parse PGP/MIME (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="299"/> - <source>Try to split attachments from PGP-MIME ecrypted messages.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="304"/> - <source>Open with external application (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="306"/> - <source>Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> - <source>Enable opening with external applications.</source> - <translation type="unfinished"></translation> + <translation>Tableau d'information</translation> </message> </context> <context> @@ -2664,12 +2801,12 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/> <source>>Recipient: </source> - <translation type="unfinished"></translation> + <translation>> Destinataire:</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/> <source>One or More Bad Signatures.</source> - <translation type="unfinished"></translation> + <translation>Une ou plusieurs mauvaises signatures.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/> @@ -2679,92 +2816,92 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation>Bien</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation>Mal</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation>Expiré</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/> <source>Missing Key's </source> - <translation type="unfinished"></translation> + <translation>Touches manquantes</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/> <source>Revoked Key's </source> - <translation type="unfinished"></translation> + <translation>Touche révoquée</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/> <source>Expired Key's </source> - <translation type="unfinished"></translation> + <translation>Clé expirée</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/> <source>Missing CRL's </source> - <translation type="unfinished"></translation> + <translation>CRL manquant</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/> <source>Signature Fully Valid.</source> - <translation type="unfinished"></translation> + <translation>Signature entièrement valide.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/> <source>Signature NOT Fully Valid.</source> - <translation type="unfinished"></translation> + <translation>Signature non complète valide.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/> <source>Key is NOT present with ID 0x</source> - <translation type="unfinished"></translation> + <translation>La clé n'est pas présente avec ID 0x</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/> <source>A signature could NOT be verified due to a Missing Key </source> - <translation type="unfinished"></translation> + <translation>Une signature n'a pas pu être vérifiée en raison d'une clé manquante</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/> <source>A signature is valid but the key used to verify the signature has been revoked </source> - <translation type="unfinished"></translation> + <translation>Une signature est valide mais la clé utilisée pour vérifier la signature a été révoquée.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/> <source>A signature is valid but expired </source> - <translation type="unfinished"></translation> + <translation>Une signature est valide mais expirée</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/> <source>A signature is valid but the key used to verify the signature has expired. </source> - <translation type="unfinished"></translation> + <translation>Une signature est valide mais la clé utilisée pour vérifier la signature a expiré.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/> <source>There was some other error which prevented the signature verification. </source> - <translation type="unfinished"></translation> + <translation>Il y avait une autre erreur qui empêchait la vérification de la signature.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/> <source>Error for key with fingerprint </source> - <translation type="unfinished"></translation> + <translation>Erreur pour la clé avec empreinte digitale</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/> <source>Signed By: </source> - <translation type="unfinished"></translation> + <translation>Signé par:</translation> </message> </context> <context> @@ -2772,60 +2909,193 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/QuitDialog.cpp" line="29"/> <source>Unsaved Files</source> - <translation type="unfinished"></translation> + <translation>Fichiers non enregistrés</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="77"/> - <source><h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3></source> - <translation type="unfinished"></translation> + <source>%1 files contain unsaved information.<br/>Save the changes before closing?</source> + <translation>% 1 Les fichiers contiennent des informations non enregistrées. <br/> Enregistrez les modifications avant la fermeture?</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="88"/> <source>Check the files you want to save:</source> - <translation type="unfinished"></translation> + <translation>Vérifiez les fichiers que vous souhaitez enregistrer:</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="89"/> <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <translation><B> REMARQUE: </ B> Si vous ne enregistrez pas ces fichiers, toutes les modifications sont perdues. <br/></translation> + </message> +</context> +<context> + <name>SendMailDialog</name> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="35"/> + <source>Incomplete configuration</source> + <translation>Configuration incomplète</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="36"/> + <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source> + <translation>L'adresse SMTP est vide, veuillez vous rendre à l'interface de réglage pour compléter la configuration.</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="86"/> + <source> Recipient cannot be empty +</source> + <translation>Le destinataire ne peut pas être vide</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="91"/> + <source> One or more Recipient's Email Address is invalid +</source> + <translation>L'une ou plusieurs adresse électronique du destinataire est invalide</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="97"/> + <source> Sender cannot be empty +</source> + <translation>L'expéditeur ne peut pas être vide</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="99"/> + <source> Sender's Email Address is invalid +</source> + <translation>L'adresse email de l'expéditeur n'est pas valide</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail</source> + <translation>Échouer</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <source>Fail to Connect SMTP Server</source> + <translation>Omettre de connecter SMTP Server</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <source>Fail to Login into SMTP Server</source> + <translation>Omettre de vous connecter au serveur SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail to Send Mail to SMTP Server</source> + <translation>Omettre d'envoyer un courrier au serveur SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Success</source> + <translation>Succès</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Succeed in Sending Mail to SMTP Server</source> + <translation>Réussir à envoyer un courrier au serveur SMTP</translation> + </message> +</context> +<context> + <name>SendMailTab</name> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> + <source>Enable</source> + <translation>Activer</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="311"/> + <source>SMTP Address</source> + <translation>Adresse SMTP</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="313"/> + <source>Username</source> + <translation>Nom d'utilisateur</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> + <source>Password</source> + <translation>Mot de passe</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="317"/> + <source>Port</source> + <translation>Port</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="319"/> + <source>Connection Security</source> + <translation>Sécurité de la connexion</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="322"/> + <source>Default Sender</source> + <translation>Expéditeur par défaut</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail</source> + <translation>Échouer</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <source>Fail to Connect SMTP Server</source> + <translation>Omettre de connecter SMTP Server</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail to Login</source> + <translation>Échouer à se connecter</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Success</source> + <translation>Succès</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Succeed in connecting and login</source> + <translation>Réussir à connecter et à vous connecter</translation> </message> </context> <context> <name>SettingsDialog</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="38"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> <source>General</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="39"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> <source>Appearance</source> - <translation type="unfinished"></translation> + <translation>Apparence</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> - <source>PGP/Mime</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="42"/> + <source>Send Mail</source> + <translation>Envoyer un mail</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> <source>Key Server</source> - <translation type="unfinished"></translation> + <translation>Serveur de clés</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="45"/> <source>Advanced</source> - <translation type="unfinished"></translation> + <translation>Avancée</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="56"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="58"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Paramètres</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="101"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="103"/> <source>System Default</source> - <translation type="unfinished"></translation> + <translation>Défaut du système</translation> </message> </context> <context> @@ -2833,62 +3103,62 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/> <source>Generate New Subkey</source> - <translation type="unfinished"></translation> + <translation>Générer une nouvelle sous-clé</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation>Chiffrement</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation>Signature</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation>Certification</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation>Authentification</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation>Date d'expiration:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>N'expire jamais</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation>Keysize (dans le bit):</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation>Type de clé:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation>Informations de base</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/> <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <translation>Heure d'expiration Pas plus de 2 ans.</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/> <source>Generating Subkey...</source> - <translation type="unfinished"></translation> + <translation>Génération de sous-clé ...</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/> @@ -2896,90 +3166,129 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation>Collecte de données aléatoires pour la génération de sous-clé. + Cela peut prendre un peu de temps. + Pour accélérer le processus, utilisez votre ordinateur + (E.G. Parcourir le Net, écoutez de la musique, ...)</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation>Succès</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>The new subkey has been generated.</source> - <translation type="unfinished"></translation> + <translation>La nouvelle sous-clé a été générée.</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation>Échec</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>An error occurred during subkey generation.</source> - <translation type="unfinished"></translation> + <translation>Une erreur s'est produite lors de la génération de sous-clé.</translation> </message> </context> <context> <name>TextEdit</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/> <source>untitled</source> - <translation type="unfinished"></translation> + <translation>sans titre</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>Avertissement</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/> + <source>Cannot read file %1: +%2.</source> + <translation>Impossible de lire le fichier% 1: +% 2.</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/> <source>Open file</source> - <translation type="unfinished"></translation> + <translation>Fichier ouvert</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/> + <source>File</source> + <translation>Déposer</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/> + <source>Cannot write file %1: +%2.</source> + <translation>Impossible d'écrire le fichier% 1: +% 2.</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> <source>Save file</source> - <translation type="unfinished"></translation> + <translation>Enregistrer le fichier</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/> + <source>Unsaved document</source> + <translation>Document non enregistré</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/> + <source>The document "%1" has been modified. Do you want to save your changes?<br/></source> + <translation>Le document "% 1" a été modifié.Voulez-vous enregistrer vos modifications? <br/></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/> + <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <translation><B> REMARQUE: </ B> Si vous ne enregistrez pas ces fichiers, toutes les modifications sont perdues. <br/></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/> <source>Application</source> - <translation type="unfinished"></translation> + <translation>Application</translation> </message> +</context> +<context> + <name>UpdateTab</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/> - <source>Cannot read file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/> + <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source> + <translation>Il est recommandé de vérifier toujours la version de GPGFRontend et de la mise à niveau vers la dernière version.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/> + <source>New versions not only represent new features, but also often represent functional and security fixes.</source> + <translation>De nouvelles versions représentent non seulement de nouvelles fonctionnalités, mais également des corrections fonctionnelles et de sécurité.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/> + <source>Current Version: </source> + <translation>Version actuelle:</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/> - <source>Unsaved document</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/> + <source>The current version is inconsistent with the latest version on github.</source> + <translation>La version actuelle est incompatible avec la dernière version sur GitHub.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/> - <source><h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/> + <source>Please click <a href="https://github.com/saturneric/GpgFrontend/releases">here</a> to download the latest version.</source> + <translation>S'il vous plaît cliquez sur <a href="htttps://github.com/saturneric/gpgfronte/relases"> ici </a> pour télécharger la dernière version.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> - <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/> + <source>Latest Version From Github: </source> + <translation>Dernière version de GitHub:</translation> </message> </context> <context> @@ -2987,32 +3296,32 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/> <source>Signature Details</source> - <translation type="unfinished"></translation> + <translation>Détails de la signature</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/> <source>Status: </source> - <translation type="unfinished"></translation> + <translation>Statut:</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/> <source>No valid input found</source> - <translation type="unfinished"></translation> + <translation>Aucune entrée valide trouvée</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/> <source>Error Validating signature</source> - <translation type="unfinished"></translation> + <translation>Erreur lors de la validation de la signature</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/> <source>File was signed on %1 <br/> It Contains:<br/><br/></source> - <translation type="unfinished"></translation> + <translation>Le fichier a été signé sur% 1 <br/> contient: <br/> <br/></translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/> <source>Signed on %1 <br/> It Contains:<br /><br/></source> - <translation type="unfinished"></translation> + <translation>Signé sur% 1 <br/> Il contient: <br /> <br/></translation> </message> </context> <context> @@ -3020,22 +3329,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/> <source>Import from keyserver</source> - <translation type="unfinished"></translation> + <translation>Importer à partir de Keyserver</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/> <source>Key not present with id 0x</source> - <translation type="unfinished"></translation> + <translation>Clé non présente avec ID 0x</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/> <source>Status:</source> - <translation type="unfinished"></translation> + <translation>Statut:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/> <source>Key not present in keylist</source> - <translation type="unfinished"></translation> + <translation>Clé non présente dans Keylist</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/> @@ -3045,7 +3354,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/> <source>Key Information is NOT Available</source> - <translation type="unfinished"></translation> + <translation>Les informations clés ne sont pas disponibles</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/> @@ -3055,103 +3364,103 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation>Empreinte digitale:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/> <source>Status: Cert Revoked</source> - <translation type="unfinished"></translation> + <translation>Statut: certificat révoqué</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/> <source>Status: Signature Expired</source> - <translation type="unfinished"></translation> + <translation>Statut: Signature EXPIRÉ</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/> <source>Status: Key Expired</source> - <translation type="unfinished"></translation> + <translation>Statut: clé expirée</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/> <source>Status: General Error</source> - <translation type="unfinished"></translation> + <translation>Statut: erreur générale</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/> <source>Status: Unknown Error</source> - <translation type="unfinished"></translation> + <translation>Statut: erreur inconnue</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/> <source>Signer Name:</source> - <translation type="unfinished"></translation> + <translation>Nom du signataire:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/> <source>Signer Email:</source> - <translation type="unfinished"></translation> + <translation>Signer Email:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/> <source>Key's Fingerprint:</source> - <translation type="unfinished"></translation> + <translation>Empreinte digitale de la clé:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/> <source>Valid:</source> - <translation type="unfinished"></translation> + <translation>Valide:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/> <source>Flags:</source> - <translation type="unfinished"></translation> + <translation>Drapeaux:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/> <source>Fully Valid</source> - <translation type="unfinished"></translation> + <translation>Entièrement valable</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/> <source>NOT Fully Valid</source> - <translation type="unfinished"></translation> + <translation>Pas complètement valide</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation>Bien</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation>Mal</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation>Expiré</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/> <source>Missing Key </source> - <translation type="unfinished"></translation> + <translation>Clé manquante</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/> <source>Revoked Key </source> - <translation type="unfinished"></translation> + <translation>Clé révoquée</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/> <source>Expired Key </source> - <translation type="unfinished"></translation> + <translation>Clé expirée</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/> <source>Missing CRL </source> - <translation type="unfinished"></translation> + <translation>CRL manquant</translation> </message> </context> <context> @@ -3159,33 +3468,33 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/Wizard.cpp" line="46"/> <source>First Start Wizard</source> - <translation type="unfinished"></translation> + <translation>Assistant de premier départ</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation>Erreur d'importation</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Couldn't locate any keyring file in %1</source> - <translation type="unfinished"></translation> + <translation>Impossible de localiser un fichier de porte-clés en% 1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="84"/> <location filename="../../src/ui/Wizard.cpp" line="95"/> <source>Import error</source> - <translation type="unfinished"></translation> + <translation>Erreur d'importation</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="85"/> <source>Couldn't open private keyringfile: %1</source> - <translation type="unfinished"></translation> + <translation>Impossible d'ouvrir le keyRingfile privé:% 1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="96"/> <source>Couldn't open public keyringfile: %1</source> - <translation type="unfinished"></translation> + <translation>Impossible d'ouvrir le keyRingfile publique:% 1</translation> </message> </context> </TS> diff --git a/resource/ts/gpg_frontend_ru.ts b/resource/ts/gpgfrontend_ru.ts index ccbd15a0..65fb3765 100644 --- a/resource/ts/gpg_frontend_ru.ts +++ b/resource/ts/gpgfrontend_ru.ts @@ -4,212 +4,197 @@ <context> <name>AboutDialog</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="29"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/> <source>About </source> - <translation type="unfinished"></translation> + <translation>О</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="35"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/> <source>General</source> - <translation type="unfinished"></translation> + <translation>Общий</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="36"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/> <source>Translators</source> - <translation type="unfinished"></translation> + <translation>Переводчики</translation> + </message> + <message> + <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/> + <source>Update</source> + <translation>Обновлять</translation> </message> </context> <context> <name>AdvancedTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="580"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="679"/> <source>Show Steganography Options [Advanced]</source> - <translation type="unfinished"></translation> + <translation>Показать объекты стеганографии [Advanced]</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="582"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="681"/> <source>Show Steganographic Options.</source> - <translation type="unfinished"></translation> + <translation>Показать стеганографические варианты.</translation> </message> </context> <context> <name>AppearanceTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="368"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="444"/> <source>Iconsize</source> - <translation type="unfinished"></translation> + <translation>Iconsize.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="370"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="446"/> <source>small</source> - <translation type="unfinished"></translation> + <translation>небольшой</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="371"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="447"/> <source>medium</source> - <translation type="unfinished"></translation> + <translation>Средняя</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="372"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="448"/> <source>large</source> - <translation type="unfinished"></translation> + <translation>большой</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="388"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="464"/> <source>Iconstyle</source> - <translation type="unfinished"></translation> + <translation>Iconstyle.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="390"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="466"/> <source>just text</source> - <translation type="unfinished"></translation> + <translation>просто текст</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="391"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="467"/> <source>just icons</source> - <translation type="unfinished"></translation> + <translation>Просто иконы</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="392"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="468"/> <source>text and icons</source> - <translation type="unfinished"></translation> + <translation>текст и значки</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="484"/> <source>Windowstate</source> - <translation type="unfinished"></translation> + <translation>Indowstate.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="411"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="487"/> <source>Save window size and position on exit.</source> - <translation type="unfinished"></translation> + <translation>Сохранить размер окна и положение на выходе.</translation> </message> -</context> -<context> - <name>AttachmentTableModel</name> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="495"/> + <source>Information Board</source> + <translation>Доска объявлений</translation> </message> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="501"/> + <source> Front Size</source> + <translation>Передний размер</translation> </message> </context> <context> - <name>Attachments</name> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> - </message> + <name>ChoosePage</name> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="165"/> + <source>Choose your action...</source> + <translation>Выберите свое действие ...</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="166"/> + <source>...by clicking on the appropriate link.</source> + <translation>... нажав на соответствующую ссылку.</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="168"/> + <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> + <translation>Если вы никогда не использовали GPGFRontend раньше, а также не владеть ключом GPG, но вы, возможно, хотите прочитать, как</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="170"/> + <source>Generate Key</source> + <translation>Генерировать ключ</translation> </message> -</context> -<context> - <name>ChoosePage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="161"/> - <source>Choose your action...</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="176"/> + <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source> + <translation>Если вы хотите узнать, как зашифровать, расшифровать, подписать и проверить текст, вы можете прочитать</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="162"/> - <source>...by clicking on the appropriate link.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <source>Encrypt & Decrypt Text</source> + <translation>Шифра и расшифровывать текст</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="164"/> - <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>or</source> + <translation>или же</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="172"/> - <source>If you want to learn how to encrypt and decrypt text, you can read </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="180"/> + <source>Sign & Verify Text</source> + <translation>Знак и проверить текст</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="174"/> - <location filename="../../src/ui/Wizard.cpp" line="183"/> - <source>this document</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="188"/> + <source>If you want to operate file, you can read </source> + <translation>Если вы хотите управлять файлом, вы можете прочитать</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="181"/> - <source>If you want to sign and verify text, you can read </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>Encrypt & Sign File</source> + <translation>Шифра и файл знака</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="166"/> - <source>create a new keypair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="192"/> + <source>Sign & Verify File</source> + <translation>Знак и проверять файл</translation> </message> </context> <context> <name>ConclusionPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="397"/> + <location filename="../../src/ui/Wizard.cpp" line="407"/> <source>Ready.</source> - <translation type="unfinished"></translation> + <translation>Готовый.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="398"/> + <location filename="../../src/ui/Wizard.cpp" line="408"/> <source>Have fun with GPGFrontend!</source> - <translation type="unfinished"></translation> + <translation>Веселитесь с GPGFRontend!</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="400"/> + <location filename="../../src/ui/Wizard.cpp" line="410"/> <source>You are ready to use GPGFrontend now.<br><br></source> - <translation type="unfinished"></translation> + <translation>Вы готовы использовать GPGFRontend сейчас. <br> <br> <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="402"/> + <location filename="../../src/ui/Wizard.cpp" line="412"/> <source>The Online Document</source> - <translation type="unfinished"></translation> + <translation>Онлайн документ</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="403"/> + <location filename="../../src/ui/Wizard.cpp" line="413"/> <source> will get you started with GPGFrontend. It will open in the main window.<br></source> - <translation type="unfinished"></translation> + <translation>Получу, вы начали с GPGFRontend.Он откроется в главном окне. <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="410"/> + <location filename="../../src/ui/Wizard.cpp" line="420"/> <source>Open offline help.</source> - <translation type="unfinished"></translation> + <translation>Откройте автономную помощь.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="413"/> + <location filename="../../src/ui/Wizard.cpp" line="423"/> <source>Dont show the wizard again.</source> - <translation type="unfinished"></translation> + <translation>Не показывать волшебник снова.</translation> </message> </context> <context> @@ -217,129 +202,152 @@ <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation>Дешифративный файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation>Зашифруйте файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation>Знак файла</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation>Проверьте файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/> <source>Input Parameters</source> - <translation type="unfinished"></translation> + <translation>Входные параметры</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/> <source>Target File</source> - <translation type="unfinished"></translation> + <translation>Целевой файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/> <source>Output File</source> - <translation type="unfinished"></translation> + <translation>Выходной файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/> <source>Signature File(.sig) Path</source> - <translation type="unfinished"></translation> + <translation>Подпись файла (.сиг) путь</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/> <source>Open File</source> - <translation type="unfinished"></translation> + <translation>Открыть файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/> <source>Save File</source> - <translation type="unfinished"></translation> + <translation>Сохранить файл</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> <source>Couldn't open file</source> - <translation type="unfinished"></translation> + <translation>Не мог открыть файл</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/> + <source>Error</source> + <translation>Ошибка</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/> + <source>Error Occurred During Encryption</source> + <translation>Произошла ошибка во время шифрования</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/> + <source>Error Occurred During Decryption</source> + <translation>Произошла ошибка во время дешифрования</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> + <source>Error Occurred During Signature</source> + <translation>Произошла ошибка во время подписи</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Файл</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/> <source>File exists! Do you want to overwrite it?</source> - <translation type="unfinished"></translation> + <translation>Файл существует!Вы хотите перезаписать это?</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/> <source>Cannot write file %1: %2.</source> - <translation type="unfinished"></translation> + <translation>Невозможно написать файл% 1: +% 2.</translation> </message> </context> <context> <name>FilePage</name> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/> <source>Open</source> - <translation type="unfinished"></translation> + <translation>Открыть</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/> <source>Delete</source> - <translation type="unfinished"></translation> + <translation>Удалить</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/> <source>Encrypt and Sign</source> - <translation type="unfinished"></translation> + <translation>Шифровать и подписать</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/> <source>Decrypt and Verify</source> - <translation type="unfinished"></translation> + <translation>Расшифровать и проверить</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/> <source>Only Sign</source> - <translation type="unfinished"></translation> + <translation>Только знак</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/> <source>Only Verify</source> - <translation type="unfinished"></translation> + <translation>Только проверить</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>Предупреждение</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/> <source>Are you sure you want to delete it?</source> - <translation type="unfinished"></translation> + <translation>Вы уверены, что хотите это удалить?</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation>Ошибка</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/> <source>Unable to delete the file or folder.</source> - <translation type="unfinished"></translation> + <translation>Невозможно удалить файл или папку.</translation> </message> </context> <context> @@ -347,266 +355,281 @@ <message> <location filename="../../src/ui/FindWidget.cpp" line="38"/> <source>Find:</source> - <translation type="unfinished"></translation> + <translation>Находить:</translation> </message> </context> <context> <name>GeneralTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="135"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="137"/> <source>Remember Password</source> - <translation type="unfinished"></translation> + <translation>Напомнить пароль</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="138"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="140"/> <source>Remember password until closing gpg4usb</source> - <translation type="unfinished"></translation> + <translation>Запомните пароль до закрытия GPG4UUSB</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="145"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="147"/> <source>Save Checked Keys</source> - <translation type="unfinished"></translation> + <translation>Сохранить проверенные ключи</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="148"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="150"/> <source>Save checked private keys on exit and restore them on next start.</source> - <translation type="unfinished"></translation> + <translation>Сохранить проверенные закрытые ключи на выходе и восстановить их на следующем запуске.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="157"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="159"/> <source>Confirm drag'n'drop key import</source> - <translation type="unfinished"></translation> + <translation>Подтвердите импорт ключа Drag'n'drop</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="160"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="162"/> <source>Import files dropped on the keylist without confirmation.</source> - <translation type="unfinished"></translation> + <translation>Файлы импорта упали на кейлист без подтверждения.</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="167"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="169"/> <source>Language</source> - <translation type="unfinished"></translation> + <translation>Язык</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="176"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="178"/> <source><b>NOTE: </b> GpgFrontend will restart automatically if you change the language!</source> - <translation type="unfinished"></translation> + <translation><b> Примечание: </ b> gpgfrontend автоматически перезагрузится, если вы измените язык!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="185"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="187"/> <source>Own key</source> - <translation type="unfinished"></translation> + <translation>Собственный ключ</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="193"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="195"/> <source><none></source> - <translation type="unfinished"></translation> + <translation><none></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="207"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="209"/> <source>Key pair for synchronization and identity authentication</source> - <translation type="unfinished"></translation> + <translation>Пара ключей для синхронизации и аутентификации идентичности</translation> </message> </context> <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="90"/> - <source>ENV Loading Failed</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="91"/> - <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="577"/> + <location filename="../../src/gpg/GpgContext.cpp" line="528"/> <source>Wrong password</source> - <translation type="unfinished"></translation> + <translation>Неправильный пароль</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="585"/> + <location filename="../../src/gpg/GpgContext.cpp" line="536"/> <source>Enter Password for</source> - <translation type="unfinished"></translation> + <translation>Введите пароль для</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="589"/> + <location filename="../../src/gpg/GpgContext.cpp" line="540"/> <source>Enter Password</source> - <translation type="unfinished"></translation> + <translation>Введите пароль</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>Key Selection</source> - <translation type="unfinished"></translation> + <translation>Выбор ключа</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>No Private Key Selected</source> - <translation type="unfinished"></translation> + <translation>Нет закрытого ключа</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="804"/> + <location filename="../../src/gpg/GpgContext.cpp" line="746"/> <source>Error in signing:</source> - <translation type="unfinished"></translation> + <translation>Ошибка в подписании:</translation> </message> </context> <context> <name>GpgPathsTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="612"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="711"/> <source>Relative path to keydb</source> - <translation type="unfinished"></translation> + <translation>Относительный путь к Keydb</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="625"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="724"/> <source>Current keydb path: </source> - <translation type="unfinished"></translation> + <translation>Текущий путь ключей:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="630"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="729"/> <source><b>NOTE: </b> Gpg4usb will restart automatically if you change the keydb path!</source> - <translation type="unfinished"></translation> + <translation><b> Примечание: </ b> GPG4USB автоматически перезагрузится, если вы измените путь ключей!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="659"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="758"/> <source>Choose keydb directory</source> - <translation type="unfinished"></translation> + <translation>Выберите каталог keydb.</translation> </message> </context> <context> <name>ImportFromGnupgPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="292"/> + <location filename="../../src/ui/Wizard.cpp" line="302"/> <source>Import keys...</source> - <translation type="unfinished"></translation> + <translation>Импорт клавиш ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="293"/> + <location filename="../../src/ui/Wizard.cpp" line="303"/> <source>...from existing GnuPG installation</source> - <translation type="unfinished"></translation> + <translation>... Из существующей установки GNUPG</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="295"/> + <location filename="../../src/ui/Wizard.cpp" line="305"/> <source>You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br></source> - <translation type="unfinished"></translation> + <translation>Вы можете импортировать ключи от локально установленного GNUPG. <br> <br> Местоположение читается из реестра в Windows или предполагается, что папка .gnupg в вашем домашнем каталоге в Linux. <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="299"/> + <location filename="../../src/ui/Wizard.cpp" line="309"/> <source>Import keys from GnuPG</source> - <translation type="unfinished"></translation> + <translation>Импорт клавиш от GNUPG</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation>Ошибка импорта</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Couldn't locate GnuPG home directory</source> - <translation type="unfinished"></translation> + <translation>Не мог найти домашний каталог GNUPG</translation> </message> </context> <context> <name>ImportFromGpg4usbPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="215"/> + <location filename="../../src/ui/Wizard.cpp" line="225"/> <source>Import from...</source> - <translation type="unfinished"></translation> + <translation>Импорт из ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="216"/> + <location filename="../../src/ui/Wizard.cpp" line="226"/> <source>...existing GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>... Существующие GPGFRontend</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="218"/> + <location filename="../../src/ui/Wizard.cpp" line="228"/> <source>You can import keys and/or settings from existing GPGFrontend. <br><br>Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source> - <translation type="unfinished"></translation> + <translation>Вы можете импортировать ключи и / или настройки из существующих GPGFRontend.<br> <br> <br> Просто проверьте, что вы хотите импортировать, нажмите кнопку «Импорт» и выберите каталог других GPGFRontend в диалоговом окне появления файла.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="225"/> + <location filename="../../src/ui/Wizard.cpp" line="235"/> <source>Keys</source> - <translation type="unfinished"></translation> + <translation>Ключи</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="229"/> + <location filename="../../src/ui/Wizard.cpp" line="239"/> <source>Configuration</source> - <translation type="unfinished"></translation> + <translation>Конфигурация</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="231"/> + <location filename="../../src/ui/Wizard.cpp" line="241"/> <source>Import from GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>Импорт от GPGFRontend</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="246"/> + <location filename="../../src/ui/Wizard.cpp" line="256"/> <source>Other GPGFrontend directory</source> - <translation type="unfinished"></translation> + <translation>Другие каталога GPGFRontend</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="265"/> + <location filename="../../src/ui/Wizard.cpp" line="275"/> <source>Configuration Imported</source> - <translation type="unfinished"></translation> + <translation>Конфигурация импортирована</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="266"/> + <location filename="../../src/ui/Wizard.cpp" line="276"/> <source>Imported Configuration from old GPGFrontend.<br>Will now restart to activate the configuration.</source> - <translation type="unfinished"></translation> + <translation>Импортированная конфигурация из старых GPGFRontend. <br> теперь перезагрузится, чтобы активировать конфигурацию.</translation> </message> </context> <context> <name>InfoBoardWidget</name> <message> - <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/> <source>Import missing key from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Импортировать недостающий ключ от Keyserver</translation> + </message> + <message> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/> + <source>Optional Actions Menu</source> + <translation>Дополнительные действия меню действий</translation> </message> </context> <context> <name>InfoTab</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="55"/> - <source><br><center>GPGFrontend is an easy-to-use, compact, <br>cross-platform, and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/> + <source><br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> + <translation><br> <Center> GPGFRontend - это простое в использовании, компактной, кроссплатформе, <br> и без установочного интерфейса GPG. <br> это визуализирует большую часть общих операций команд GPG. <BR> Он лицензирован под GPL V3 <br> <br> <b> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> Если у вас есть какие-либо вопросы или предложения, повысить проблему <br/>href = "https://github.com/saturneric/gpgfrontend"> github </a> или отправьте письмо в мой список рассылки на <a href="mailte: @bktus.com"> [email protected] </ a>.</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="63"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/> <source><br><br> Built with Qt </source> - <translation type="unfinished"></translation> + <translation><br> <br> построен с Qt</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="64"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/> <source> and GPGME </source> - <translation type="unfinished"></translation> + <translation>и GPGME</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="65"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/> <source><br>Built at </source> - <translation type="unfinished"></translation> + <translation><br> построен</translation> </message> </context> <context> <name>IntroPage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="111"/> - <source>Getting started...</source> - <translation type="unfinished"></translation> + <source>Getting Started...</source> + <translation>Начиная...</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="112"/> <source>... with GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>... с gpgfrontend</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="114"/> - <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br></source> - <translation type="unfinished"></translation> + <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source> + <translation>Добро пожаловать использовать GPGFRontend для расшифровки и подписания текста или файла!</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="116"/> + <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source> + <translation>Является мощным, простым в использовании, компактной, кроссплатформенной и монтажной программой Crypto Crypto OpenPGP.</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="117"/> + <source>For brief information have a look at the</source> + <translation>Для краткой информации посмотрите на</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="118"/> + <source>Overview</source> + <translation>Обзор</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="123"/> + <location filename="../../src/ui/Wizard.cpp" line="119"/> + <source>by clicking the link, the page will open in the web browser</source> + <translation>Нажав на ссылку, страница откроется в веб-браузере</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="127"/> <source>Choose a Language</source> - <translation type="unfinished"></translation> + <translation>Выберите язык</translation> </message> </context> <context> @@ -614,22 +637,22 @@ <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/> <source>KeyPair</source> - <translation type="unfinished"></translation> + <translation>Keypair.</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/> <source>UIDs</source> - <translation type="unfinished"></translation> + <translation>UIDs</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/> <source>Subkeys</source> - <translation type="unfinished"></translation> + <translation>Подсказки</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/> <source>Key Details</source> - <translation type="unfinished"></translation> + <translation>Основные детали</translation> </message> </context> <context> @@ -637,150 +660,159 @@ <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/> <source>Generate Key</source> - <translation type="unfinished"></translation> + <translation>Генерировать ключ</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation>Имя должно содержать не менее пяти символов.</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, дайте адрес электронной почты.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/> - <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/> + <source> Expiration time no more than 2 years. +</source> + <translation>Время истечения не более 2 лет.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/> <source>Generating Key...</source> - <translation type="unfinished"></translation> + <translation>Генератор ключа ...</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/> <source>Collecting random data for key generation. This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation>Сбор случайных данных для генерации ключей. + Это может занять некоторое время. + Чтобы ускорить процесс, используйте свой компьютер + (например, просмотрите чистую, слушаю музыку, ...)</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/> + <source>Key Usage</source> + <translation>Ключевое использование</translation> + </message> + <message> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation>Шифрование</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation>Подписание</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation>Сертификация</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation>Аутентификация</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation>Успех</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>The new key pair has been generated.</source> - <translation type="unfinished"></translation> + <translation>Новая ключевая пара была сгенерирована.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation>Отказ</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>An error occurred during key generation.</source> - <translation type="unfinished"></translation> + <translation>Произошла ошибка во время генерации ключей.</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation>Имя:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation>Адрес электронной почты:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation>Комментарий:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation>Дата окончания срока:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>Никогда не истекаешь</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation>Клинизировать (по-бит):</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation>Тип ключа:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> <source>Non Pass Phrase</source> - <translation type="unfinished"></translation> + <translation>Не проходящая фраза</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation>Основная информация</translation> </message> </context> <context> <name>KeyGenPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="356"/> + <location filename="../../src/ui/Wizard.cpp" line="366"/> <source>Create a keypair...</source> - <translation type="unfinished"></translation> + <translation>Создать клавиатуру ...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="357"/> + <location filename="../../src/ui/Wizard.cpp" line="367"/> <source>...for decrypting and signing messages</source> - <translation type="unfinished"></translation> + <translation>... Для расшифровки и подписания сообщений</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="358"/> + <location filename="../../src/ui/Wizard.cpp" line="368"/> <source>You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window):</source> - <translation type="unfinished"></translation> + <translation>Вы должны создать новую keypair. Пара состоит из публики и закрытого ключа. <br> Другие пользователи могут использовать открытый ключ для шифрования сообщений для вас и проверить сообщения, подписанные вами. Вы можете использовать закрытый ключ для расшифровки и подписатьСообщения. <br> Для получения дополнительной информации посмотрите на автономный учебник (который затем отображается в главном окне):</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="365"/> + <location filename="../../src/ui/Wizard.cpp" line="375"/> <source>Offline tutorial</source> - <translation type="unfinished"></translation> + <translation>Оффлайн учебник</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="372"/> + <location filename="../../src/ui/Wizard.cpp" line="382"/> <source>Create New Key</source> - <translation type="unfinished"></translation> + <translation>Создать новый ключ</translation> </message> </context> <context> @@ -789,118 +821,118 @@ <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/> <source>Key Update Details</source> - <translation type="unfinished"></translation> + <translation>Детали обновления ключа</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <source>No keys found</source> - <translation type="unfinished"></translation> + <translation>Ключи не найдены</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/> <source>Key Import Details</source> - <translation type="unfinished"></translation> + <translation>Детали ввоза ключей</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <source>No keys found to import</source> - <translation type="unfinished"></translation> + <translation>Клавиши не найдены для импорта</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/> <source>General key info</source> - <translation type="unfinished"></translation> + <translation>Общая ключевая информация</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/> <source>Considered:</source> - <translation type="unfinished"></translation> + <translation>Считается:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/> <source>Public unchanged:</source> - <translation type="unfinished"></translation> + <translation>Общественность без изменений:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/> <source>Imported:</source> - <translation type="unfinished"></translation> + <translation>Импортирован:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/> <source>Not imported:</source> - <translation type="unfinished"></translation> + <translation>Не импортировано:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/> <source>Private read:</source> - <translation type="unfinished"></translation> + <translation>Частный читал:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/> <source>Private imported:</source> - <translation type="unfinished"></translation> + <translation>Частный импорт:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/> <source>Private unchanged:</source> - <translation type="unfinished"></translation> + <translation>Частный без изменений:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Имя</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>Электронное письмо</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Status</source> - <translation type="unfinished"></translation> + <translation>Статус</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation>Отпечаток пальца</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/> <source>private</source> - <translation type="unfinished"></translation> + <translation>частный</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="138"/> <source>public</source> - <translation type="unfinished"></translation> + <translation>публичный</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="141"/> <source>unchanged</source> - <translation type="unfinished"></translation> + <translation>без изменений</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/> <source>new key</source> - <translation type="unfinished"></translation> + <translation>новый ключ</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/> <source>new subkey</source> - <translation type="unfinished"></translation> + <translation>Новый подраздел</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/> <source>new signature</source> - <translation type="unfinished"></translation> + <translation>Новая подпись</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/> <source>new uid</source> - <translation type="unfinished"></translation> + <translation>Новый UID</translation> </message> </context> <context> @@ -908,157 +940,158 @@ <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>Выбирать</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Type</source> - <translation type="unfinished"></translation> + <translation>Тип</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Имя</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Email Address</source> - <translation type="unfinished"></translation> + <translation>Адрес электронной почты</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Usage</source> - <translation type="unfinished"></translation> + <translation>Применение</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Validity</source> - <translation type="unfinished"></translation> + <translation>Срок действия</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Finger Print</source> - <translation type="unfinished"></translation> + <translation>Печать пальцев</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> <source>Import Keys</source> - <translation type="unfinished"></translation> + <translation>Импорт клавиш</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/> <source>You've dropped something on the table. GpgFrontend will now try to import key(s).</source> - <translation type="unfinished"></translation> + <translation>Вы что-то бросили на стол. + GPGFRontend теперь попробует импортировать ключ (ы).</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/> <source>Always import without bothering.</source> - <translation type="unfinished"></translation> + <translation>Всегда импортировать, не беспокоясь.</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/> <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <translation>Не удалось открыть файл:</translation> </message> </context> <context> <name>KeyMgmt</name> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="81"/> - <source>KeyPairs Management</source> - <translation type="unfinished"></translation> + <source>Key Pair Management</source> + <translation>Ключевое управление паре</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="88"/> <source>&Open</source> - <translation type="unfinished"></translation> + <translation>&Открыть</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="89"/> <source>Ctrl+O</source> - <translation type="unfinished"></translation> + <translation>Ctrl + O.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="90"/> <source>Open Key File</source> - <translation type="unfinished"></translation> + <translation>Откройте файл ключа</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="93"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&Закрывать</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="94"/> <source>Ctrl+Q</source> - <translation type="unfinished"></translation> + <translation>Ctrl + Q.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="96"/> <source>Close</source> - <translation type="unfinished"></translation> + <translation>Закрывать</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="99"/> <source>New Keypair</source> - <translation type="unfinished"></translation> + <translation>Новая клавиатура</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="100"/> <source>Ctrl+N</source> - <translation type="unfinished"></translation> + <translation>Ctrl + N.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="102"/> <source>Generate KeyPair</source> - <translation type="unfinished"></translation> + <translation>Создать ключевую пару</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="105"/> <source>New Subkey</source> - <translation type="unfinished"></translation> + <translation>Новый подраздел</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="106"/> <source>Ctrl+Shift+N</source> - <translation type="unfinished"></translation> + <translation>Ctrl + Shift + N</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="108"/> <source>Generate Subkey For Selected KeyPair</source> - <translation type="unfinished"></translation> + <translation>Создать подраздел для выбранной клавиатуры</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="111"/> <location filename="../../src/ui/KeyMgmt.cpp" line="152"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation>&Файл</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="113"/> <source>Import New Key From File</source> - <translation type="unfinished"></translation> + <translation>Импортировать новый ключ из файла</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="116"/> <source>&Clipboard</source> - <translation type="unfinished"></translation> + <translation>И буфер обмена</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="118"/> <source>Import New Key From Clipboard</source> - <translation type="unfinished"></translation> + <translation>Импортировать новый ключ из буфера обмена</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="121"/> <source>&Keyserver</source> - <translation type="unfinished"></translation> + <translation>& Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="123"/> <source>Import New Key From Keyserver</source> - <translation type="unfinished"></translation> + <translation>Импортировать новый ключ от Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="126"/> @@ -1068,149 +1101,149 @@ <message> <location filename="../../src/ui/KeyMgmt.cpp" line="128"/> <source>Export Selected Key(s) To Clipboard</source> - <translation type="unfinished"></translation> + <translation>Экспорт выбранных клавиш в буфер обмена</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="131"/> <source>Export To &File</source> - <translation type="unfinished"></translation> + <translation>Экспорт в & file</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="133"/> <source>Export Selected Key(s) To File</source> - <translation type="unfinished"></translation> + <translation>Экспорт выбранных клавиш (ы) в файл</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="136"/> <source>Delete Selected Key(s)</source> - <translation type="unfinished"></translation> + <translation>Удалить выбранные ключи (ы)</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="137"/> <source>Delete the Selected keys</source> - <translation type="unfinished"></translation> + <translation>Удалить выбранные ключи</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="140"/> <source>Delete Checked Key(s)</source> - <translation type="unfinished"></translation> + <translation>Удалить проверенные ключи (ы)</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="141"/> <source>Delete the Checked keys</source> - <translation type="unfinished"></translation> + <translation>Удалить проверенные ключи</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="145"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation>Показать ключевые детали</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="146"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation>Показать детали для этого ключа</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="156"/> <source>&Key</source> - <translation type="unfinished"></translation> + <translation>&Ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="157"/> <source>&Generate Key</source> - <translation type="unfinished"></translation> + <translation>Генерировать ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="161"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation>И Импорт ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="173"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>Ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="181"/> <source>Generate</source> - <translation type="unfinished"></translation> + <translation>Генерация</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="182"/> <source>Generate A New Keypair or Subkey</source> - <translation type="unfinished"></translation> + <translation>Генерировать новую клавиатуру или подразделение</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="191"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation>Импорт ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="192"/> <source>Import Key</source> - <translation type="unfinished"></translation> + <translation>Импорт ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Open Key</source> - <translation type="unfinished"></translation> + <translation>Открыть ключ</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation>Ключевые файлы</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Keyring files</source> - <translation type="unfinished"></translation> + <translation>Ключевые файлы</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="218"/> <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <translation>Не удалось открыть файл:</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="268"/> <source>Deleting Keys</source> - <translation type="unfinished"></translation> + <translation>Удаление клавиш</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="269"/> <source>Are you sure that you want to delete the following keys?</source> - <translation type="unfinished"></translation> + <translation>Вы уверены, что хотите удалить следующие клавиши?</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="270"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation>Действие не может быть отменено.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation>Экспорт ключа в файл</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="309"/> <source>key(s) exported</source> - <translation type="unfinished"></translation> + <translation>Ключ (ы) экспортирован</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="338"/> <location filename="../../src/ui/KeyMgmt.cpp" line="345"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>Неверная операция</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="339"/> <source>Please select one KeyPair before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, выберите одну клавиатуру перед этой операцией.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="346"/> <source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source> - <translation type="unfinished"></translation> + <translation>Если ключевая пара не имеет частного ключа, то он не сможет генерировать подшиные клавиши.</translation> </message> </context> <context> @@ -1218,198 +1251,237 @@ <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Имя</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>Электронное письмо</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>Комментарий</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/> <source>Create New UID</source> - <translation type="unfinished"></translation> + <translation>Создать новый UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation>Имя должно содержать не менее пяти символов.</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, дайте адрес электронной почты.</translation> </message> </context> <context> <name>KeyPairDetailTab</name> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> <source>Owner</source> - <translation type="unfinished"></translation> + <translation>Владелец</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> <source>Master Key</source> - <translation type="unfinished"></translation> + <translation>Отмычка</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation>Отпечаток пальца</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/> <source>Additional UIDs</source> - <translation type="unfinished"></translation> + <translation>Дополнительные UID</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Exists</source> + <translation>Существуют</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Not Exists</source> + <translation>Не существует</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation>Имя:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation>Адрес электронной почты:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation>Комментарий:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation>Ключевой идентификатор:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation>Алгоритм:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation>Размер ключа:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> <source>Nominal Usage: </source> - <translation type="unfinished"></translation> + <translation>Номинальное использование:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> <source>Actual Usage: </source> - <translation type="unfinished"></translation> + <translation>Фактическое использование:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> <source>Expires on: </source> - <translation type="unfinished"></translation> + <translation>Годен до:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation>Последнее обновление:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/> <source>Secret Key Existence: </source> - <translation type="unfinished"></translation> + <translation>Секретное ключевое существование:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> <source>Copy</source> - <translation type="unfinished"></translation> + <translation>Скопировать</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/> <source>copy fingerprint to clipboard</source> - <translation type="unfinished"></translation> + <translation>Скопируйте отпечаток пальца в буфер обмена</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/> <source>Operations</source> - <translation type="unfinished"></translation> + <translation>Операции</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/> - <source>Export Private Key (Include Subkeys)</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/> + <source>Export Private Key (Include Subkey)</source> + <translation>Экспорт закрытый ключ (включить подразделение)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/> <source>Modify Expiration Datetime (Master Key)</source> - <translation type="unfinished"></translation> + <translation>Изменить истечения срока действия данных (главный ключ)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/> <source>Key Server Operation (Pubkey)</source> - <translation type="unfinished"></translation> + <translation>Операция ключевым сервером (PUBKEY)</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/> + <source>Generate Revoke Certificate</source> + <translation>Создать сертификат Revoke.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/> <source>Warning: The Master Key has expired.</source> - <translation type="unfinished"></translation> + <translation>ПРЕДУПРЕЖДЕНИЕ. Срок действия главного ключа истек.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/> <source>Warning: The Master Key has been revoked</source> - <translation type="unfinished"></translation> + <translation>Предупреждение: главный ключ был отменен</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/> <source>Exporting private Key</source> - <translation type="unfinished"></translation> + <translation>Экспорт закрытого ключа</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/> - <source><h3>You are about to export your <font color="red">PRIVATE KEY</font>!</h3> -This is NOT your Public Key, so DON'T give it away.<br />Do you REALLY want to export your PRIVATE KEY?</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/> + <source>You are about to export your</source> + <translation>Вы собираетесь экспортировать свой</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/> + <source>PRIVATE KEY</source> + <translation>Закрытый ключ</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/> + <source>This is NOT your Public Key, so DON'T give it away.</source> + <translation>Это не ваш открытый ключ, поэтому не отдавай.</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/> + <source>Do you REALLY want to export your PRIVATE KEY?</source> + <translation>Вы действительно хотите экспортировать свой закрытый ключ?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation>Экспорт ключа в файл</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation>Ключевые файлы</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Export Error</source> - <translation type="unfinished"></translation> + <translation>Экспорт ошибок</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Couldn't open %1 for writing</source> - <translation type="unfinished"></translation> + <translation>Не мог открыть% 1 для письма</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>Никогда не истекаешь</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/> - <source>Upload Key Pair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/> + <source>Upload Key Pair to Key Server</source> + <translation>Загрузить ключевую пару на ключевой сервер</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/> <source>Update Key Pair</source> - <translation type="unfinished"></translation> + <translation>Обновить ключевую пару</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/> + <source>Generate revocation certificate</source> + <translation>Генерировать сертификат отзыва</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/> + <source>Revocation Certificates</source> + <translation>Сертификаты отзыва</translation> </message> </context> <context> @@ -1417,87 +1489,87 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/> <source>Generate A New Subkey</source> - <translation type="unfinished"></translation> + <translation>Генерировать новый подразделение</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation>Ключевой идентификатор:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation>Алгоритм:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation>Размер ключа:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> <source>Usage: </source> - <translation type="unfinished"></translation> + <translation>Применение:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> <source>Expires On </source> - <translation type="unfinished"></translation> + <translation>Годен до</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation>Последнее обновление:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> <source>Existence: </source> - <translation type="unfinished"></translation> + <translation>Существование:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation>Отпечаток пальца:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Subkey ID</source> - <translation type="unfinished"></translation> + <translation>ID SUBKEY ID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Key Size</source> - <translation type="unfinished"></translation> + <translation>Размер ключа</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Algo</source> - <translation type="unfinished"></translation> + <translation>Что-нибудь</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation>Создать дату</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation>Дата истечения срока годности</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>Никогда не истекаешь</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation>Никогда не заканчивается</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/> <source>Edit Expire Date</source> - <translation type="unfinished"></translation> + <translation>Редактировать дату истечения срока действия</translation> </message> </context> <context> @@ -1505,192 +1577,202 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/> <source>New UID</source> - <translation type="unfinished"></translation> + <translation>Новый UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/> <source>UID Management</source> - <translation type="unfinished"></translation> + <translation>Управление UID</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/> + <source>UIDs</source> + <translation>UIDs</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/> + <source>Signature of Selected UID</source> + <translation>Подпись выбранного UID</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>Выбирать</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>Имя</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>Электронное письмо</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>Комментарий</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Key ID</source> - <translation type="unfinished"></translation> + <translation>Идентификатор ключа</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation>Создать дату</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Expired Date</source> - <translation type="unfinished"></translation> + <translation>Истекший срок</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation>Никогда не заканчивается</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>Неверная операция</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/> <source>Please select one or more UIDs before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, выберите один или несколько UID, прежде чем делать эту операцию.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/> <source>Sign Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation>Знак выбран UID (ы)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/> <source>Delete Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation>Удалить выбранные UID (ы)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/> <source>Successful Operation</source> - <translation type="unfinished"></translation> + <translation>Успешная операция</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> <source>Successfully added a new UID.</source> - <translation type="unfinished"></translation> + <translation>Успешно добавил новый UID.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation>Операция не удалась</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation>Во время операции произошла ошибка.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/> <source>Deleting UIDs</source> - <translation type="unfinished"></translation> + <translation>Удаление UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/> <source>Are you sure that you want to delete the following uids?</source> - <translation type="unfinished"></translation> + <translation>Вы уверены, что хотите удалить следующие UID?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation>Действие не может быть отменено.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/> <source>Set Primary UID</source> - <translation type="unfinished"></translation> + <translation>Установите первичный UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/> <source>Are you sure that you want to set the Primary UID to?</source> - <translation type="unfinished"></translation> + <translation>Вы уверены, что хотите установить основной UID?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/> <source>Set As Primary</source> - <translation type="unfinished"></translation> + <translation>Установить как первичный</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/> <source>Sign UID</source> - <translation type="unfinished"></translation> + <translation>Знак UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/> <source>Delete UID</source> - <translation type="unfinished"></translation> + <translation>Удалить UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/> <source>Please select one UID before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, выберите один UID перед этой операцией.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/> <source>Deleting UID</source> - <translation type="unfinished"></translation> + <translation>Удаление UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/> <source>Are you sure that you want to delete the following uid?</source> - <translation type="unfinished"></translation> + <translation>Вы уверены, что хотите удалить следующий UID?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/> <source>Delete(Revoke) Key Signature</source> - <translation type="unfinished"></translation> + <translation>Удалить (отозвать) подпись ключа</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/> <source>Please select one Key Signature before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, выберите одну клавишу подпись перед выполнением этой операции.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/> <source>To delete the signature, you need to have its corresponding public key in the local database.</source> - <translation type="unfinished"></translation> + <translation>Чтобы удалить подпись, вам нужно иметь соответствующий открытый ключ в локальной базе данных.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/> <source>Deleting Key Signature</source> - <translation type="unfinished"></translation> + <translation>Удаление подписи ключей</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/> <source>Are you sure that you want to delete the following signature?</source> - <translation type="unfinished"></translation> + <translation>Вы уверены, что хотите удалить следующую подпись?</translation> </message> </context> <context> @@ -1698,140 +1780,140 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&Закрывать</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/> <source>&Import ALL</source> - <translation type="unfinished"></translation> + <translation>И импорт все</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/> <source>&Search</source> - <translation type="unfinished"></translation> + <translation>&Поиск</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/> <source>Search String:</source> - <translation type="unfinished"></translation> + <translation>Строка поиска:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/> <source>Key Server:</source> - <translation type="unfinished"></translation> + <translation>Ключевой сервер:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/> <source>Update Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Обновлять ключи от Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/> <source>Import Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Импорт клавиш от Keyserver</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>UID</source> - <translation type="unfinished"></translation> + <translation>UID</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Creation date</source> - <translation type="unfinished"></translation> + <translation>Дата создания</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>KeyID</source> - <translation type="unfinished"></translation> + <translation>Кейд</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Tag</source> - <translation type="unfinished"></translation> + <translation>Тег</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/> - <source><h4>Text is empty.</h4></source> - <translation type="unfinished"></translation> + <source>Text is empty.</source> + <translation>Текст пуст.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/> <source>Not Key Found</source> - <translation type="unfinished"></translation> + <translation>Не найден ключ</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation>Время ожидания</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation>Ключевой сервер не найден</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation>Ошибка соединения</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> - <source><h4>CToo many responses from keyserver!</h4></source> - <translation type="unfinished"></translation> + <source>Too many responses from keyserver!</source> + <translation>Слишком много ответов от Keyserver!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> - <source><h4>No keys found, input may be kexId, retrying search with 0x.</h4></source> - <translation type="unfinished"></translation> + <source>No keys found, input may be kexId, retrying search with 0x.</source> + <translation>Не найдено ключей, вход может быть кекидом, повторный поиск с 0x.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> - <source><h4>No keys found containing the search string!</h4></source> - <translation type="unfinished"></translation> + <source>No keys found containing the search string!</source> + <translation>Клавиши не найдены, содержащие строку поиска!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> - <source><h4>Insufficiently specific search string!</h4></source> - <translation type="unfinished"></translation> + <source>Insufficiently specific search string!</source> + <translation>Недостаточно определенная строка поиска!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/> <source>revoked</source> - <translation type="unfinished"></translation> + <translation>отзыв</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/> <source>disabled</source> - <translation type="unfinished"></translation> + <translation>отключен</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/> <source><h4>%1 keys found. Double click a key to import it.</h4></source> - <translation type="unfinished"></translation> + <translation><h4>% 1 ключей найден.Дважды щелкните ключ, чтобы импортировать его. </ H4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation>Ключ не найден</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/> <source><h4>Key Updated</h4></source> - <translation type="unfinished"></translation> + <translation><h4> ключ обновлен </ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/> <source><h4>Key Imported</h4></source> - <translation type="unfinished"></translation> + <translation><H4> КЛЮЧ импортирован </ H4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/> <source>Upload Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>Клавиши загрузки от Keyserver</translation> </message> </context> <context> @@ -1839,22 +1921,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/> <source>Confirm</source> - <translation type="unfinished"></translation> + <translation>Подтверждать</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>Никогда не истекаешь</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation>Операция не удалась</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation>Во время операции произошла ошибка.</translation> </message> </context> <context> @@ -1862,801 +1944,856 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation>Дата истечения срока годности</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/> <source>Sign For Key's UID(s)</source> - <translation type="unfinished"></translation> + <translation>Знак для ключа UID (ы)</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/> <source>Unsuccessful Operation</source> - <translation type="unfinished"></translation> + <translation>Неудачная операция</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/> <source>Signature operation failed for UID </source> - <translation type="unfinished"></translation> + <translation>Операция подписи не удалась для UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/> <source>Operation Complete</source> - <translation type="unfinished"></translation> + <translation>Операция завершена</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/> <source>The signature operation of the UID is complete</source> - <translation type="unfinished"></translation> + <translation>Эксплуатация подписи UID завершена</translation> </message> </context> <context> <name>KeyUploadDialog</name> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/> <source>Uploading Public Key</source> - <translation type="unfinished"></translation> + <translation>Загрузка открытого ключа</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation>Ключ не найден</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation>Время ожидания</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation>Ключевой сервер не найден</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation>Ошибка соединения</translation> </message> </context> <context> <name>KeyserverTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="508"/> - <source>Default Keyserver for import:</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="607"/> + <source>Default Key Server for import:</source> + <translation>Сервер по умолчанию для импорта:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="525"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="624"/> <source>Add</source> - <translation type="unfinished"></translation> + <translation>Добавлять</translation> </message> </context> <context> <name>MainWindow</name> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/> + <location filename="../../src/MainWindow.cpp" line="35"/> + <source>Loading Gnupg</source> + <translation>Загрузка GNUPG.</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="62"/> + <source>ENV Loading Failed</source> + <translation>Загрузка ENV не удалась</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="63"/> + <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> + <translation>GNUPG не установлен правильно, пожалуйста, следуйте инструкциям ReadMe для установки GNUPG, а затем открыть GPGFRontend.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/> <source>No Key Selected</source> - <translation type="unfinished"></translation> + <translation>Нет выбранного ключа</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>Неверная операция</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/> <source>The selected key contains a key that does not actually have a encrypt usage.<br/></source> - <translation type="unfinished"></translation> + <translation>Выбранный ключ содержит ключ, который на самом деле не имеет использование шифрования. <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/> + <source><br/>For example the Following Key: <br/></source> + <translation><br/> Например, следующий ключ: <br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/> + <source>Encrypting</source> + <translation>Шифрование</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/> + <source>Function Disabled</source> + <translation>Функция отключена</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/> + <source>Please go to the settings interface to enable and configure this function.</source> + <translation>Пожалуйста, перейдите на интерфейс настроек, чтобы включить и настроить эту функцию.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/> <source>The selected key contains a key that does not actually have a signature usage.<br/></source> - <translation type="unfinished"></translation> + <translation>Выбранный ключ содержит клавишу, на самом деле не имеет использование подписи. <br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/> + <source>Signing</source> + <translation>Подписание</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/> + <source>Decrypting</source> + <translation>Расшифровка</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/> + <source>Verifying</source> + <translation>Проверка</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/> <source>Invalid KeyPair</source> - <translation type="unfinished"></translation> + <translation>Неверная keypair.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/> <source>The selected keypair cannot be used for signing and encryption at the same time.<br/></source> - <translation type="unfinished"></translation> + <translation>Выбранная клавиатура не может быть использована для подписания и шифрования одновременно. <br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/> <source>Incomplete Operation</source> - <translation type="unfinished"></translation> + <translation>Неполная операция</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/> <source>None of the selected key pairs can provide the encryption function.</source> - <translation type="unfinished"></translation> + <translation>Ни одна из выбранных парных пар не может предоставлять функцию шифрования.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/> <source>None of the selected key pairs can provide the signature function.</source> - <translation type="unfinished"></translation> + <translation>Ни одна из выбранных парных пар не может обеспечить функцию подписи.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/> + <source>Encrypting and Signing</source> + <translation>Шифрование и подписание</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/> + <source>Decrypting and Verifying</source> + <translation>Расшифровка и проверка</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation>Ошибка</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <source>Select a file before doing it.</source> + <translation>Выберите файл перед этим.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> <source>No permission to read this file.</source> - <translation type="unfinished"></translation> + <translation>Нет разрешения на чтение этого файла.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> <source>No permission to create file.</source> - <translation type="unfinished"></translation> + <translation>Нет разрешения на создание файла.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>Предупреждение</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/> <source>The target file already exists, do you need to overwrite it?</source> - <translation type="unfinished"></translation> + <translation>Целевой файл уже существует, вам нужно перезаписать это?</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>An error occurred during operation.</source> - <translation type="unfinished"></translation> + <translation>Во время работы произошла ошибка.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/> <source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source> - <translation type="unfinished"></translation> + <translation>Пожалуйста, выберите подходящий целевой файл или файл подписи.Убедитесь, что оба находятся в этом каталоге.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> <source>No permission to read target file.</source> - <translation type="unfinished"></translation> + <translation>Нет разрешения на чтение целевого файла.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> <source>No permission to read signature file.</source> - <translation type="unfinished"></translation> + <translation>Нет разрешения на чтение файла подписи.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> <source>Select a file(.gpg/.asc) before doing it.</source> - <translation type="unfinished"></translation> + <translation>Выберите файл (.gpg / .asc), прежде чем делать это.</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/> - <source><br/>For example the Following Key: <br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/> + <source>Outdated Version</source> + <translation>Устаревшая версия</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> - <source>Select a file before doing it.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/> + <source>This version(%1) is out of date, please update the latest version in time. </source> + <translation>Эта версия (% 1) устарела, пожалуйста, обновите последнюю версию вовремя.</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/> + <source>You can download the latest version(%1) on Github Releases Page.<br/></source> + <translation>Вы можете скачать последнюю версию (% 1) на странице выбросов GitHub. <br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/> + <source>Unreleased Version</source> + <translation>Неразрешенная версия</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/> + <source>This version(%1) has not been officially released and is not recommended for use in a production environment. <br/></source> + <translation>Эта версия (% 1) не была официально выпущена и не рекомендуется для использования в производственной среде.<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/> <source>There is one unencrypted file in attachment folder</source> - <translation type="unfinished"></translation> + <translation>Есть один незашифрованный файл в папке вложения</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source>There are </source> - <translation type="unfinished"></translation> + <translation>Есть</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source> unencrypted files in attachment folder</source> - <translation type="unfinished"></translation> + <translation>Непритвержденные файлы в папке вложения</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/> <source>&New</source> - <translation type="unfinished"></translation> + <translation>&Новый</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/> <source>Open a new file</source> - <translation type="unfinished"></translation> + <translation>Открыть новый файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/> <source>&Open...</source> - <translation type="unfinished"></translation> + <translation>&Открыть...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/> <source>Open an existing file</source> - <translation type="unfinished"></translation> + <translation>Откройте существующий файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/> <source>&Browser</source> - <translation type="unfinished"></translation> + <translation>И браузер</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/> <source>Open a file browser</source> - <translation type="unfinished"></translation> + <translation>Откройте файловый браузер</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/> <source>&Save</source> - <translation type="unfinished"></translation> + <translation>&Сохранить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/> <source>Save the current File</source> - <translation type="unfinished"></translation> + <translation>Сохранить текущий файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/> <source>Save &As</source> - <translation type="unfinished"></translation> + <translation>Сохранить как</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/> <source>Save the current File as...</source> - <translation type="unfinished"></translation> + <translation>Сохраните текущий файл как ...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/> <source>&Print</source> - <translation type="unfinished"></translation> + <translation>&Распечатать</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/> <source>Print Document</source> - <translation type="unfinished"></translation> + <translation>Печать документа</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&Закрывать</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/> <source>Close file</source> - <translation type="unfinished"></translation> + <translation>Закрыть файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/> <source>&Quit</source> - <translation type="unfinished"></translation> + <translation>&Покидать</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/> <source>Quit Program</source> - <translation type="unfinished"></translation> + <translation>Бросить программу</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/> <source>&Undo</source> - <translation type="unfinished"></translation> + <translation>&Отменить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/> <source>Undo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation>Отменить последнее редактировать действие</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/> <source>&Redo</source> - <translation type="unfinished"></translation> + <translation>& Redo.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/> <source>Redo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation>Redo Последние редактировать действие</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/> <source>Zoom In</source> - <translation type="unfinished"></translation> + <translation>Увеличить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/> <source>Zoom Out</source> - <translation type="unfinished"></translation> + <translation>Уменьшить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/> <source>&Paste</source> - <translation type="unfinished"></translation> + <translation>&Вставить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/> <source>Paste Text From Clipboard</source> - <translation type="unfinished"></translation> + <translation>Вставить текст из буфера обмена</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/> <source>Cu&t</source> - <translation type="unfinished"></translation> + <translation>С & т.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/> <source>Cut the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <translation>Разрежьте содержимое текущего выбора в буфер обмена</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/> <source>&Copy</source> - <translation type="unfinished"></translation> + <translation>И скопируйте</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/> <source>Copy the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <translation>Скопируйте содержимое текущего выбора в буфер обмена</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/> <source>&Quote</source> - <translation type="unfinished"></translation> + <translation>& quot</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/> <source>Quote whole text</source> - <translation type="unfinished"></translation> + <translation>Цитировать весь текст</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/> <source>Select &All</source> - <translation type="unfinished"></translation> + <translation>Выбрать все</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/> <source>Select the whole text</source> - <translation type="unfinished"></translation> + <translation>Выберите весь текст</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/> <source>&Find</source> - <translation type="unfinished"></translation> + <translation>&Находить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/> <source>Find a word</source> - <translation type="unfinished"></translation> + <translation>Найти слово</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/> <source>Remove &spacing</source> - <translation type="unfinished"></translation> + <translation>Удалить и расстояние</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/> <source>Remove double linebreaks, e.g. in pasted text from webmailer</source> - <translation type="unfinished"></translation> + <translation>Удалить двойные линии, например,В вставленном тексте от Webmailer</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/> <source>Se&ttings</source> - <translation type="unfinished"></translation> + <translation>& Tutting.</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/> <source>Open settings dialog</source> - <translation type="unfinished"></translation> + <translation>Диалог открытых настроек</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/> <source>&Encrypt</source> - <translation type="unfinished"></translation> + <translation>& Шифрование</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/> <source>Encrypt Message</source> - <translation type="unfinished"></translation> + <translation>Шифрование сообщения</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/> <source>&Encrypt &Sign</source> - <translation type="unfinished"></translation> + <translation>& Шифра и подписать</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/> <source>Encrypt and Sign Message</source> - <translation type="unfinished"></translation> + <translation>Зашифруйте и подписывать сообщение</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/> <source>&Decrypt</source> - <translation type="unfinished"></translation> + <translation>& Decrypt</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/> <source>Decrypt Message</source> - <translation type="unfinished"></translation> + <translation>Расшифровать сообщение</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/> <source>&Decrypt &Verify</source> - <translation type="unfinished"></translation> + <translation>& Decrypt & проверить</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/> <source>Decrypt and Verify Message</source> - <translation type="unfinished"></translation> + <translation>Расшифровать и проверить сообщение</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/> <source>&Encrypt File</source> - <translation type="unfinished"></translation> + <translation>Зашифруйте файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation>Зашифруйте файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/> <source>&Decrypt File</source> - <translation type="unfinished"></translation> + <translation>Дешифративный файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation>Дешифративный файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/> <source>&Sign File</source> - <translation type="unfinished"></translation> + <translation>& Знак файла</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation>Знак файла</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/> <source>&Verify File</source> - <translation type="unfinished"></translation> + <translation>И проверить файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation>Проверьте файл</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/> <source>&Sign</source> - <translation type="unfinished"></translation> + <translation>&Знак</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/> <source>Sign Message</source> - <translation type="unfinished"></translation> + <translation>Знак сообщения</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/> <source>&Verify</source> - <translation type="unfinished"></translation> + <translation>&Проверять</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/> <source>Verify Message</source> - <translation type="unfinished"></translation> + <translation>Проверить сообщение</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/> <source>&Editor</source> - <translation type="unfinished"></translation> + <translation>&Редактор</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/> <source>Import New Key From Editor</source> - <translation type="unfinished"></translation> + <translation>Импортировать новый ключ от редактора</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/> - <source>Manage &keys</source> - <translation type="unfinished"></translation> + <source>Manage &Keys</source> + <translation>Управление и клавиши</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/> <source>Open Keymanagement</source> - <translation type="unfinished"></translation> + <translation>Открыть ключманагемент</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/> <source>&About</source> - <translation type="unfinished"></translation> + <translation>&О</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/> <source>Show the application's About box</source> - <translation type="unfinished"></translation> + <translation>Показать приложение о коробке</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/> + <source>&Check for Updates</source> + <translation>Проверьте наличие обновлений</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <source>Check for updates</source> + <translation>Проверьте наличие обновлений</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/> <source>Open &Wizard</source> - <translation type="unfinished"></translation> + <translation>Open & Wizard</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> <source>Open the wizard</source> - <translation type="unfinished"></translation> + <translation>Откройте волшебник</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> <source>Append Selected Key(s) To Text</source> - <translation type="unfinished"></translation> + <translation>Добавьте выбранные ключи в текст</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> <source>Append The Selected Keys To Text in Editor</source> - <translation type="unfinished"></translation> + <translation>Добавьте выбранные ключи в текст в редакторе</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> - <source>Copy EMail-address</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <source>Copy Email</source> + <translation>Скопируйте электронную почту</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/> - <source>Copy selected EMailaddress to clipboard</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <source>Copy selected Email to clipboard</source> + <translation>Скопируйте выбранную электронную почту в буфер обмена</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation>Показать ключевые детали</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation>Показать детали для этого ключа</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/> <source>Refresh Key From Key Server</source> - <translation type="unfinished"></translation> + <translation>Обновить ключ от ключевого сервера</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/> <source>Refresh key from default key server</source> - <translation type="unfinished"></translation> + <translation>Обновить ключ с сервера ключей по умолчанию</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/> <source>Upload Public Key(s) To Server</source> - <translation type="unfinished"></translation> + <translation>Загрузить открытый ключ (ы) на сервер</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/> <source>Upload The Selected Public Keys To Server</source> - <translation type="unfinished"></translation> + <translation>Загрузить выбранные открытые клавиши на сервер</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/> <source>Remove PGP Header</source> - <translation type="unfinished"></translation> + <translation>Удалить заголовок PGP</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/> <source>Add PGP Header</source> - <translation type="unfinished"></translation> + <translation>Добавить PGP заголовок</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation>&Файл</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/> <source>&Edit</source> - <translation type="unfinished"></translation> + <translation>&Редактировать</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/> <source>&File...</source> - <translation type="unfinished"></translation> + <translation>&Файл...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/> <source>&Crypt</source> - <translation type="unfinished"></translation> + <translation>И склеил</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> <source>&Keys</source> - <translation type="unfinished"></translation> + <translation>И ключи</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation>И Импорт ключ</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/> <source>&Steganography</source> - <translation type="unfinished"></translation> + <translation>Стеганография</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> <source>&View</source> - <translation type="unfinished"></translation> + <translation>&Вид</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/> <source>&Help</source> - <translation type="unfinished"></translation> + <translation>&Помощь</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>Файл</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/> <source>Crypt</source> - <translation type="unfinished"></translation> + <translation>Крипта</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>Ключ</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/> <source>Edit</source> - <translation type="unfinished"></translation> + <translation>Редактировать</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/> <source>Special Edit</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/> <source>Import key from...</source> - <translation type="unfinished"></translation> + <translation>Импорт ключ от ...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation>Импорт ключ</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/> <source>Browser to view and operate file</source> - <translation type="unfinished"></translation> + <translation>Браузер для просмотра и управления файлом</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/> <source>Browser</source> - <translation type="unfinished"></translation> + <translation>Браузер</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/> <source>Ready</source> - <translation type="unfinished"></translation> + <translation>Готовый</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/> <source>Key ToolBox</source> - <translation type="unfinished"></translation> + <translation>Ключевой набор инструментов</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/> <source>Information Board</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>MimeTab</name> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> - <source>Decode quoted printable</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="292"/> - <source>Try to recognize quoted printable.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="296"/> - <source>Parse PGP/MIME (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="299"/> - <source>Try to split attachments from PGP-MIME ecrypted messages.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="304"/> - <source>Open with external application (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="306"/> - <source>Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> - <source>Enable opening with external applications.</source> - <translation type="unfinished"></translation> + <translation>Доска объявлений</translation> </message> </context> <context> @@ -2664,107 +2801,107 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/> <source>>Recipient: </source> - <translation type="unfinished"></translation> + <translation>> Получатель:</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/> <source>One or More Bad Signatures.</source> - <translation type="unfinished"></translation> + <translation>Одна или несколько плохих подписей.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/> <source>A </source> - <translation type="unfinished"></translation> + <translation>А.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation>Хорошо</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation>Плохо</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation>Истекший</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/> <source>Missing Key's </source> - <translation type="unfinished"></translation> + <translation>Отсутствует ключ</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/> <source>Revoked Key's </source> - <translation type="unfinished"></translation> + <translation>Отменил ключ</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/> <source>Expired Key's </source> - <translation type="unfinished"></translation> + <translation>Истекший ключ</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/> <source>Missing CRL's </source> - <translation type="unfinished"></translation> + <translation>Отсутствие CRL's.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/> <source>Signature Fully Valid.</source> - <translation type="unfinished"></translation> + <translation>Подпись полностью действительна.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/> <source>Signature NOT Fully Valid.</source> - <translation type="unfinished"></translation> + <translation>Подпись не полностью действительна.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/> <source>Key is NOT present with ID 0x</source> - <translation type="unfinished"></translation> + <translation>Ключ отсутствует с ID 0x</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/> <source>A signature could NOT be verified due to a Missing Key </source> - <translation type="unfinished"></translation> + <translation>Подпись не может быть проверена из-за недостающего ключа</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/> <source>A signature is valid but the key used to verify the signature has been revoked </source> - <translation type="unfinished"></translation> + <translation>Подпись действительна, но ключ, используемый для проверки подписи, был отменен</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/> <source>A signature is valid but expired </source> - <translation type="unfinished"></translation> + <translation>Подпись действительна, но истек</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/> <source>A signature is valid but the key used to verify the signature has expired. </source> - <translation type="unfinished"></translation> + <translation>Подпись действительна, но ключ, используемый для проверки подписи, истек.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/> <source>There was some other error which prevented the signature verification. </source> - <translation type="unfinished"></translation> + <translation>Была какая-то другая ошибка, которая предотвратила проверку подписи.</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/> <source>Error for key with fingerprint </source> - <translation type="unfinished"></translation> + <translation>Ошибка для ключа с отпечатками пальца</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/> <source>Signed By: </source> - <translation type="unfinished"></translation> + <translation>Подписано:</translation> </message> </context> <context> @@ -2772,60 +2909,193 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/QuitDialog.cpp" line="29"/> <source>Unsaved Files</source> - <translation type="unfinished"></translation> + <translation>Несохраненные файлы</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="77"/> - <source><h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3></source> - <translation type="unfinished"></translation> + <source>%1 files contain unsaved information.<br/>Save the changes before closing?</source> + <translation>Файлы% 1 содержат несохраненную информацию. <br/> Сохранить изменения перед закрытием?</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="88"/> <source>Check the files you want to save:</source> - <translation type="unfinished"></translation> + <translation>Проверьте файлы, которые вы хотите сохранить:</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="89"/> <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <translation><b> Примечание: </ b> Если вы не сохраните эти файлы, все изменения потеряны. <br/></translation> + </message> +</context> +<context> + <name>SendMailDialog</name> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="35"/> + <source>Incomplete configuration</source> + <translation>Неполная конфигурация</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="36"/> + <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source> + <translation>Адрес SMTP пуст, перейдите на интерфейс настройки, чтобы завершить конфигурацию.</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="86"/> + <source> Recipient cannot be empty +</source> + <translation>Получатель не может быть пустым</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="91"/> + <source> One or more Recipient's Email Address is invalid +</source> + <translation>Один или несколько адресов электронной почты получателя недействителен</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="97"/> + <source> Sender cannot be empty +</source> + <translation>Отправитель не может быть пустым</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="99"/> + <source> Sender's Email Address is invalid +</source> + <translation>Адрес электронной почты отправителя недействителен</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail</source> + <translation>Неудача</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <source>Fail to Connect SMTP Server</source> + <translation>Не удается подключить SMTP-сервер</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <source>Fail to Login into SMTP Server</source> + <translation>Не входить в систему на SMTP-сервер</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail to Send Mail to SMTP Server</source> + <translation>Не удалось отправить почту на SMTP-сервер</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Success</source> + <translation>Успех</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Succeed in Sending Mail to SMTP Server</source> + <translation>Успешно отправлять почту на SMTP-сервер</translation> + </message> +</context> +<context> + <name>SendMailTab</name> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> + <source>Enable</source> + <translation>Давать возможность</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="311"/> + <source>SMTP Address</source> + <translation>SMTP-адрес</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="313"/> + <source>Username</source> + <translation>Имя пользователя</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> + <source>Password</source> + <translation>Пароль</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="317"/> + <source>Port</source> + <translation>Порт</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="319"/> + <source>Connection Security</source> + <translation>Безопасность подключения</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="322"/> + <source>Default Sender</source> + <translation>Отправитель по умолчанию</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail</source> + <translation>Неудача</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <source>Fail to Connect SMTP Server</source> + <translation>Не удается подключить SMTP-сервер</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail to Login</source> + <translation>Не входить в систему</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Success</source> + <translation>Успех</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Succeed in connecting and login</source> + <translation>Преуспеть в подключении и входе в систему</translation> </message> </context> <context> <name>SettingsDialog</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="38"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> <source>General</source> - <translation type="unfinished"></translation> + <translation>Общий</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="39"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> <source>Appearance</source> - <translation type="unfinished"></translation> + <translation>Появление</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> - <source>PGP/Mime</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="42"/> + <source>Send Mail</source> + <translation>Отправить почту</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> <source>Key Server</source> - <translation type="unfinished"></translation> + <translation>Ключевой сервер</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="45"/> <source>Advanced</source> - <translation type="unfinished"></translation> + <translation>Передовой</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="56"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="58"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>Настройки</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="101"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="103"/> <source>System Default</source> - <translation type="unfinished"></translation> + <translation>Системные установки по умолчанию</translation> </message> </context> <context> @@ -2833,62 +3103,62 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/> <source>Generate New Subkey</source> - <translation type="unfinished"></translation> + <translation>Генерировать новый подразделение</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation>Шифрование</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation>Подписание</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation>Сертификация</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation>Аутентификация</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation>Дата окончания срока:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>Никогда не истекаешь</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation>Клинизировать (по-бит):</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation>Тип ключа:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation>Основная информация</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/> <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <translation>Время истечения не более 2 лет.</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/> <source>Generating Subkey...</source> - <translation type="unfinished"></translation> + <translation>Генерация подраздела ...</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/> @@ -2896,90 +3166,129 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation>Сбор случайных данных для поколения подраздела. + Это может занять некоторое время. + Чтобы ускорить процесс, используйте свой компьютер + (например, просмотрите чистую, слушаю музыку, ...)</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation>Успех</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>The new subkey has been generated.</source> - <translation type="unfinished"></translation> + <translation>Новый подразделение было сгенерировано.</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation>Отказ</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>An error occurred during subkey generation.</source> - <translation type="unfinished"></translation> + <translation>Произошла ошибка во время поколения подраздела.</translation> </message> </context> <context> <name>TextEdit</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/> <source>untitled</source> - <translation type="unfinished"></translation> + <translation>Безватый</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>Предупреждение</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/> + <source>Cannot read file %1: +%2.</source> + <translation>Не удается прочитать файл% 1: +% 2.</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/> <source>Open file</source> - <translation type="unfinished"></translation> + <translation>Открыть файл</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/> + <source>File</source> + <translation>Файл</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/> + <source>Cannot write file %1: +%2.</source> + <translation>Невозможно написать файл% 1: +% 2.</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> <source>Save file</source> - <translation type="unfinished"></translation> + <translation>Сохранить файл</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/> + <source>Unsaved document</source> + <translation>Несохраненный документ</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/> + <source>The document "%1" has been modified. Do you want to save your changes?<br/></source> + <translation>Документ «% 1» был изменен.Вы хотите сохранить ваши изменения? <br/></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/> + <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <translation><b> Примечание: </ b> Если вы не сохраните эти файлы, все изменения потеряны. <br/></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/> <source>Application</source> - <translation type="unfinished"></translation> + <translation>Заявление</translation> </message> +</context> +<context> + <name>UpdateTab</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/> - <source>Cannot read file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/> + <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source> + <translation>Рекомендуется, чтобы вы всегда проверяли версию GPGFRontend и обновите до последней версии.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/> + <source>New versions not only represent new features, but also often represent functional and security fixes.</source> + <translation>Новые версии не только представляют новые функции, но и часто представляют функциональные и безопасные исправления.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/> + <source>Current Version: </source> + <translation>Текущая версия:</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/> - <source>Unsaved document</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/> + <source>The current version is inconsistent with the latest version on github.</source> + <translation>Текущая версия несовместима с последней версией на Github.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/> - <source><h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/> + <source>Please click <a href="https://github.com/saturneric/GpgFrontend/releases">here</a> to download the latest version.</source> + <translation>Пожалуйста, нажмите <a href="http://github.com/saturneric/gpgfrontend/relestrestions"> Здесь </a> для загрузки последней версии.</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> - <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/> + <source>Latest Version From Github: </source> + <translation>Последняя версия из GitHub:</translation> </message> </context> <context> @@ -2987,32 +3296,32 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/> <source>Signature Details</source> - <translation type="unfinished"></translation> + <translation>Подробности подписи</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/> <source>Status: </source> - <translation type="unfinished"></translation> + <translation>Статус:</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/> <source>No valid input found</source> - <translation type="unfinished"></translation> + <translation>Допустимый вход не найден</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/> <source>Error Validating signature</source> - <translation type="unfinished"></translation> + <translation>Ошибка проверки подписи</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/> <source>File was signed on %1 <br/> It Contains:<br/><br/></source> - <translation type="unfinished"></translation> + <translation>Файл был подписан на% 1 <br/> он содержит: <br/> <br/></translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/> <source>Signed on %1 <br/> It Contains:<br /><br/></source> - <translation type="unfinished"></translation> + <translation>Подписано на% 1 <br/> Он содержит: <br /> <br/></translation> </message> </context> <context> @@ -3020,22 +3329,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/> <source>Import from keyserver</source> - <translation type="unfinished"></translation> + <translation>Импорт от Keyserver</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/> <source>Key not present with id 0x</source> - <translation type="unfinished"></translation> + <translation>Ключ не присутствует с ID 0x</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/> <source>Status:</source> - <translation type="unfinished"></translation> + <translation>Статус:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/> <source>Key not present in keylist</source> - <translation type="unfinished"></translation> + <translation>Ключ не присутствует в кейлисте</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/> @@ -3045,7 +3354,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/> <source>Key Information is NOT Available</source> - <translation type="unfinished"></translation> + <translation>Основная информация недоступна</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/> @@ -3055,103 +3364,103 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation>Отпечаток пальца:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/> <source>Status: Cert Revoked</source> - <translation type="unfinished"></translation> + <translation>Статус: Сертинг отозван</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/> <source>Status: Signature Expired</source> - <translation type="unfinished"></translation> + <translation>Статус: подпись истек</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/> <source>Status: Key Expired</source> - <translation type="unfinished"></translation> + <translation>Статус: ключ истек</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/> <source>Status: General Error</source> - <translation type="unfinished"></translation> + <translation>Статус: общая ошибка</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/> <source>Status: Unknown Error</source> - <translation type="unfinished"></translation> + <translation>Статус: неизвестная ошибка</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/> <source>Signer Name:</source> - <translation type="unfinished"></translation> + <translation>Название сигнала:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/> <source>Signer Email:</source> - <translation type="unfinished"></translation> + <translation>Email Signer Email:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/> <source>Key's Fingerprint:</source> - <translation type="unfinished"></translation> + <translation>Отпечаток ключа:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/> <source>Valid:</source> - <translation type="unfinished"></translation> + <translation>Действительный:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/> <source>Flags:</source> - <translation type="unfinished"></translation> + <translation>Флаги:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/> <source>Fully Valid</source> - <translation type="unfinished"></translation> + <translation>Полностью действителен</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/> <source>NOT Fully Valid</source> - <translation type="unfinished"></translation> + <translation>Не полностью действительным</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation>Хорошо</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation>Плохо</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation>Истекший</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/> <source>Missing Key </source> - <translation type="unfinished"></translation> + <translation>Пропавший ключ</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/> <source>Revoked Key </source> - <translation type="unfinished"></translation> + <translation>Отменил ключ</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/> <source>Expired Key </source> - <translation type="unfinished"></translation> + <translation>Ключ срок действия</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/> <source>Missing CRL </source> - <translation type="unfinished"></translation> + <translation>Пропавший CRL</translation> </message> </context> <context> @@ -3159,33 +3468,33 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/Wizard.cpp" line="46"/> <source>First Start Wizard</source> - <translation type="unfinished"></translation> + <translation>Первый запуск волшебника</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation>Ошибка импорта</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Couldn't locate any keyring file in %1</source> - <translation type="unfinished"></translation> + <translation>Не мог найти любой файл ключа в% 1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="84"/> <location filename="../../src/ui/Wizard.cpp" line="95"/> <source>Import error</source> - <translation type="unfinished"></translation> + <translation>Ошибка импорта</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="85"/> <source>Couldn't open private keyringfile: %1</source> - <translation type="unfinished"></translation> + <translation>Не мог открыть частное cliedingfile:% 1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="96"/> <source>Couldn't open public keyringfile: %1</source> - <translation type="unfinished"></translation> + <translation>Не удалось открыть открытый клавиатуре:% 1</translation> </message> </context> </TS> diff --git a/resource/ts/gpgfrontend_zh_chs.ts b/resource/ts/gpgfrontend_zh_cn.ts index 7bf4bd62..58efd923 100644 --- a/resource/ts/gpgfrontend_zh_chs.ts +++ b/resource/ts/gpgfrontend_zh_cn.ts @@ -4,212 +4,197 @@ <context> <name>AboutDialog</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="29"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="35"/> <source>About </source> - <translation type="unfinished"></translation> + <translation>关于</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="35"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="42"/> <source>General</source> - <translation type="unfinished"></translation> + <translation>通用</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="36"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="43"/> <source>Translators</source> - <translation type="unfinished"></translation> + <translation>译者</translation> + </message> + <message> + <location filename="../../src/ui/help/AboutDialog.cpp" line="44"/> + <source>Update</source> + <translation>更新</translation> </message> </context> <context> <name>AdvancedTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="580"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="679"/> <source>Show Steganography Options [Advanced]</source> - <translation type="unfinished"></translation> + <translation>显示隐写术选项[高级]</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="582"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="681"/> <source>Show Steganographic Options.</source> - <translation type="unfinished"></translation> + <translation>显示隐写术选项。</translation> </message> </context> <context> <name>AppearanceTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="368"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="444"/> <source>Iconsize</source> - <translation type="unfinished"></translation> + <translation>图标化</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="370"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="446"/> <source>small</source> - <translation type="unfinished"></translation> + <translation>小的</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="371"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="447"/> <source>medium</source> - <translation type="unfinished"></translation> + <translation>中等的</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="372"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="448"/> <source>large</source> - <translation type="unfinished"></translation> + <translation>大</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="388"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="464"/> <source>Iconstyle</source> - <translation type="unfinished"></translation> + <translation>图标样式</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="390"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="466"/> <source>just text</source> - <translation type="unfinished"></translation> + <translation>只是文字</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="391"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="467"/> <source>just icons</source> - <translation type="unfinished"></translation> + <translation>只是图标</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="392"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="468"/> <source>text and icons</source> - <translation type="unfinished"></translation> + <translation>文字和图标</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="484"/> <source>Windowstate</source> - <translation type="unfinished"></translation> + <translation>窗口状态</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="411"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="487"/> <source>Save window size and position on exit.</source> - <translation type="unfinished"></translation> + <translation>保存窗口大小和位置。</translation> </message> -</context> -<context> - <name>AttachmentTableModel</name> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="124"/> - <source>Filename</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="495"/> + <source>Information Board</source> + <translation>信息板</translation> </message> <message> - <location filename="../../src/ui/AttachmentTableModel.cpp" line="127"/> - <source>Contenttype</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="501"/> + <source> Front Size</source> + <translation>字体大小</translation> </message> </context> <context> - <name>Attachments</name> + <name>ChoosePage</name> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="78"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="113"/> - <source>Save File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="165"/> + <source>Choose your action...</source> + <translation>选择你的行动......</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="79"/> - <source>Save this file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="166"/> + <source>...by clicking on the appropriate link.</source> + <translation>...单击相应的链接。</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="83"/> - <source>Open File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="168"/> + <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> + <translation>如果您之前从未使用过GPG2Rend并且也没有拥有GPG密钥,但您可能希望阅读如何</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="84"/> - <source>Open this file</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="170"/> + <source>Generate Key</source> + <translation>生成密钥对</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="119"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="164"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="176"/> + <source>If you want to learn how to encrypt, decrypt, sign and verify text, you can read </source> + <translation>如果您想了解如何加密,解密,签名和验证文本,可以阅读</translation> </message> <message> - <location filename="../../src/ui/widgets/Attachments.cpp" line="120"/> - <location filename="../../src/ui/widgets/Attachments.cpp" line="165"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <source>Encrypt & Decrypt Text</source> + <translation>加密&解密文本</translation> </message> -</context> -<context> - <name>ChoosePage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="161"/> - <source>Choose your action...</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="178"/> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>or</source> + <translation>或者</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="162"/> - <source>...by clicking on the appropriate link.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="180"/> + <source>Sign & Verify Text</source> + <translation>签名&验证文本</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="164"/> - <source>If you have never used GPGFrontend before and also don't own a gpg key yet you may possibly want to read how to</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="188"/> + <source>If you want to operate file, you can read </source> + <translation>如果要操作文件,可以阅读</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="172"/> - <source>If you want to learn how to encrypt and decrypt text, you can read </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="190"/> + <source>Encrypt & Sign File</source> + <translation>加密&签名文件</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="174"/> - <location filename="../../src/ui/Wizard.cpp" line="183"/> - <source>this document</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/Wizard.cpp" line="181"/> - <source>If you want to sign and verify text, you can read </source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/Wizard.cpp" line="166"/> - <source>create a new keypair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/Wizard.cpp" line="192"/> + <source>Sign & Verify File</source> + <translation>签名&验证文件</translation> </message> </context> <context> <name>ConclusionPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="397"/> + <location filename="../../src/ui/Wizard.cpp" line="407"/> <source>Ready.</source> - <translation type="unfinished"></translation> + <translation>准备好。</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="398"/> + <location filename="../../src/ui/Wizard.cpp" line="408"/> <source>Have fun with GPGFrontend!</source> - <translation type="unfinished"></translation> + <translation>在GPGFrontend玩得开心!</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="400"/> + <location filename="../../src/ui/Wizard.cpp" line="410"/> <source>You are ready to use GPGFrontend now.<br><br></source> - <translation type="unfinished"></translation> + <translation>你现在准备好使用GPGFrontend。<br> <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="402"/> + <location filename="../../src/ui/Wizard.cpp" line="412"/> <source>The Online Document</source> - <translation type="unfinished"></translation> + <translation>在线文档</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="403"/> + <location filename="../../src/ui/Wizard.cpp" line="413"/> <source> will get you started with GPGFrontend. It will open in the main window.<br></source> - <translation type="unfinished"></translation> + <translation>会带领你开始使用GPGFrontend。它将在主窗口中打开。<br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="410"/> + <location filename="../../src/ui/Wizard.cpp" line="420"/> <source>Open offline help.</source> - <translation type="unfinished"></translation> + <translation>打开离线帮助。</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="413"/> + <location filename="../../src/ui/Wizard.cpp" line="423"/> <source>Dont show the wizard again.</source> - <translation type="unfinished"></translation> + <translation>不要再次显示向导。</translation> </message> </context> <context> @@ -217,129 +202,152 @@ <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="32"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation>解密文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="34"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation>加密文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="36"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation>签名文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="38"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation>验证文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="47"/> <source>Input Parameters</source> - <translation type="unfinished"></translation> + <translation>输入参数</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="53"/> <source>Target File</source> - <translation type="unfinished"></translation> + <translation>目标文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="59"/> <source>Output File</source> - <translation type="unfinished"></translation> + <translation>输出文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="75"/> <source>Signature File(.sig) Path</source> - <translation type="unfinished"></translation> + <translation>签名文件(.sig)路径</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="134"/> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="177"/> <source>Open File</source> - <translation type="unfinished"></translation> + <translation>打开文件</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="165"/> <source>Save File</source> - <translation type="unfinished"></translation> + <translation>保存存档</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="194"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="222"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> <source>Couldn't open file</source> - <translation type="unfinished"></translation> + <translation>无法打开文件</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="213"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="224"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="235"/> + <source>Error</source> + <translation>错误</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="214"/> + <source>Error Occurred During Encryption</source> + <translation>加密期间发生错误</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="225"/> + <source>Error Occurred During Decryption</source> + <translation>解密期间发生错误</translation> </message> <message> <location filename="../../src/ui/FileEncryptionDialog.cpp" line="236"/> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="245"/> + <source>Error Occurred During Signature</source> + <translation>签名期间发生错误</translation> + </message> + <message> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="259"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="268"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>文件</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="237"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="260"/> <source>File exists! Do you want to overwrite it?</source> - <translation type="unfinished"></translation> + <translation>文件已存在!你想覆盖它吗?</translation> </message> <message> - <location filename="../../src/ui/FileEncryptionDialog.cpp" line="246"/> + <location filename="../../src/ui/FileEncryptionDialog.cpp" line="269"/> <source>Cannot write file %1: %2.</source> - <translation type="unfinished"></translation> + <translation>无法写入文件%1: +%2。</translation> </message> </context> <context> <name>FilePage</name> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="137"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="161"/> <source>Open</source> - <translation type="unfinished"></translation> + <translation>打开</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="139"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="163"/> <source>Delete</source> - <translation type="unfinished"></translation> + <translation>删除</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="141"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="165"/> <source>Encrypt and Sign</source> - <translation type="unfinished"></translation> + <translation>加密和签名</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="143"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="167"/> <source>Decrypt and Verify</source> - <translation type="unfinished"></translation> + <translation>解密和验证</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="145"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="169"/> <source>Only Sign</source> - <translation type="unfinished"></translation> + <translation>只签名</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="147"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="171"/> <source>Only Verify</source> - <translation type="unfinished"></translation> + <translation>只验证</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="198"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="222"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>警告</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="199"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="223"/> <source>Are you sure you want to delete it?</source> - <translation type="unfinished"></translation> + <translation>你确定你要删除它?</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="209"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="233"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation>错误</translation> </message> <message> - <location filename="../../src/ui/widgets/FilePage.cpp" line="210"/> + <location filename="../../src/ui/widgets/FilePage.cpp" line="234"/> <source>Unable to delete the file or folder.</source> - <translation type="unfinished"></translation> + <translation>无法删除文件或文件夹。</translation> </message> </context> <context> @@ -347,266 +355,281 @@ <message> <location filename="../../src/ui/FindWidget.cpp" line="38"/> <source>Find:</source> - <translation type="unfinished"></translation> + <translation>查找:</translation> </message> </context> <context> <name>GeneralTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="135"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="137"/> <source>Remember Password</source> - <translation type="unfinished"></translation> + <translation>记住密码</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="138"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="140"/> <source>Remember password until closing gpg4usb</source> - <translation type="unfinished"></translation> + <translation>记住密码,直到关闭GPG4USB</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="145"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="147"/> <source>Save Checked Keys</source> - <translation type="unfinished"></translation> + <translation>保存选中密钥</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="148"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="150"/> <source>Save checked private keys on exit and restore them on next start.</source> - <translation type="unfinished"></translation> + <translation>在退出时保存已选中的密钥对并在下次启动时恢复。</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="157"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="159"/> <source>Confirm drag'n'drop key import</source> - <translation type="unfinished"></translation> + <translation>默认拖拽文件'触发密钥导入</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="160"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="162"/> <source>Import files dropped on the keylist without confirmation.</source> - <translation type="unfinished"></translation> + <translation>无需确认导入文件是否要在密钥列表中显示。</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="167"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="169"/> <source>Language</source> - <translation type="unfinished"></translation> + <translation>语言</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="176"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="178"/> <source><b>NOTE: </b> GpgFrontend will restart automatically if you change the language!</source> - <translation type="unfinished"></translation> + <translation><b>注意:如果更改语言,则会自动重启!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="185"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="187"/> <source>Own key</source> - <translation type="unfinished"></translation> + <translation>我的密钥</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="193"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="195"/> <source><none></source> - <translation type="unfinished"></translation> + <translation><无></translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="207"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="209"/> <source>Key pair for synchronization and identity authentication</source> - <translation type="unfinished"></translation> + <translation>用于同步和身份验证的密钥对</translation> </message> </context> <context> <name>GpgME::GpgContext</name> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="90"/> - <source>ENV Loading Failed</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="91"/> - <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/gpg/GpgContext.cpp" line="577"/> + <location filename="../../src/gpg/GpgContext.cpp" line="528"/> <source>Wrong password</source> - <translation type="unfinished"></translation> + <translation>密码错误</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="585"/> + <location filename="../../src/gpg/GpgContext.cpp" line="536"/> <source>Enter Password for</source> - <translation type="unfinished"></translation> + <translation>输入密码</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="589"/> + <location filename="../../src/gpg/GpgContext.cpp" line="540"/> <source>Enter Password</source> - <translation type="unfinished"></translation> + <translation>输入密码</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>Key Selection</source> - <translation type="unfinished"></translation> + <translation>密钥选择</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="764"/> + <location filename="../../src/gpg/GpgContext.cpp" line="706"/> <source>No Private Key Selected</source> - <translation type="unfinished"></translation> + <translation>没有选择私钥</translation> </message> <message> - <location filename="../../src/gpg/GpgContext.cpp" line="804"/> + <location filename="../../src/gpg/GpgContext.cpp" line="746"/> <source>Error in signing:</source> - <translation type="unfinished"></translation> + <translation>签名时出错:</translation> </message> </context> <context> <name>GpgPathsTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="612"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="711"/> <source>Relative path to keydb</source> - <translation type="unfinished"></translation> + <translation>keydB的相对路径</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="625"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="724"/> <source>Current keydb path: </source> - <translation type="unfinished"></translation> + <translation>当前密钥数据库路径:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="630"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="729"/> <source><b>NOTE: </b> Gpg4usb will restart automatically if you change the keydb path!</source> - <translation type="unfinished"></translation> + <translation><b>注意:如果更改密钥数据库路径,则会自动重启!</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="659"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="758"/> <source>Choose keydb directory</source> - <translation type="unfinished"></translation> + <translation>选择密钥数据库目录</translation> </message> </context> <context> <name>ImportFromGnupgPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="292"/> + <location filename="../../src/ui/Wizard.cpp" line="302"/> <source>Import keys...</source> - <translation type="unfinished"></translation> + <translation>导入密钥......</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="293"/> + <location filename="../../src/ui/Wizard.cpp" line="303"/> <source>...from existing GnuPG installation</source> - <translation type="unfinished"></translation> + <translation>...从现有的Gnupg安装</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="295"/> + <location filename="../../src/ui/Wizard.cpp" line="305"/> <source>You can import keys from a locally installed GnuPG.<br><br> The location is read from registry in Windows or assumed to be the .gnupg folder in the your home directory in Linux.<br></source> - <translation type="unfinished"></translation> + <translation>您可以从本地安装的gnupg导入密钥。<br> <br>从Windows中的Registry读取位置,也可以在Linux中的主目录中假定为.gnupg文件夹。<br> <br></translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="299"/> + <location filename="../../src/ui/Wizard.cpp" line="309"/> <source>Import keys from GnuPG</source> - <translation type="unfinished"></translation> + <translation>从Gnupg导入密钥</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation>导入错误</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="313"/> + <location filename="../../src/ui/Wizard.cpp" line="323"/> <source>Couldn't locate GnuPG home directory</source> - <translation type="unfinished"></translation> + <translation>无法找到gnupg主目录</translation> </message> </context> <context> <name>ImportFromGpg4usbPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="215"/> + <location filename="../../src/ui/Wizard.cpp" line="225"/> <source>Import from...</source> - <translation type="unfinished"></translation> + <translation>导入于...</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="216"/> + <location filename="../../src/ui/Wizard.cpp" line="226"/> <source>...existing GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>......现有的GPGFrontend.</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="218"/> + <location filename="../../src/ui/Wizard.cpp" line="228"/> <source>You can import keys and/or settings from existing GPGFrontend. <br><br>Just check what you want to import, click the import button and choose the directory of your other GPGFrontend in the appearing file dialog.</source> - <translation type="unfinished"></translation> + <translation>您可以从现有GPGFrontend导入密钥和/或设置。<br> <br>查看要导入的内容,单击“导入”按钮,然后在“出现的文件”对话框中选择其他GPGFrontend的目录。</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="225"/> + <location filename="../../src/ui/Wizard.cpp" line="235"/> <source>Keys</source> - <translation type="unfinished"></translation> + <translation>密钥</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="229"/> + <location filename="../../src/ui/Wizard.cpp" line="239"/> <source>Configuration</source> - <translation type="unfinished"></translation> + <translation>配置</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="231"/> + <location filename="../../src/ui/Wizard.cpp" line="241"/> <source>Import from GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>从GPGFrontend导入</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="246"/> + <location filename="../../src/ui/Wizard.cpp" line="256"/> <source>Other GPGFrontend directory</source> - <translation type="unfinished"></translation> + <translation>其他GPGFrontend目录</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="265"/> + <location filename="../../src/ui/Wizard.cpp" line="275"/> <source>Configuration Imported</source> - <translation type="unfinished"></translation> + <translation>配置导入</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="266"/> + <location filename="../../src/ui/Wizard.cpp" line="276"/> <source>Imported Configuration from old GPGFrontend.<br>Will now restart to activate the configuration.</source> - <translation type="unfinished"></translation> + <translation>从旧GPGFrontend导入配置。<br>现在将重新启动以激活配置。</translation> </message> </context> <context> <name>InfoBoardWidget</name> <message> - <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="38"/> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="40"/> <source>Import missing key from Keyserver</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器导入丢失的密钥</translation> + </message> + <message> + <location filename="../../src/ui/widgets/InfoBoardWidget.cpp" line="57"/> + <source>Optional Actions Menu</source> + <translation>可选操作菜单</translation> </message> </context> <context> <name>InfoTab</name> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="55"/> - <source><br><center>GPGFrontend is an easy-to-use, compact, <br>cross-platform, and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="74"/> + <source><br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>and installation-free gpg front-end tool.<br>It visualizes most of the common operations of gpg commands.<br>It's licensed under the GPL v3<br><br><b>Developer:</b><br>Saturneric<br><br>If you have any questions or suggestions, raise an issue<br/>at <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> or send a mail to my mailing list at <a href="mailto:[email protected]">[email protected]</a>.</source> + <translation><br><center>GPGFrontend是一个易于使用,紧凑,跨平台,无需安装的GPG前端工具。<br>它可视化GPG命令的大多数常见操作。<br>它使用GPL V3许可证<br> <br> <br> <br> <br> <br> 作者:</b><br>Saturneric<br><br>如果你有任何疑问, 请发起一个issue<br/>到 <a href="https://github.com/saturneric/GpgFrontend">GitHub</a> 或者给我发邮件 <a href="mailto:[email protected]">[email protected]</a>.</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="63"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="82"/> <source><br><br> Built with Qt </source> - <translation type="unfinished"></translation> + <translation><br> <br>构建该程序使用了Qt</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="64"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="83"/> <source> and GPGME </source> - <translation type="unfinished"></translation> + <translation>和gpgme</translation> </message> <message> - <location filename="../../src/ui/AboutDialog.cpp" line="65"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="84"/> <source><br>Built at </source> - <translation type="unfinished"></translation> + <translation><br>构建于</translation> </message> </context> <context> <name>IntroPage</name> <message> <location filename="../../src/ui/Wizard.cpp" line="111"/> - <source>Getting started...</source> - <translation type="unfinished"></translation> + <source>Getting Started...</source> + <translation>入门...</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="112"/> <source>... with GPGFrontend</source> - <translation type="unfinished"></translation> + <translation>...与GPGFrontend.</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="114"/> - <source>To use GPGFrontend for decrypting and signing messages, you need a private key. The next page will help you with key generation or import.<br><br>For more information have a look at the <a href='docu_concepts.html'>concepts</a> (by clicking the link, the page will open in the main window). <br></source> - <translation type="unfinished"></translation> + <source>Welcome to use GPGFrontend for decrypting and signing text or file!</source> + <translation>欢迎使用GPGFrontend进行解密和签名文本或文件!</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="116"/> + <source>is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.</source> + <translation>是一个功能强大,易于使用,小巧,跨平台和无需安装的OpenPGP加密工具。</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="117"/> + <source>For brief information have a look at the</source> + <translation>了解简要信息请查看</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="123"/> + <location filename="../../src/ui/Wizard.cpp" line="118"/> + <source>Overview</source> + <translation>概述</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="119"/> + <source>by clicking the link, the page will open in the web browser</source> + <translation>通过单击链接,页面将在Web浏览器中打开</translation> + </message> + <message> + <location filename="../../src/ui/Wizard.cpp" line="127"/> <source>Choose a Language</source> - <translation type="unfinished"></translation> + <translation>选择一种语言</translation> </message> </context> <context> @@ -614,22 +637,22 @@ <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="31"/> <source>KeyPair</source> - <translation type="unfinished"></translation> + <translation>密钥对</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="32"/> <source>UIDs</source> - <translation type="unfinished"></translation> + <translation>UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="33"/> <source>Subkeys</source> - <translation type="unfinished"></translation> + <translation>子密钥</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyDetailsDialog.cpp" line="40"/> <source>Key Details</source> - <translation type="unfinished"></translation> + <translation>密钥详情</translation> </message> </context> <context> @@ -637,150 +660,159 @@ <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="32"/> <source>Generate Key</source> - <translation type="unfinished"></translation> + <translation>生成密钥</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation>名称必须包含至少五个字符。</translation> </message> <message> <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation>请提供电子邮件地址。</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="78"/> - <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="77"/> + <source> Expiration time no more than 2 years. +</source> + <translation>到期时间不超过2年。</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="104"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="103"/> <source>Generating Key...</source> - <translation type="unfinished"></translation> + <translation>生成密钥......</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="107"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="106"/> <source>Collecting random data for key generation. This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation>收集密钥生成的随机数据。 + 可能还要等一下。 + 加快过程使用您的计算机 + (例如,浏览网,听音乐,......)</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="153"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="150"/> + <source>Key Usage</source> + <translation>密钥用法</translation> + </message> + <message> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="152"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation>加密</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="156"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="155"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation>签名</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="159"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="158"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation>认证</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="162"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="161"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation>验证</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation>成功</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="313"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="312"/> <source>The new key pair has been generated.</source> - <translation type="unfinished"></translation> + <translation>已生成新的密钥对。</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation>失败</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="315"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="314"/> <source>An error occurred during key generation.</source> - <translation type="unfinished"></translation> + <translation>密钥生成期间发生错误。</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="350"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation>名称:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="351"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation>电子邮件地址:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="352"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation>备注:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="353"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation>过期日期:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="354"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>永不过期</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="355"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation>密钥长度(位):</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="356"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation>密钥类型:</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="358"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="357"/> <source>Non Pass Phrase</source> - <translation type="unfinished"></translation> + <translation>无需密码保护</translation> </message> <message> - <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="371"/> + <location filename="../../src/ui/keygen/KeygenDialog.cpp" line="370"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation>基本信息</translation> </message> </context> <context> <name>KeyGenPage</name> <message> - <location filename="../../src/ui/Wizard.cpp" line="356"/> + <location filename="../../src/ui/Wizard.cpp" line="366"/> <source>Create a keypair...</source> - <translation type="unfinished"></translation> + <translation>新建一个密钥对......</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="357"/> + <location filename="../../src/ui/Wizard.cpp" line="367"/> <source>...for decrypting and signing messages</source> - <translation type="unfinished"></translation> + <translation>...用于解密和签名消息</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="358"/> + <location filename="../../src/ui/Wizard.cpp" line="368"/> <source>You should create a new keypair.The pair consists of a public and a private key.<br>Other users can use the public key to encrypt messages for you and verify messages signed by you.You can use the private key to decrypt and sign messages.<br>For more information have a look at the offline tutorial (which then is shown in the main window):</source> - <translation type="unfinished"></translation> + <translation>您应该创建一个新的keypair.该金对由公共和私钥组成。<br>其他用户可以使用公钥来加密为您的消息,并验证由您签名的消息。您可以使用私钥来解密和签名消息。<br> <br>更多信息看看脱机教程(然后在主窗口中显示):</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="365"/> + <location filename="../../src/ui/Wizard.cpp" line="375"/> <source>Offline tutorial</source> - <translation type="unfinished"></translation> + <translation>离线教程</translation> </message> <message> - <location filename="../../src/ui/Wizard.cpp" line="372"/> + <location filename="../../src/ui/Wizard.cpp" line="382"/> <source>Create New Key</source> - <translation type="unfinished"></translation> + <translation>创建新密钥</translation> </message> </context> <context> @@ -789,118 +821,118 @@ <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="53"/> <source>Key Update Details</source> - <translation type="unfinished"></translation> + <translation>密钥更新详细信息</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="34"/> <source>No keys found</source> - <translation type="unfinished"></translation> + <translation>没有找到密钥</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="55"/> <source>Key Import Details</source> - <translation type="unfinished"></translation> + <translation>密钥导入详细信息</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="36"/> <source>No keys found to import</source> - <translation type="unfinished"></translation> + <translation>没有发现导入的密钥</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="64"/> <source>General key info</source> - <translation type="unfinished"></translation> + <translation>通用密钥信息</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="67"/> <source>Considered:</source> - <translation type="unfinished"></translation> + <translation>经过考虑的:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="71"/> <source>Public unchanged:</source> - <translation type="unfinished"></translation> + <translation>公开未改变的:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="76"/> <source>Imported:</source> - <translation type="unfinished"></translation> + <translation>导入:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="81"/> <source>Not imported:</source> - <translation type="unfinished"></translation> + <translation>未导入:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="86"/> <source>Private read:</source> - <translation type="unfinished"></translation> + <translation>私有读取:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="91"/> <source>Private imported:</source> - <translation type="unfinished"></translation> + <translation>私有导入:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="96"/> <source>Private unchanged:</source> - <translation type="unfinished"></translation> + <translation>私有未改变的:</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>名称</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>电子邮件</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Status</source> - <translation type="unfinished"></translation> + <translation>状态</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="111"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation>指纹</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="135"/> <source>private</source> - <translation type="unfinished"></translation> + <translation>私有的</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="138"/> <source>public</source> - <translation type="unfinished"></translation> + <translation>公有</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="141"/> <source>unchanged</source> - <translation type="unfinished"></translation> + <translation>不变的</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="144"/> <source>new key</source> - <translation type="unfinished"></translation> + <translation>新密钥</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="147"/> <source>new subkey</source> - <translation type="unfinished"></translation> + <translation>新子密钥</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="151"/> <source>new signature</source> - <translation type="unfinished"></translation> + <translation>新签名</translation> </message> <message> <location filename="../../src/ui/KeyImportDetailDialog.cpp" line="155"/> <source>new uid</source> - <translation type="unfinished"></translation> + <translation>新UID</translation> </message> </context> <context> @@ -908,309 +940,310 @@ <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>选择</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Type</source> - <translation type="unfinished"></translation> + <translation>类型</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>名称</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="77"/> <source>Email Address</source> - <translation type="unfinished"></translation> + <translation>电子邮件地址</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Usage</source> - <translation type="unfinished"></translation> + <translation>用法</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Validity</source> - <translation type="unfinished"></translation> + <translation>有效性</translation> </message> <message> <location filename="../../src/ui/widgets/KeyList.cpp" line="78"/> <source>Finger Print</source> - <translation type="unfinished"></translation> + <translation>指纹</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="310"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> <source>Import Keys</source> - <translation type="unfinished"></translation> + <translation>导入密钥</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="312"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="317"/> <source>You've dropped something on the table. GpgFrontend will now try to import key(s).</source> - <translation type="unfinished"></translation> + <translation>你拖拽了某些文件到表格上。 + GPGFrontend现在将尝试导入密钥。</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="315"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="320"/> <source>Always import without bothering.</source> - <translation type="unfinished"></translation> + <translation>始终导入而不再询问。</translation> </message> <message> - <location filename="../../src/ui/widgets/KeyList.cpp" line="351"/> + <location filename="../../src/ui/widgets/KeyList.cpp" line="356"/> <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <translation>无法打开文件:</translation> </message> </context> <context> <name>KeyMgmt</name> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="81"/> - <source>KeyPairs Management</source> - <translation type="unfinished"></translation> + <source>Key Pair Management</source> + <translation>密钥对管理</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="88"/> <source>&Open</source> - <translation type="unfinished"></translation> + <translation>&打开</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="89"/> <source>Ctrl+O</source> - <translation type="unfinished"></translation> + <translation>Ctrl + O.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="90"/> <source>Open Key File</source> - <translation type="unfinished"></translation> + <translation>打开密钥文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="93"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&关闭</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="94"/> <source>Ctrl+Q</source> - <translation type="unfinished"></translation> + <translation>Ctrl + Q.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="96"/> <source>Close</source> - <translation type="unfinished"></translation> + <translation>关闭</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="99"/> <source>New Keypair</source> - <translation type="unfinished"></translation> + <translation>新密钥对</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="100"/> <source>Ctrl+N</source> - <translation type="unfinished"></translation> + <translation>Ctrl + N.</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="102"/> <source>Generate KeyPair</source> - <translation type="unfinished"></translation> + <translation>生成密钥对</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="105"/> <source>New Subkey</source> - <translation type="unfinished"></translation> + <translation>新子密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="106"/> <source>Ctrl+Shift+N</source> - <translation type="unfinished"></translation> + <translation>ctrl + shift + n</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="108"/> <source>Generate Subkey For Selected KeyPair</source> - <translation type="unfinished"></translation> + <translation>为选定的keypair生成subkey</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="111"/> <location filename="../../src/ui/KeyMgmt.cpp" line="152"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation>&文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="113"/> <source>Import New Key From File</source> - <translation type="unfinished"></translation> + <translation>从文件导入新密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="116"/> <source>&Clipboard</source> - <translation type="unfinished"></translation> + <translation>&剪贴板</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="118"/> <source>Import New Key From Clipboard</source> - <translation type="unfinished"></translation> + <translation>从剪贴板导入新密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="121"/> <source>&Keyserver</source> - <translation type="unfinished"></translation> + <translation>&密钥服务器</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="123"/> <source>Import New Key From Keyserver</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器导入新密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="126"/> <source>Export To &Clipboard</source> - <translation type="unfinished"></translation> + <translation>导出到剪贴板</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="128"/> <source>Export Selected Key(s) To Clipboard</source> - <translation type="unfinished"></translation> + <translation>将所选密钥导出到剪贴板</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="131"/> <source>Export To &File</source> - <translation type="unfinished"></translation> + <translation>导出到&文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="133"/> <source>Export Selected Key(s) To File</source> - <translation type="unfinished"></translation> + <translation>将所选密钥导出到文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="136"/> <source>Delete Selected Key(s)</source> - <translation type="unfinished"></translation> + <translation>删除所选密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="137"/> <source>Delete the Selected keys</source> - <translation type="unfinished"></translation> + <translation>删除所选密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="140"/> <source>Delete Checked Key(s)</source> - <translation type="unfinished"></translation> + <translation>删除已选密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="141"/> <source>Delete the Checked keys</source> - <translation type="unfinished"></translation> + <translation>删除已选中的密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="145"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation>显示密钥详情</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="146"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation>显示此密钥的详细信息</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="156"/> <source>&Key</source> - <translation type="unfinished"></translation> + <translation>&密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="157"/> <source>&Generate Key</source> - <translation type="unfinished"></translation> + <translation>生成密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="161"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation>&导入密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="173"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="181"/> <source>Generate</source> - <translation type="unfinished"></translation> + <translation>生成</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="182"/> <source>Generate A New Keypair or Subkey</source> - <translation type="unfinished"></translation> + <translation>生成一个新的keypair或subkey</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="191"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation>导入密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="192"/> <source>Import Key</source> - <translation type="unfinished"></translation> + <translation>导入密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Open Key</source> - <translation type="unfinished"></translation> + <translation>打开密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation>密钥文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="213"/> <source>Keyring files</source> - <translation type="unfinished"></translation> + <translation>密钥入文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="218"/> <source>Couldn't Open File: </source> - <translation type="unfinished"></translation> + <translation>无法打开文件:</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="268"/> <source>Deleting Keys</source> - <translation type="unfinished"></translation> + <translation>删除密钥</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="269"/> <source>Are you sure that you want to delete the following keys?</source> - <translation type="unfinished"></translation> + <translation>您确定要删除以下密钥吗?</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="270"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation>行动无法撤消。</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="299"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation>导出文件</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="309"/> <source>key(s) exported</source> - <translation type="unfinished"></translation> + <translation>密钥导出</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="338"/> <location filename="../../src/ui/KeyMgmt.cpp" line="345"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>操作无效</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="339"/> <source>Please select one KeyPair before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>请在执行此操作之前选择一个keypair。</translation> </message> <message> <location filename="../../src/ui/KeyMgmt.cpp" line="346"/> <source>If a key pair does not have a private key then it will not be able to generate sub-keys.</source> - <translation type="unfinished"></translation> + <translation>如果密钥对没有私钥,则它将无法生成子密钥。</translation> </message> </context> <context> @@ -1218,198 +1251,247 @@ <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="40"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>名称</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="41"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>电子邮件</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="42"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>备注</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="55"/> <source>Create New UID</source> - <translation type="unfinished"></translation> + <translation>创建新UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="68"/> <source> Name must contain at least five characters. </source> - <translation type="unfinished"></translation> + <translation>名称必须包含至少五个字符。</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyNewUIDDialog.cpp" line="70"/> <source> Please give a email address. </source> - <translation type="unfinished"></translation> + <translation>请提供电子邮件地址。</translation> </message> </context> <context> <name>KeyPairDetailTab</name> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="32"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> <source>Owner</source> - <translation type="unfinished"></translation> + <translation>所有者</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="33"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> <source>Master Key</source> - <translation type="unfinished"></translation> + <translation>主密钥</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="34"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="36"/> <source>Fingerprint</source> - <translation type="unfinished"></translation> + <translation>指纹</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="35"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="37"/> <source>Additional UIDs</source> - <translation type="unfinished"></translation> + <translation>额外的UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="81"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Exists</source> + <translation>存在</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="58"/> + <source>Not Exists</source> + <translation>不存在</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> <source>Name:</source> - <translation type="unfinished"></translation> + <translation>名称:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="82"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="84"/> <source>Email Address:</source> - <translation type="unfinished"></translation> + <translation>电子邮件地址:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="83"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="85"/> <source>Comment:</source> - <translation type="unfinished"></translation> + <translation>备注:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="88"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation>密钥ID:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="89"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation>算法:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="90"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation>密钥长度:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="91"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> <source>Nominal Usage: </source> - <translation type="unfinished"></translation> + <translation>名义用法:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="92"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> <source>Actual Usage: </source> - <translation type="unfinished"></translation> + <translation>实际用法:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="93"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> <source>Expires on: </source> - <translation type="unfinished"></translation> + <translation>到期:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="94"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="96"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation>最后更新:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="95"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="97"/> <source>Secret Key Existence: </source> - <translation type="unfinished"></translation> + <translation>主密钥存在:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="119"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> <source>Copy</source> - <translation type="unfinished"></translation> + <translation>复制</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="121"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="123"/> <source>copy fingerprint to clipboard</source> - <translation type="unfinished"></translation> + <translation>将指纹复制到剪贴板</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="131"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="133"/> <source>Operations</source> - <translation type="unfinished"></translation> + <translation>操作</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="136"/> + <source>Export Private Key (Include Subkey)</source> + <translation></translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="203"/> + <source>You are about to export your</source> + <translation>你现在正在导出</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="204"/> + <source>PRIVATE KEY</source> + <translation>私钥</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="205"/> + <source>This is NOT your Public Key, so DON'T give it away.</source> + <translation>这不是公钥,所以不要随意放置</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="206"/> + <source>Do you REALLY want to export your PRIVATE KEY?</source> + <translation>你真的想要导出该私钥吗</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="134"/> <source>Export Private Key (Include Subkeys)</source> - <translation type="unfinished"></translation> + <translation type="obsolete">导出私钥(包括子密钥)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="139"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="141"/> <source>Modify Expiration Datetime (Master Key)</source> - <translation type="unfinished"></translation> + <translation>修改到期日期时间(主密钥)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="143"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="146"/> <source>Key Server Operation (Pubkey)</source> - <translation type="unfinished"></translation> + <translation>密钥服务器操作(Pubkey)</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="149"/> + <source>Generate Revoke Certificate</source> + <translation>生成撤销证书</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="166"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="175"/> <source>Warning: The Master Key has expired.</source> - <translation type="unfinished"></translation> + <translation>警告:主密钥已过期。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="169"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="178"/> <source>Warning: The Master Key has been revoked</source> - <translation type="unfinished"></translation> + <translation>警告:主密钥已被撤销</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="192"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="202"/> <source>Exporting private Key</source> - <translation type="unfinished"></translation> + <translation>导出私钥</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="193"/> <source><h3>You are about to export your <font color="red">PRIVATE KEY</font>!</h3> This is NOT your Public Key, so DON'T give it away.<br />Do you REALLY want to export your PRIVATE KEY?</source> - <translation type="unfinished"></translation> + <translation type="vanished"><h3>您即将导出<font color =“红色”>私钥</ font>!</ h3> +这不是你的公钥,所以随意放置它。<br />你真的想导出私钥吗?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="210"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="221"/> <source>Export Key To File</source> - <translation type="unfinished"></translation> + <translation>导出文件</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="211"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="222"/> <source>Key Files</source> - <translation type="unfinished"></translation> + <translation>密钥文件</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Export Error</source> - <translation type="unfinished"></translation> + <translation>导出错误</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="214"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="225"/> <source>Couldn't open %1 for writing</source> - <translation type="unfinished"></translation> + <translation>无法打开%1来写作</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="284"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="295"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>永不过期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="304"/> - <source>Upload Key Pair</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="315"/> + <source>Upload Key Pair to Key Server</source> + <translation>将密钥对上传到密钥服务器</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="306"/> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="317"/> <source>Update Key Pair</source> - <translation type="unfinished"></translation> + <translation>更新密钥对</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="340"/> + <source>Generate revocation certificate</source> + <translation>生成撤销证书</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairDetailTab.cpp" line="343"/> + <source>Revocation Certificates</source> + <translation>撤销证书</translation> </message> </context> <context> @@ -1417,87 +1499,87 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="37"/> <source>Generate A New Subkey</source> - <translation type="unfinished"></translation> + <translation>生成一个新的子密钥</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="53"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> <source>Key ID: </source> - <translation type="unfinished"></translation> + <translation>密钥ID:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="54"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> <source>Algorithm: </source> - <translation type="unfinished"></translation> + <translation>算法:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="55"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> <source>Key Size:</source> - <translation type="unfinished"></translation> + <translation>密钥大小:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="56"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> <source>Usage: </source> - <translation type="unfinished"></translation> + <translation>用法:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="57"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> <source>Expires On </source> - <translation type="unfinished"></translation> + <translation>到期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="58"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> <source>Last Update: </source> - <translation type="unfinished"></translation> + <translation>最后更新:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="59"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> <source>Existence: </source> - <translation type="unfinished"></translation> + <translation>存在:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="60"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="61"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation>指纹:</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Subkey ID</source> - <translation type="unfinished"></translation> + <translation>次要ID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Key Size</source> - <translation type="unfinished"></translation> + <translation>密钥大小</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Algo</source> - <translation type="unfinished"></translation> + <translation>某物</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation>创建日期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="117"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="121"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation>到期日期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="157"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="161"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>永不过期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="181"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="185"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation>永远不会到期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="227"/> + <location filename="../../src/ui/keypair_details/KeyPairSubkeyTab.cpp" line="231"/> <source>Edit Expire Date</source> - <translation type="unfinished"></translation> + <translation>编辑到期日期</translation> </message> </context> <context> @@ -1505,192 +1587,202 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="39"/> <source>New UID</source> - <translation type="unfinished"></translation> + <translation>新UID</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="40"/> <source>UID Management</source> - <translation type="unfinished"></translation> + <translation>UID管理</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="59"/> + <source>UIDs</source> + <translation>UID</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="67"/> + <source>Signature of Selected UID</source> + <translation>已选择UID包含的签名</translation> + </message> + <message> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>选择</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Name</source> - <translation type="unfinished"></translation> + <translation>名称</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Email</source> - <translation type="unfinished"></translation> + <translation>电子邮件</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="100"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="103"/> <source>Comment</source> - <translation type="unfinished"></translation> + <translation>备注</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Key ID</source> - <translation type="unfinished"></translation> + <translation>密钥ID.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Create Date</source> - <translation type="unfinished"></translation> + <translation>创建日期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="123"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="126"/> <source>Expired Date</source> - <translation type="unfinished"></translation> + <translation>过期日期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="216"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="219"/> <source>Never Expires</source> - <translation type="unfinished"></translation> + <translation>永远不会到期</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="234"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="297"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="422"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="437"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="477"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="484"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="237"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="300"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="425"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="440"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="480"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="487"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>操作无效</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="235"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="298"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="238"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="301"/> <source>Please select one or more UIDs before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>请在执行此操作之前选择一个或多个UID。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="260"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="263"/> <source>Sign Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation>签名所选UID(s)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="262"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="265"/> <source>Delete Selected UID(s)</source> - <translation type="unfinished"></translation> + <translation>删除所选的UID(s)</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="281"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="284"/> <source>Successful Operation</source> - <translation type="unfinished"></translation> + <translation>成功运作</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="282"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> <source>Successfully added a new UID.</source> - <translation type="unfinished"></translation> + <translation>成功添加了一个新的UID。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="285"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="327"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="360"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="457"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="504"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="288"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="330"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="363"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="460"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="507"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation>操作失败</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="286"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="328"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="361"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="458"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="505"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="289"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="331"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="364"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="461"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="508"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation>操作期间发生错误。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="310"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="313"/> <source>Deleting UIDs</source> - <translation type="unfinished"></translation> + <translation>删除UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="311"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="314"/> <source>Are you sure that you want to delete the following uids?</source> - <translation type="unfinished"></translation> + <translation>您确定要删除以下UID吗?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="312"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="354"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="451"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="498"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="315"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="357"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="454"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="501"/> <source>The action can not be undone.</source> - <translation type="unfinished"></translation> + <translation>行动无法撤消。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="352"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="355"/> <source>Set Primary UID</source> - <translation type="unfinished"></translation> + <translation>设置主UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="353"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="356"/> <source>Are you sure that you want to set the Primary UID to?</source> - <translation type="unfinished"></translation> + <translation>您确定要将主UID设置为吗?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="392"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="395"/> <source>Set As Primary</source> - <translation type="unfinished"></translation> + <translation>设为主要</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="394"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="397"/> <source>Sign UID</source> - <translation type="unfinished"></translation> + <translation>签名UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="396"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="399"/> <source>Delete UID</source> - <translation type="unfinished"></translation> + <translation>删除UID.</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="423"/> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="438"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="426"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="441"/> <source>Please select one UID before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>在执行此操作之前,请选择一个UID。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="449"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="452"/> <source>Deleting UID</source> - <translation type="unfinished"></translation> + <translation>删除UID</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="450"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="453"/> <source>Are you sure that you want to delete the following uid?</source> - <translation type="unfinished"></translation> + <translation>您确定要删除以下UID吗?</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="466"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="469"/> <source>Delete(Revoke) Key Signature</source> - <translation type="unfinished"></translation> + <translation>删除(撤消)密钥签名</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="478"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="481"/> <source>Please select one Key Signature before doing this operation.</source> - <translation type="unfinished"></translation> + <translation>请在执行此操作之前选择一个密钥签名。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="485"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="488"/> <source>To delete the signature, you need to have its corresponding public key in the local database.</source> - <translation type="unfinished"></translation> + <translation>要删除签名,您需要在本地数据库中拥有其相应的公钥。</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="496"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="499"/> <source>Deleting Key Signature</source> - <translation type="unfinished"></translation> + <translation>删除密钥签名</translation> </message> <message> - <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="497"/> + <location filename="../../src/ui/keypair_details/KeyPairUIDTab.cpp" line="500"/> <source>Are you sure that you want to delete the following signature?</source> - <translation type="unfinished"></translation> + <translation>您确定要删除以下签名吗?</translation> </message> </context> <context> @@ -1698,140 +1790,140 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="40"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&关闭</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="41"/> <source>&Import ALL</source> - <translation type="unfinished"></translation> + <translation>&导入全部</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="42"/> <source>&Search</source> - <translation type="unfinished"></translation> + <translation>&搜索</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="45"/> <source>Search String:</source> - <translation type="unfinished"></translation> + <translation>搜索字符串:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="49"/> <source>Key Server:</source> - <translation type="unfinished"></translation> + <translation>密钥服务器:</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="97"/> <source>Update Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器更新密钥</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="99"/> <source>Import Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器导入密钥</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>UID</source> - <translation type="unfinished"></translation> + <translation>uid</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Creation date</source> - <translation type="unfinished"></translation> + <translation>创建日期</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>KeyID</source> - <translation type="unfinished"></translation> + <translation>keyid.</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="158"/> <source>Tag</source> - <translation type="unfinished"></translation> + <translation>标签</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="179"/> - <source><h4>Text is empty.</h4></source> - <translation type="unfinished"></translation> + <source>Text is empty.</source> + <translation>文本为空</translation> + </message> + <message> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> + <source>Too many responses from keyserver!</source> + <translation>太多来自密钥服务器的响应</translation> + </message> + <message> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> + <source>No keys found, input may be kexId, retrying search with 0x.</source> + <translation>没有找到密钥,尝试使用密钥标识搜索。</translation> + </message> + <message> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> + <source>No keys found containing the search string!</source> + <translation>没有发现包含搜索字符串的密钥!</translation> + </message> + <message> + <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> + <source>Insufficiently specific search string!</source> + <translation>特定的搜索字符串不足!</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="213"/> <source>Not Key Found</source> - <translation type="unfinished"></translation> + <translation>没有密钥</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="216"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="386"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation>超时</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="219"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="389"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation>找不到密钥服务器</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="222"/> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="392"/> <source>Connection Error</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="230"/> - <source><h4>CToo many responses from keyserver!</h4></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="237"/> - <source><h4>No keys found, input may be kexId, retrying search with 0x.</h4></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="242"/> - <source><h4>No keys found containing the search string!</h4></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/KeyServerImportDialog.cpp" line="246"/> - <source><h4>Insufficiently specific search string!</h4></source> - <translation type="unfinished"></translation> + <translation>连接错误</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="274"/> <source>revoked</source> - <translation type="unfinished"></translation> + <translation>撤销</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="277"/> <source>disabled</source> - <translation type="unfinished"></translation> + <translation>禁用</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="317"/> <source><h4>%1 keys found. Double click a key to import it.</h4></source> - <translation type="unfinished"></translation> + <translation>找到<h4>%1密钥。双击将密钥导入它。</ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="383"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation>找不到密钥</translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="410"/> <source><h4>Key Updated</h4></source> - <translation type="unfinished"></translation> + <translation><h4>密钥更新</ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="412"/> <source><h4>Key Imported</h4></source> - <translation type="unfinished"></translation> + <translation><H4>密钥导入</ h4></translation> </message> <message> <location filename="../../src/ui/KeyServerImportDialog.cpp" line="473"/> <source>Upload Keys from Keyserver</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器上传密钥</translation> </message> </context> <context> @@ -1839,22 +1931,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="36"/> <source>Confirm</source> - <translation type="unfinished"></translation> + <translation>确认</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="41"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>永不过期</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="61"/> <source>Operation Failed</source> - <translation type="unfinished"></translation> + <translation>操作失败</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeySetExpireDateDialog.cpp" line="62"/> <source>An error occurred during the operation.</source> - <translation type="unfinished"></translation> + <translation>操作期间发生错误。</translation> </message> </context> <context> @@ -1862,801 +1954,856 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="72"/> <source>Expire Date</source> - <translation type="unfinished"></translation> + <translation>到期日期</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="81"/> <source>Sign For Key's UID(s)</source> - <translation type="unfinished"></translation> + <translation>为密钥的UID签名</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="100"/> <source>Unsuccessful Operation</source> - <translation type="unfinished"></translation> + <translation>不成功的操作</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="101"/> <source>Signature operation failed for UID </source> - <translation type="unfinished"></translation> + <translation>UID的签名操作失败</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="108"/> <source>Operation Complete</source> - <translation type="unfinished"></translation> + <translation>操作完成</translation> </message> <message> <location filename="../../src/ui/keypair_details/KeyUIDSignDialog.cpp" line="109"/> <source>The signature operation of the UID is complete</source> - <translation type="unfinished"></translation> + <translation>UID的签名操作是完整的</translation> </message> </context> <context> <name>KeyUploadDialog</name> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="45"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="49"/> <source>Uploading Public Key</source> - <translation type="unfinished"></translation> + <translation>上传公钥</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="108"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="112"/> <source>Key Not Found</source> - <translation type="unfinished"></translation> + <translation>找不到密钥</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="111"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="115"/> <source>Timeout</source> - <translation type="unfinished"></translation> + <translation>超时</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="114"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="118"/> <source>Key Server Not Found</source> - <translation type="unfinished"></translation> + <translation>找不到密钥服务器</translation> </message> <message> - <location filename="../../src/ui/KeyUploadDialog.cpp" line="117"/> + <location filename="../../src/ui/KeyUploadDialog.cpp" line="121"/> <source>Connection Error</source> - <translation type="unfinished"></translation> + <translation>连接错误</translation> </message> </context> <context> <name>KeyserverTab</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="508"/> - <source>Default Keyserver for import:</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="607"/> + <source>Default Key Server for import:</source> + <translation>导入的默认密钥服务器:</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="525"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="624"/> <source>Add</source> - <translation type="unfinished"></translation> + <translation>添加</translation> </message> </context> <context> <name>MainWindow</name> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="37"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="88"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="220"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="419"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="562"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="705"/> + <location filename="../../src/MainWindow.cpp" line="35"/> + <source>Loading Gnupg</source> + <translation>正在加载Gnupg</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="62"/> + <source>ENV Loading Failed</source> + <translation>ENV Loading失败了</translation> + </message> + <message> + <location filename="../../src/MainWindow.cpp" line="63"/> + <source>Gnupg is not installed correctly, please follow the ReadME instructions to install gnupg and then open GPGFrontend.</source> + <translation>GNUPG未正确安装,请按照README说明安装GNUPG,然后打开GPGFrontend。</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="38"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="117"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="286"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="525"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="702"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="885"/> <source>No Key Selected</source> - <translation type="unfinished"></translation> + <translation>没有选择密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="44"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="426"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="569"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="124"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="532"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="709"/> <source>Invalid Operation</source> - <translation type="unfinished"></translation> + <translation>操作无效</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="45"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="427"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="570"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="533"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="710"/> <source>The selected key contains a key that does not actually have a encrypt usage.<br/></source> - <translation type="unfinished"></translation> + <translation>所选密钥包含一个实际上没有加密使用的密钥。<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="47"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="126"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="300"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="534"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="711"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="899"/> + <source><br/>For example the Following Key: <br/></source> + <translation><br/>例如以下密钥:<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="65"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="554"/> + <source>Encrypting</source> + <translation>加密</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="94"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="368"/> + <source>Function Disabled</source> + <translation>功能已禁用</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="96"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="95"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="369"/> + <source>Please go to the settings interface to enable and configure this function.</source> + <translation>请转到“设置”界面以启用和配置此功能。</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="125"/> <source>The selected key contains a key that does not actually have a signature usage.<br/></source> - <translation type="unfinished"></translation> + <translation>所选密钥包含一个实际上没有签名使用的密钥。<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="142"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="731"/> + <source>Signing</source> + <translation>签名</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="232"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="717"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="186"/> + <source>Decrypting</source> + <translation>解密</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="246"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="816"/> + <source>Verifying</source> + <translation>验证</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="298"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="897"/> <source>Invalid KeyPair</source> - <translation type="unfinished"></translation> + <translation>无效的密钥对</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="233"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="718"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="299"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="898"/> <source>The selected keypair cannot be used for signing and encryption at the same time.<br/></source> - <translation type="unfinished"></translation> + <translation>选定的密钥对不能同时使用用于签名和加密。<br/></translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="244"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="251"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="729"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="736"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="310"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="317"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="909"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="916"/> <source>Incomplete Operation</source> - <translation type="unfinished"></translation> + <translation>不完整的操作</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="245"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="730"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="311"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="910"/> <source>None of the selected key pairs can provide the encryption function.</source> - <translation type="unfinished"></translation> + <translation>没有选定的密钥对可以提供加密功能。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="252"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="737"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="917"/> <source>None of the selected key pairs can provide the signature function.</source> - <translation type="unfinished"></translation> + <translation>没有选定的密钥对可以提供签名功能。</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="335"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="936"/> + <source>Encrypting and Signing</source> + <translation>加密和签名</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1014"/> + <source>Decrypting and Verifying</source> + <translation>解密和验证</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="626"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="789"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>Error</source> - <translation type="unfinished"></translation> + <translation>错误</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="397"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="472"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="539"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="782"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="499"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="590"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="675"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="859"/> + <source>Select a file before doing it.</source> + <translation>在执行此操作之前选择文件。</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="503"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="594"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="863"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="980"/> <source>No permission to read this file.</source> - <translation type="unfinished"></translation> + <translation>无权限读取此文件。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="401"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="476"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="543"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="687"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="786"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="507"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="683"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="867"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="984"/> <source>No permission to create file.</source> - <translation type="unfinished"></translation> + <translation>无权限创建文件。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="406"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="491"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="549"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="692"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="512"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="613"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="689"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="872"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>警告</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="407"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="492"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="550"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="693"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="513"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="614"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="690"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="873"/> <source>The target file already exists, do you need to overwrite it?</source> - <translation type="unfinished"></translation> + <translation>目标文件已存在,您是否需要覆盖它?</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="455"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="519"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="598"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="666"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="767"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="830"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="577"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="659"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="757"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="846"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="964"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1046"/> <source>An error occurred during operation.</source> - <translation type="unfinished"></translation> + <translation>操作期间发生错误。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="627"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="790"/> <source>Please select the appropriate target file or signature file. Ensure that both are in this directory.</source> - <translation type="unfinished"></translation> + <translation>请选择相应的目标文件或签名文件。确保两者都在此目录中。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="631"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="794"/> <source>No permission to read target file.</source> - <translation type="unfinished"></translation> + <translation>无权限读取目标文件。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="635"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="798"/> <source>No permission to read signature file.</source> - <translation type="unfinished"></translation> + <translation>无权限读取签名文件。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="778"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="976"/> <source>Select a file(.gpg/.asc) before doing it.</source> - <translation type="unfinished"></translation> + <translation>在做之前选择一个文件(.gpg / .casc)。</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="46"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="97"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="234"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="428"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="571"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="719"/> - <source><br/>For example the Following Key: <br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1082"/> + <source>Outdated Version</source> + <translation>过时的版本</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="393"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="468"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="535"/> - <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="679"/> - <source>Select a file before doing it.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1083"/> + <source>This version(%1) is out of date, please update the latest version in time. </source> + <translation>此版本(%1)已过期,请及时更新最新版本。</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1085"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1092"/> + <source>You can download the latest version(%1) on Github Releases Page.<br/></source> + <translation>您可以在Github发布页面上下载最新版本(%1)。<br/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1089"/> + <source>Unreleased Version</source> + <translation>未发布的版本</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="54"/> + <location filename="../../src/ui/main_window/MainWindowSlotFunction.cpp" line="1090"/> + <source>This version(%1) has not been officially released and is not recommended for use in a production environment. <br/></source> + <translation>此版本(%1)尚未正式发布,不建议在生产环境中使用。<BR/></translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="58"/> <source>There is one unencrypted file in attachment folder</source> - <translation type="unfinished"></translation> + <translation>附件文件夹中有一个未加密的文件</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source>There are </source> - <translation type="unfinished"></translation> + <translation>有</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="56"/> + <location filename="../../src/ui/main_window/MainWindowSlotUI.cpp" line="60"/> <source> unencrypted files in attachment folder</source> - <translation type="unfinished"></translation> + <translation>附件文件夹中的未加密文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="30"/> <source>&New</source> - <translation type="unfinished"></translation> + <translation>&新标签页</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="36"/> <source>Open a new file</source> - <translation type="unfinished"></translation> + <translation>打开一个新文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="39"/> <source>&Open...</source> - <translation type="unfinished"></translation> + <translation>&打开...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="42"/> <source>Open an existing file</source> - <translation type="unfinished"></translation> + <translation>打开现有文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="45"/> <source>&Browser</source> - <translation type="unfinished"></translation> + <translation>&文件查看器</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="47"/> <source>Open a file browser</source> - <translation type="unfinished"></translation> + <translation>打开文件浏览器</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="50"/> <source>&Save</source> - <translation type="unfinished"></translation> + <translation>&保存</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="53"/> <source>Save the current File</source> - <translation type="unfinished"></translation> + <translation>保存当前文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="56"/> <source>Save &As</source> - <translation type="unfinished"></translation> + <translation>另存为</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="59"/> <source>Save the current File as...</source> - <translation type="unfinished"></translation> + <translation>将当前文件保存为...</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="62"/> <source>&Print</source> - <translation type="unfinished"></translation> + <translation>&打印</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="65"/> <source>Print Document</source> - <translation type="unfinished"></translation> + <translation>打印文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="68"/> <source>&Close</source> - <translation type="unfinished"></translation> + <translation>&关闭标签页</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="70"/> <source>Close file</source> - <translation type="unfinished"></translation> + <translation>关闭文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="73"/> <source>&Quit</source> - <translation type="unfinished"></translation> + <translation>&关闭</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="76"/> <source>Quit Program</source> - <translation type="unfinished"></translation> + <translation>退出程序</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="81"/> <source>&Undo</source> - <translation type="unfinished"></translation> + <translation>&撤消</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="83"/> <source>Undo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation>撤消上次编辑操作</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="86"/> <source>&Redo</source> - <translation type="unfinished"></translation> + <translation>&重做</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="88"/> <source>Redo Last Edit Action</source> - <translation type="unfinished"></translation> + <translation>重做上次编辑动作</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="91"/> <source>Zoom In</source> - <translation type="unfinished"></translation> + <translation>放大</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="95"/> <source>Zoom Out</source> - <translation type="unfinished"></translation> + <translation>缩小</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="99"/> <source>&Paste</source> - <translation type="unfinished"></translation> + <translation>&粘贴</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="102"/> <source>Paste Text From Clipboard</source> - <translation type="unfinished"></translation> + <translation>从剪贴板导出文本</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="105"/> <source>Cu&t</source> - <translation type="unfinished"></translation> + <translation>&剪切</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="108"/> <source>Cut the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <translation>将当前选择的内容切割到剪贴板上</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="112"/> <source>&Copy</source> - <translation type="unfinished"></translation> + <translation>&复制</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="115"/> <source>Copy the current selection's contents to the clipboard</source> - <translation type="unfinished"></translation> + <translation>将当前选择的内容复制到剪贴板</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="119"/> <source>&Quote</source> - <translation type="unfinished"></translation> + <translation>&引用</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="121"/> <source>Quote whole text</source> - <translation type="unfinished"></translation> + <translation>引用整个文本</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="124"/> <source>Select &All</source> - <translation type="unfinished"></translation> + <translation>全选</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="127"/> <source>Select the whole text</source> - <translation type="unfinished"></translation> + <translation>选择整个文本</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="130"/> <source>&Find</source> - <translation type="unfinished"></translation> + <translation>&查找</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="132"/> <source>Find a word</source> - <translation type="unfinished"></translation> + <translation>查找一个单词</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="135"/> <source>Remove &spacing</source> - <translation type="unfinished"></translation> + <translation>删除&间距</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="138"/> <source>Remove double linebreaks, e.g. in pasted text from webmailer</source> - <translation type="unfinished"></translation> + <translation>删除双重剪辑,例如在webmailer的导出文本中</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="141"/> <source>Se&ttings</source> - <translation type="unfinished"></translation> + <translation>&设置</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="142"/> <source>Open settings dialog</source> - <translation type="unfinished"></translation> + <translation>打开设置对话框</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="148"/> <source>&Encrypt</source> - <translation type="unfinished"></translation> + <translation>&加密</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="151"/> <source>Encrypt Message</source> - <translation type="unfinished"></translation> + <translation>加密消息</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="154"/> <source>&Encrypt &Sign</source> - <translation type="unfinished"></translation> + <translation>&加密&签名</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="157"/> <source>Encrypt and Sign Message</source> - <translation type="unfinished"></translation> + <translation>加密和签名消息</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="160"/> <source>&Decrypt</source> - <translation type="unfinished"></translation> + <translation>&解密</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="163"/> <source>Decrypt Message</source> - <translation type="unfinished"></translation> + <translation>解密消息</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="166"/> <source>&Decrypt &Verify</source> - <translation type="unfinished"></translation> + <translation>&解密和验证</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="169"/> <source>Decrypt and Verify Message</source> - <translation type="unfinished"></translation> + <translation>解密和验证消息</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="175"/> <source>&Encrypt File</source> - <translation type="unfinished"></translation> + <translation>加密文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="176"/> <source>Encrypt File</source> - <translation type="unfinished"></translation> + <translation>加密文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="179"/> <source>&Decrypt File</source> - <translation type="unfinished"></translation> + <translation>解密文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="180"/> <source>Decrypt File</source> - <translation type="unfinished"></translation> + <translation>解密文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="183"/> <source>&Sign File</source> - <translation type="unfinished"></translation> + <translation>&签名文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="184"/> <source>Sign File</source> - <translation type="unfinished"></translation> + <translation>签名文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="187"/> <source>&Verify File</source> - <translation type="unfinished"></translation> + <translation>&验证文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="188"/> <source>Verify File</source> - <translation type="unfinished"></translation> + <translation>验证文件</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="192"/> <source>&Sign</source> - <translation type="unfinished"></translation> + <translation>&签名</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="195"/> <source>Sign Message</source> - <translation type="unfinished"></translation> + <translation>签名消息</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="198"/> <source>&Verify</source> - <translation type="unfinished"></translation> + <translation>&验证</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="201"/> <source>Verify Message</source> - <translation type="unfinished"></translation> + <translation>验证消息</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="207"/> <source>&Editor</source> - <translation type="unfinished"></translation> + <translation>&编辑器</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="209"/> <source>Import New Key From Editor</source> - <translation type="unfinished"></translation> + <translation>从编辑器导入新密钥</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="212"/> - <source>Manage &keys</source> - <translation type="unfinished"></translation> + <source>Manage &Keys</source> + <translation>管理和密钥</translation> </message> <message> <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="214"/> <source>Open Keymanagement</source> - <translation type="unfinished"></translation> + <translation>打开密钥管理</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="219"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="220"/> <source>&About</source> - <translation type="unfinished"></translation> + <translation>&关于</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="221"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="222"/> <source>Show the application's About box</source> - <translation type="unfinished"></translation> + <translation>显示应用程序的框</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="224"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="228"/> + <source>&Check for Updates</source> + <translation>检查更新</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <source>Check for updates</source> + <translation>检查更新</translation> + </message> + <message> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="233"/> <source>Open &Wizard</source> - <translation type="unfinished"></translation> + <translation>打开和向导</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="225"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> <source>Open the wizard</source> - <translation type="unfinished"></translation> + <translation>打开向导</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="230"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> <source>Append Selected Key(s) To Text</source> - <translation type="unfinished"></translation> + <translation>将所选密钥附加到文本</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="231"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> <source>Append The Selected Keys To Text in Editor</source> - <translation type="unfinished"></translation> + <translation>将所选密钥附加到编辑器中的文本</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="234"/> - <source>Copy EMail-address</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <source>Copy Email</source> + <translation>复制电子邮件</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="235"/> - <source>Copy selected EMailaddress to clipboard</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <source>Copy selected Email to clipboard</source> + <translation>复制所选电子邮件至剪贴板</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="239"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> <source>Show Key Details</source> - <translation type="unfinished"></translation> + <translation>显示密钥详情</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="240"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="249"/> <source>Show Details for this Key</source> - <translation type="unfinished"></translation> + <translation>显示此密钥的详细信息</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="243"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="252"/> <source>Refresh Key From Key Server</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器的刷新密钥对</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="244"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="253"/> <source>Refresh key from default key server</source> - <translation type="unfinished"></translation> + <translation>刷新默认密钥服务器的密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="247"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="256"/> <source>Upload Public Key(s) To Server</source> - <translation type="unfinished"></translation> + <translation>将公钥上传到服务器</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="248"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="257"/> <source>Upload The Selected Public Keys To Server</source> - <translation type="unfinished"></translation> + <translation>将所选公钥上传到服务器</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="262"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="272"/> <source>Remove PGP Header</source> - <translation type="unfinished"></translation> + <translation>删除PGP标题</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="265"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="275"/> <source>Add PGP Header</source> - <translation type="unfinished"></translation> + <translation>添加PGP标题</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="270"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="280"/> <source>&File</source> - <translation type="unfinished"></translation> + <translation>&文件</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="283"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="293"/> <source>&Edit</source> - <translation type="unfinished"></translation> + <translation>&编辑</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="301"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="311"/> <source>&File...</source> - <translation type="unfinished"></translation> + <translation>&文件...</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="307"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="317"/> <source>&Crypt</source> - <translation type="unfinished"></translation> + <translation>&加密</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="318"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> <source>&Keys</source> - <translation type="unfinished"></translation> + <translation>&密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="319"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="329"/> <source>&Import Key</source> - <translation type="unfinished"></translation> + <translation>&导入密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="328"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="338"/> <source>&Steganography</source> - <translation type="unfinished"></translation> + <translation>隐写术</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="337"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> <source>&View</source> - <translation type="unfinished"></translation> + <translation>&视图</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="339"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="349"/> <source>&Help</source> - <translation type="unfinished"></translation> + <translation>&帮助</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="347"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="358"/> <source>File</source> - <translation type="unfinished"></translation> + <translation>文件</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="355"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="366"/> <source>Crypt</source> - <translation type="unfinished"></translation> + <translation>加密</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="365"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="376"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="370"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="381"/> <source>Edit</source> - <translation type="unfinished"></translation> + <translation>编辑</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="377"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="388"/> <source>Special Edit</source> - <translation type="unfinished"></translation> + <translation>特殊编辑操作</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="389"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="400"/> <source>Import key from...</source> - <translation type="unfinished"></translation> + <translation>从...导入密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="390"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="401"/> <source>Import key</source> - <translation type="unfinished"></translation> + <translation>导入密钥</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="398"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="409"/> <source>Browser to view and operate file</source> - <translation type="unfinished"></translation> + <translation>文件查看器用于浏览和操作文件</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="399"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="410"/> <source>Browser</source> - <translation type="unfinished"></translation> + <translation>文件查看器</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="417"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="428"/> <source>Ready</source> - <translation type="unfinished"></translation> + <translation>准备好</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="424"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="435"/> <source>Key ToolBox</source> - <translation type="unfinished"></translation> + <translation>密钥工具箱</translation> </message> <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="432"/> + <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="443"/> <source>Information Board</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/main_window/MainWindowUI.cpp" line="452"/> - <source>Attached files:</source> - <translation type="unfinished"></translation> - </message> -</context> -<context> - <name>MimeTab</name> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> - <source>Decode quoted printable</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="292"/> - <source>Try to recognize quoted printable.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="296"/> - <source>Parse PGP/MIME (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="299"/> - <source>Try to split attachments from PGP-MIME ecrypted messages.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="304"/> - <source>Open with external application (Experimental)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="306"/> - <source>Open attachments with default application for the filetype.<br> There are at least two possible problems with this behaviour:<ol><li>File needs to be saved unencrypted to attachments folder.<br> Its your job to clean this folder.</li><li>The external application may have its own temp files.</li></ol></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> - <source>Enable opening with external applications.</source> - <translation type="unfinished"></translation> + <translation>信息板</translation> </message> </context> <context> @@ -2664,107 +2811,107 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/gpg/result_analyse/DecryptResultAnalyse.cpp" line="42"/> <source>>Recipient: </source> - <translation type="unfinished"></translation> + <translation>>收件人:</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="35"/> <source>One or More Bad Signatures.</source> - <translation type="unfinished"></translation> + <translation>一个或多个糟糕的签名。</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="40"/> <source>A </source> - <translation type="unfinished"></translation> + <translation>一种</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="42"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation>好的</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="45"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation>坏的</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="48"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation>已到期</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="51"/> <source>Missing Key's </source> - <translation type="unfinished"></translation> + <translation>缺少密钥</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="54"/> <source>Revoked Key's </source> - <translation type="unfinished"></translation> + <translation>撤销密钥</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="57"/> <source>Expired Key's </source> - <translation type="unfinished"></translation> + <translation>过期密钥</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="60"/> <source>Missing CRL's </source> - <translation type="unfinished"></translation> + <translation>缺少CRL</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="64"/> <source>Signature Fully Valid.</source> - <translation type="unfinished"></translation> + <translation>签名完全有效。</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="66"/> <source>Signature NOT Fully Valid.</source> - <translation type="unfinished"></translation> + <translation>签名无效。</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="74"/> <source>Key is NOT present with ID 0x</source> - <translation type="unfinished"></translation> + <translation>密钥不存在ID 0x</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="81"/> <source>A signature could NOT be verified due to a Missing Key </source> - <translation type="unfinished"></translation> + <translation>由于缺少密钥而无法验证签名</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="85"/> <source>A signature is valid but the key used to verify the signature has been revoked </source> - <translation type="unfinished"></translation> + <translation>签名是有效的,但用于验证签名的密钥已被撤销</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="93"/> <source>A signature is valid but expired </source> - <translation type="unfinished"></translation> + <translation>签名有效但已过期</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="100"/> <source>A signature is valid but the key used to verify the signature has expired. </source> - <translation type="unfinished"></translation> + <translation>签名有效,但用于验证签名的密钥已过期。</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="107"/> <source>There was some other error which prevented the signature verification. </source> - <translation type="unfinished"></translation> + <translation>还有一些其他错误阻止了签名验证。</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="113"/> <source>Error for key with fingerprint </source> - <translation type="unfinished"></translation> + <translation>带指纹的密钥错误</translation> </message> <message> <location filename="../../src/gpg/result_analyse/VerifyResultAnalyse.cpp" line="128"/> <source>Signed By: </source> - <translation type="unfinished"></translation> + <translation>被...签名:</translation> </message> </context> <context> @@ -2772,60 +2919,193 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/QuitDialog.cpp" line="29"/> <source>Unsaved Files</source> - <translation type="unfinished"></translation> + <translation>未保存的文件</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="77"/> - <source><h3>%1 files contain unsaved information.<br/>Save the changes before closing?</h3></source> - <translation type="unfinished"></translation> + <source>%1 files contain unsaved information.<br/>Save the changes before closing?</source> + <translation>%1文件包含未保存的信息。<br/>在结束前保存更改?</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="88"/> <source>Check the files you want to save:</source> - <translation type="unfinished"></translation> + <translation>检查要保存的文件:</translation> </message> <message> <location filename="../../src/ui/QuitDialog.cpp" line="89"/> <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <translation><b>注意:</ b>如果您不保存这些文件,则所有更改都会丢失。<br/></translation> + </message> +</context> +<context> + <name>SendMailDialog</name> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="35"/> + <source>Incomplete configuration</source> + <translation>配置不完整</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="36"/> + <source>The SMTP address is empty, please go to the setting interface to complete the configuration.</source> + <translation>SMTP地址为空,请转到设置界面以完成配置。</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="86"/> + <source> Recipient cannot be empty +</source> + <translation>收件人不能空</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="91"/> + <source> One or more Recipient's Email Address is invalid +</source> + <translation>一个或多个收件人的电子邮件地址无效</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="97"/> + <source> Sender cannot be empty +</source> + <translation>发件人不能为空</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="99"/> + <source> Sender's Email Address is invalid +</source> + <translation>发件人的电子邮件地址无效</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail</source> + <translation>失败</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="155"/> + <source>Fail to Connect SMTP Server</source> + <translation>无法连接SMTP服务器</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="160"/> + <source>Fail to Login into SMTP Server</source> + <translation>无法登录SMTP服务器</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="165"/> + <source>Fail to Send Mail to SMTP Server</source> + <translation>无法将邮件发送到SMTP服务器</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Success</source> + <translation>成功</translation> + </message> + <message> + <location filename="../../src/ui/SendMailDialog.cpp" line="171"/> + <source>Succeed in Sending Mail to SMTP Server</source> + <translation>成功向SMTP服务器发送邮件</translation> + </message> +</context> +<context> + <name>SendMailTab</name> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="289"/> + <source>Enable</source> + <translation>使能够</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="311"/> + <source>SMTP Address</source> + <translation>SMTP地址</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="313"/> + <source>Username</source> + <translation>用户名</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="315"/> + <source>Password</source> + <translation>密码</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="317"/> + <source>Port</source> + <translation>港口</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="319"/> + <source>Connection Security</source> + <translation>连接安全</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="322"/> + <source>Default Sender</source> + <translation>默认发件人</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail</source> + <translation>失败</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="404"/> + <source>Fail to Connect SMTP Server</source> + <translation>无法连接SMTP服务器</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="408"/> + <source>Fail to Login</source> + <translation>未登录</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Success</source> + <translation>成功</translation> + </message> + <message> + <location filename="../../src/ui/SettingsDialog.cpp" line="413"/> + <source>Succeed in connecting and login</source> + <translation>成功连接和登录</translation> </message> </context> <context> <name>SettingsDialog</name> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="38"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> <source>General</source> - <translation type="unfinished"></translation> + <translation>通用</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="39"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> <source>Appearance</source> - <translation type="unfinished"></translation> + <translation>外观</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="40"/> - <source>PGP/Mime</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/SettingsDialog.cpp" line="42"/> + <source>Send Mail</source> + <translation>发送邮件</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="41"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> <source>Key Server</source> - <translation type="unfinished"></translation> + <translation>密钥服务器</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="43"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="45"/> <source>Advanced</source> - <translation type="unfinished"></translation> + <translation>高级</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="56"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="58"/> <source>Settings</source> - <translation type="unfinished"></translation> + <translation>设置</translation> </message> <message> - <location filename="../../src/ui/SettingsDialog.cpp" line="101"/> + <location filename="../../src/ui/SettingsDialog.cpp" line="103"/> <source>System Default</source> - <translation type="unfinished"></translation> + <translation>系统默认值</translation> </message> </context> <context> @@ -2833,62 +3113,62 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="46"/> <source>Generate New Subkey</source> - <translation type="unfinished"></translation> + <translation>生成新的子项</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="61"/> <source>Encryption</source> - <translation type="unfinished"></translation> + <translation>加密</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="64"/> <source>Signing</source> - <translation type="unfinished"></translation> + <translation>签名</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="67"/> <source>Certification</source> - <translation type="unfinished"></translation> + <translation>认证</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="70"/> <source>Authentication</source> - <translation type="unfinished"></translation> + <translation>验证</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="114"/> <source>Expiration Date:</source> - <translation type="unfinished"></translation> + <translation>过期日期:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="115"/> <source>Never Expire</source> - <translation type="unfinished"></translation> + <translation>永不过期</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="116"/> <source>KeySize (in Bit):</source> - <translation type="unfinished"></translation> + <translation>keysize(位):</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="117"/> <source>Key Type:</source> - <translation type="unfinished"></translation> + <translation>密钥类型:</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="126"/> <source>Basic Information</source> - <translation type="unfinished"></translation> + <translation>基本信息</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="214"/> <source> Expiration time no more than 2 years. </source> - <translation type="unfinished"></translation> + <translation>到期时间不超过2年。</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="235"/> <source>Generating Subkey...</source> - <translation type="unfinished"></translation> + <translation>生成子密钥......</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="238"/> @@ -2896,90 +3176,129 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL This may take a while. To speed up the process use your computer (e.g. browse the net, listen to music,...)</source> - <translation type="unfinished"></translation> + <translation>收集子项的随机数据。 + 可能还要等一下。 + 加快过程使用您的计算机 + (例如,浏览网,听音乐,......)</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>Success</source> - <translation type="unfinished"></translation> + <translation>成功</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="309"/> <source>The new subkey has been generated.</source> - <translation type="unfinished"></translation> + <translation>已生成新的子项。</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>Failure</source> - <translation type="unfinished"></translation> + <translation>失败</translation> </message> <message> <location filename="../../src/ui/keygen/SubkeyGenerateDialog.cpp" line="311"/> <source>An error occurred during subkey generation.</source> - <translation type="unfinished"></translation> + <translation>子项生成期间发生错误。</translation> </message> </context> <context> <name>TextEdit</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="49"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="53"/> <source>untitled</source> - <translation type="unfinished"></translation> + <translation>无标题</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="99"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="131"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="120"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="200"/> <source>Warning</source> - <translation type="unfinished"></translation> + <translation>警告</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="106"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="121"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="201"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="482"/> + <source>Cannot read file %1: +%2.</source> + <translation>无法读取文件%1: +%2。</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="175"/> <source>Open file</source> - <translation type="unfinished"></translation> + <translation>打开文件</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="251"/> + <source>File</source> + <translation>文件</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="252"/> + <source>Cannot write file %1: +%2.</source> + <translation>无法写入文件%1: +%2。</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="203"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> <source>Save file</source> - <translation type="unfinished"></translation> + <translation>保存存档</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="333"/> + <source>Unsaved document</source> + <translation>未保存的文件</translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="334"/> + <source>The document "%1" has been modified. Do you want to save your changes?<br/></source> + <translation>文档“%1”已被修改。你想保存你的更改吗?<br/></translation> + </message> + <message> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="337"/> + <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> + <translation><b>注意:</ b>如果您不保存这些文件,则所有更改都会丢失。<br/></translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="415"/> + <location filename="../../src/ui/widgets/TextEdit.cpp" line="481"/> <source>Application</source> - <translation type="unfinished"></translation> + <translation>应用</translation> </message> +</context> +<context> + <name>UpdateTab</name> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="100"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="132"/> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="416"/> - <source>Cannot read file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="127"/> + <source>It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.</source> + <translation>建议您始终检查GPGFrontend的版本并升级到最新版本。</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="181"/> - <source>File</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="129"/> + <source>New versions not only represent new features, but also often represent functional and security fixes.</source> + <translation>新版本不仅代表新功能,而且通常代表功能和安全修复。</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="182"/> - <source>Cannot write file %1: -%2.</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="133"/> + <source>Current Version: </source> + <translation>当前版本:</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="267"/> - <source>Unsaved document</source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="141"/> + <source>The current version is inconsistent with the latest version on github.</source> + <translation>当前版本与GitHub上的最新版本不一致。</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="268"/> - <source><h3>The document "%1" has been modified.<br/>Do you want to save your changes?</h3></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="143"/> + <source>Please click <a href="https://github.com/saturneric/GpgFrontend/releases">here</a> to download the latest version.</source> + <translation>请单击<a href="https://github.com/saturneric/gpgfrontend/releases">此处</a>下载最新版本。</translation> </message> <message> - <location filename="../../src/ui/widgets/TextEdit.cpp" line="270"/> - <source><b>Note:</b> If you don't save these files, all changes are lost.<br/></source> - <translation type="unfinished"></translation> + <location filename="../../src/ui/help/AboutDialog.cpp" line="187"/> + <location filename="../../src/ui/help/AboutDialog.cpp" line="209"/> + <source>Latest Version From Github: </source> + <translation>GitHub的最新版本:</translation> </message> </context> <context> @@ -2987,32 +3306,32 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="32"/> <source>Signature Details</source> - <translation type="unfinished"></translation> + <translation>签名细节</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="53"/> <source>Status: </source> - <translation type="unfinished"></translation> + <translation>状态:</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="56"/> <source>No valid input found</source> - <translation type="unfinished"></translation> + <translation>没有找到有效的输入</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="67"/> <source>Error Validating signature</source> - <translation type="unfinished"></translation> + <translation>验证签名时出错</translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="70"/> <source>File was signed on %1 <br/> It Contains:<br/><br/></source> - <translation type="unfinished"></translation> + <translation>文件已签名%1 <br/> <br/> <br/></translation> </message> <message> <location filename="../../src/ui/VerifyDetailsDialog.cpp" line="72"/> <source>Signed on %1 <br/> It Contains:<br /><br/></source> - <translation type="unfinished"></translation> + <translation>签名%1 <br/>它包含:<br /> <br/></translation> </message> </context> <context> @@ -3020,22 +3339,22 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="36"/> <source>Import from keyserver</source> - <translation type="unfinished"></translation> + <translation>从密钥服务器导入</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="39"/> <source>Key not present with id 0x</source> - <translation type="unfinished"></translation> + <translation>密钥不存在ID 0x</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="43"/> <source>Status:</source> - <translation type="unfinished"></translation> + <translation>地位:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="45"/> <source>Key not present in keylist</source> - <translation type="unfinished"></translation> + <translation>密钥不存在于keylist</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="58"/> @@ -3045,7 +3364,7 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="115"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="129"/> <source>Key Information is NOT Available</source> - <translation type="unfinished"></translation> + <translation>密钥信息不可用</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="60"/> @@ -3055,103 +3374,103 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="117"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="131"/> <source>Fingerprint: </source> - <translation type="unfinished"></translation> + <translation>指纹:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="67"/> <source>Status: Cert Revoked</source> - <translation type="unfinished"></translation> + <translation>状态:证书撤销</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="81"/> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="95"/> <source>Status: Signature Expired</source> - <translation type="unfinished"></translation> + <translation>状态:签名已过期</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="96"/> <source>Status: Key Expired</source> - <translation type="unfinished"></translation> + <translation>状态:密钥已过期</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="110"/> <source>Status: General Error</source> - <translation type="unfinished"></translation> + <translation>状态:一般错误</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="124"/> <source>Status: Unknown Error</source> - <translation type="unfinished"></translation> + <translation>状态:未知错误</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="159"/> <source>Signer Name:</source> - <translation type="unfinished"></translation> + <translation>签名者名称:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="160"/> <source>Signer Email:</source> - <translation type="unfinished"></translation> + <translation>签名电子邮件:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="161"/> <source>Key's Fingerprint:</source> - <translation type="unfinished"></translation> + <translation>密钥的指纹:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="162"/> <source>Valid:</source> - <translation type="unfinished"></translation> + <translation>有效的:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="163"/> <source>Flags:</source> - <translation type="unfinished"></translation> + <translation>标志:</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="171"/> <source>Fully Valid</source> - <translation type="unfinished"></translation> + <translation>完全有效</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="173"/> <source>NOT Fully Valid</source> - <translation type="unfinished"></translation> + <translation>没有完全有效</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="180"/> <source>Good </source> - <translation type="unfinished"></translation> + <translation>好的</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="183"/> <source>Bad </source> - <translation type="unfinished"></translation> + <translation>坏的</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="186"/> <source>Expired </source> - <translation type="unfinished"></translation> + <translation>已到期</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="189"/> <source>Missing Key </source> - <translation type="unfinished"></translation> + <translation>缺少密钥</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="192"/> <source>Revoked Key </source> - <translation type="unfinished"></translation> + <translation>撤销密钥</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="195"/> <source>Expired Key </source> - <translation type="unfinished"></translation> + <translation>过期的密钥</translation> </message> <message> <location filename="../../src/ui/widgets/VerifyKeyDetailBox.cpp" line="198"/> <source>Missing CRL </source> - <translation type="unfinished"></translation> + <translation>缺少CRL.</translation> </message> </context> <context> @@ -3159,33 +3478,33 @@ This is NOT your Public Key, so DON'T give it away.<br />Do you REALL <message> <location filename="../../src/ui/Wizard.cpp" line="46"/> <source>First Start Wizard</source> - <translation type="unfinished"></translation> + <translation>首次开始向导</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Import Error</source> - <translation type="unfinished"></translation> + <translation>导入错误</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="76"/> <source>Couldn't locate any keyring file in %1</source> - <translation type="unfinished"></translation> + <translation>无法在%1中定位任何密钥控文件</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="84"/> <location filename="../../src/ui/Wizard.cpp" line="95"/> <source>Import error</source> - <translation type="unfinished"></translation> + <translation>导入错误</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="85"/> <source>Couldn't open private keyringfile: %1</source> - <translation type="unfinished"></translation> + <translation>无法打开私有keyringfile:%1</translation> </message> <message> <location filename="../../src/ui/Wizard.cpp" line="96"/> <source>Couldn't open public keyringfile: %1</source> - <translation type="unfinished"></translation> + <translation>无法打开公钥密钥入文件:%1</translation> </message> </context> </TS> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0d1336ba..ad56423d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ set(ALL_SOURCE_FILE) add_subdirectory(gpg) add_subdirectory(ui) +add_subdirectory(smtp) aux_source_directory(. BASE_SOURCE) @@ -23,6 +24,8 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Release") elseif(LINUX) file(COPY ${CMAKE_SOURCE_DIR}/resource/gpgfrontend DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/share) + else() + set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) endif() else() set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) @@ -33,7 +36,9 @@ message(STATUS "RESOURCE_OUTPUT_DIRECTORY ${RESOURCE_OUTPUT_DIRECTORY}") file(GLOB_RECURSE ALL_SOURCE_FILES RELACTIVE ${CMAKE_SOURCE_DIR}/src/*.cpp) # Set Translation Files -set(QT_TS_FILES gpgfrontend_en_us.ts gpgfrontend_zh_chs.ts gpgfrontend_zh_cht.ts gpg_frontend_fr.ts gpg_frontend_ru.ts) +set(QT_TS_FILES + gpgfrontend_en_us.ts gpgfrontend_zh_cn.ts + gpgfrontend_fr.ts gpgfrontend_ru.ts gpgfrontend_es.ts) list(TRANSFORM QT_TS_FILES PREPEND ${CMAKE_SOURCE_DIR}/resource/ts/) message(STATUS "QT_TS_FILES ${QT_TS_FILES}") set(QT_QM_FILES_OUTPUT_DIR ${RESOURCE_OUTPUT_DIRECTORY}/ts) @@ -44,6 +49,7 @@ add_custom_target(translations DEPENDS ${QON_QM_FILES}) # Set Build Information configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontend.h @ONLY) +configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h @ONLY) # Copy Resource Files file(COPY ${CMAKE_SOURCE_DIR}/resource/css DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) @@ -118,19 +124,19 @@ endif() IF (MINGW) message(STATUS "Link Application Static Library For MINGW") target_link_libraries(${AppName} - gpgfrontend-ui gpg + smtp gpgfrontend-ui gpg Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core crypto ssl) elseif(APPLE) message(STATUS "Link Application Static Library For macOS") target_link_libraries(${AppName} - gpgfrontend-ui gpg + smtp gpgfrontend-ui gpg Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core crypto ssl) else() message(STATUS "Link Application Static Library For UNIX") target_link_libraries(${AppName} - gpgfrontend-ui gpg + smtp gpgfrontend-ui gpg Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core crypto ssl pthread) endif() diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index a59bd01d..eb8b96b1 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -23,208 +23,223 @@ */ #include "MainWindow.h" +#include "ui/help/VersionCheckThread.h" MainWindow::MainWindow() - : appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - - auto waitingDialog = new WaitingDialog(this); - - auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); }); - - ctx_thread->start(); - - while (ctx_thread->isRunning()) - QApplication::processEvents(); - - waitingDialog->close(); - - - if (!mCtx->isGood()) { - QMessageBox::critical( - nullptr, tr("ENV Loading Failed"), - tr("Gnupg is not installed correctly, please follow the ReadME " - "instructions to install gnupg and then open GPGFrontend.")); - QCoreApplication::quit(); - exit(0); - } - - /* get path were app was started */ - setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - qDebug() << "Main Window" << this; - - edit = new TextEdit(this); - setCentralWidget(edit); - - /* the list of Keys available*/ - mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | - KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - this); - mKeyList->setFilter([](const GpgKey &key) -> bool { - if (key.revoked || key.disabled || key.expired) - return false; - else - return true; - }); - mKeyList->slotRefresh(); - - infoBoard = new InfoBoardWidget(this, mCtx, mKeyList); - - /* List of binary Attachments */ - attachmentDockCreated = false; - - /* Variable containing if restart is needed */ - this->slotSetRestartNeeded(false); - - keyMgmt = new KeyMgmt(mCtx, this); - keyMgmt->hide(); - /* test attachmentdir for files alll 15s */ - auto *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder())); - timer->start(5000); - - createActions(); - createMenus(); - createToolBars(); - createStatusBar(); - createDockWindows(); - - connect(edit->tabWidget, SIGNAL(currentChanged(int)), this, - SLOT(slotDisableTabActions(int))); - - mKeyList->addMenuAction(appendSelectedKeysAct); - mKeyList->addMenuAction(copyMailAddressToClipboardAct); - mKeyList->addMenuAction(showKeyDetailsAct); - mKeyList->addMenuAction(refreshKeysFromKeyserverAct); - mKeyList->addMenuAction(uploadKeyToServerAct); - - restoreSettings(); - - // open filename if provided as first command line parameter - QStringList args = qApp->arguments(); - if (args.size() > 1) { - if (!args[1].startsWith("-")) { - if (QFile::exists(args[1])) - edit->loadFile(args[1]); + : appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + + networkAccessManager = new QNetworkAccessManager(this); + + auto waitingDialog = new WaitingDialog(tr("Loading Gnupg"), this); + + // Init Gnupg + auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); }); + ctx_thread->start(); + while (ctx_thread->isRunning()) + QApplication::processEvents(); + waitingDialog->close(); + ctx_thread->deleteLater(); + + QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; + + QNetworkRequest request; + request.setUrl(QUrl(baseUrl)); + + QNetworkReply *replay = networkAccessManager->get(request); + + auto version_thread = new VersionCheckThread(replay); + + connect(version_thread, SIGNAL(finished(QPrivateSignal)), version_thread, SLOT(deleteLater())); + connect(version_thread, SIGNAL(upgradeVersion(const QString &, const QString &)), this, SLOT(slotVersionUpgrade(const QString &, const QString &))); + + version_thread->start(); + + // Check Context Status + if (!mCtx->isGood()) { + QMessageBox::critical( + nullptr, tr("ENV Loading Failed"), + tr("Gnupg is not installed correctly, please follow the ReadME " + "instructions to install gnupg and then open GPGFrontend.")); + QCoreApplication::quit(); + exit(0); + } + + /* get path were app was started */ + setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); + setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + + edit = new TextEdit(this); + setCentralWidget(edit); + + /* the list of Keys available*/ + mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY, + KeyListColumn::TYPE | KeyListColumn::NAME | + KeyListColumn::EmailAddress | + KeyListColumn::Usage | KeyListColumn::Validity, + this); + mKeyList->setFilter([](const GpgKey &key) -> bool { + if (key.revoked || key.disabled || key.expired) + return false; + else + return true; + }); + mKeyList->slotRefresh(); + + infoBoard = new InfoBoardWidget(this, mCtx, mKeyList); + + /* List of binary Attachments */ + attachmentDockCreated = false; + + /* Variable containing if restart is needed */ + this->slotSetRestartNeeded(false); + + keyMgmt = new KeyMgmt(mCtx, this); + keyMgmt->hide(); + /* test attachmentdir for files alll 15s */ + auto *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder())); + timer->start(5000); + + createActions(); + createMenus(); + createToolBars(); + createStatusBar(); + createDockWindows(); + + connect(edit->tabWidget, SIGNAL(currentChanged(int)), this, + SLOT(slotDisableTabActions(int))); + + mKeyList->addMenuAction(appendSelectedKeysAct); + mKeyList->addMenuAction(copyMailAddressToClipboardAct); + mKeyList->addMenuAction(showKeyDetailsAct); + mKeyList->addSeparator(); + mKeyList->addMenuAction(refreshKeysFromKeyserverAct); + mKeyList->addMenuAction(uploadKeyToServerAct); + + restoreSettings(); + + // open filename if provided as first command line parameter + QStringList args = qApp->arguments(); + if (args.size() > 1) { + if (!args[1].startsWith("-")) { + if (QFile::exists(args[1])) + edit->loadFile(args[1]); + } + } + edit->curTextPage()->setFocus(); + this->setMinimumSize(1200, 700); + this->setWindowTitle(qApp->applicationName()); + this->show(); + + // Show wizard, if the don't show wizard message box wasn't checked + // and keylist doesn't contain a private key + qDebug() << "wizard/showWizard" + << settings.value("wizard/showWizard", true).toBool(); + qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull(); + if (settings.value("wizard/showWizard", true).toBool() || + !settings.value("wizard/nextPage").isNull()) { + slotStartWizard(); } - } - edit->curTextPage()->setFocus(); - this->setMinimumSize(1200, 700); - this->setWindowTitle(qApp->applicationName()); - this->show(); - - // Show wizard, if the don't show wizard message box wasn't checked - // and keylist doesn't contain a private key - qDebug() << "wizard/showWizard" - << settings.value("wizard/showWizard", true).toBool(); - qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull(); - if (settings.value("wizard/showWizard", true).toBool() || - !settings.value("wizard/nextPage").isNull()) { - slotStartWizard(); - } } void MainWindow::restoreSettings() { - // state sets pos & size of dock-widgets - this->restoreState(settings.value("window/windowState").toByteArray()); - - // Restore window size & location - if (settings.value("window/windowSave").toBool()) { - QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint(); - QSize size = settings.value("window/size", QSize(800, 450)).toSize(); - this->resize(size); - this->move(pos); - } else { - this->resize(QSize(800, 450)); - this->move(QPoint(100, 100)); - } - - // Iconsize - QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize(); - this->setIconSize(iconSize); - - importButton->setIconSize(iconSize); - fileEncButton->setIconSize(iconSize); - // set list of keyserver if not defined - QStringList *keyServerDefaultList; - keyServerDefaultList = new QStringList("http://keys.gnupg.net"); - keyServerDefaultList->append("https://keyserver.ubuntu.com"); - keyServerDefaultList->append("http://pool.sks-keyservers.net"); - - QStringList keyServerList = - settings.value("keyserver/keyServerList", *keyServerDefaultList) - .toStringList(); - settings.setValue("keyserver/keyServerList", keyServerList); - - // set default keyserver, if it's not set - QString defaultKeyServer = settings - .value("keyserver/defaultKeyServer", - QString("https://keyserver.ubuntu.com")) - .toString(); - settings.setValue("keyserver/defaultKeyServer", defaultKeyServer); - - // Iconstyle - Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>( - settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon) - .toUInt()); - this->setToolButtonStyle(buttonStyle); - importButton->setToolButtonStyle(buttonStyle); - fileEncButton->setToolButtonStyle(buttonStyle); - - // Checked Keys - if (settings.value("keys/saveKeyChecked").toBool()) { - QStringList keyIds = - settings.value("keys/savedCheckedKeyList").toStringList(); - mKeyList->setChecked(&keyIds); - } + // state sets pos & size of dock-widgets + this->restoreState(settings.value("window/windowState").toByteArray()); + + // Restore window size & location + if (settings.value("window/windowSave").toBool()) { + QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint(); + QSize size = settings.value("window/size", QSize(800, 450)).toSize(); + this->resize(size); + this->move(pos); + } else { + this->resize(QSize(800, 450)); + this->move(QPoint(100, 100)); + } + + // Iconsize + QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize(); + this->setIconSize(iconSize); + + importButton->setIconSize(iconSize); + fileEncButton->setIconSize(iconSize); + // set list of keyserver if not defined + QStringList *keyServerDefaultList; + keyServerDefaultList = new QStringList("http://keys.gnupg.net"); + keyServerDefaultList->append("https://keyserver.ubuntu.com"); + keyServerDefaultList->append("http://pool.sks-keyservers.net"); + + QStringList keyServerList = + settings.value("keyserver/keyServerList", *keyServerDefaultList) + .toStringList(); + settings.setValue("keyserver/keyServerList", keyServerList); + + // set default keyserver, if it's not set + QString defaultKeyServer = settings + .value("keyserver/defaultKeyServer", + QString("https://keyserver.ubuntu.com")) + .toString(); + settings.setValue("keyserver/defaultKeyServer", defaultKeyServer); + + // Iconstyle + Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>( + settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon) + .toUInt()); + this->setToolButtonStyle(buttonStyle); + importButton->setToolButtonStyle(buttonStyle); + fileEncButton->setToolButtonStyle(buttonStyle); + + // Checked Keys + if (settings.value("keys/saveKeyChecked").toBool()) { + QStringList keyIds = + settings.value("keys/savedCheckedKeyList").toStringList(); + mKeyList->setChecked(&keyIds); + } } void MainWindow::saveSettings() { - // window position and size - settings.setValue("window/windowState", saveState()); - settings.setValue("window/pos", pos()); - settings.setValue("window/size", size()); - - // keyid-list of private checked keys - if (settings.value("keys/saveKeyChecked").toBool()) { - QStringList *keyIds = mKeyList->getChecked(); - if (!keyIds->isEmpty()) { - settings.setValue("keys/savedCheckedKeyList", *keyIds); + // window position and size + settings.setValue("window/windowState", saveState()); + settings.setValue("window/pos", pos()); + settings.setValue("window/size", size()); + + // keyid-list of private checked keys + if (settings.value("keys/saveKeyChecked").toBool()) { + QStringList *keyIds = mKeyList->getChecked(); + if (!keyIds->isEmpty()) { + settings.setValue("keys/savedCheckedKeyList", *keyIds); + } else { + settings.setValue("keys/savedCheckedKeyList", ""); + } } else { - settings.setValue("keys/savedCheckedKeyList", ""); + settings.remove("keys/savedCheckedKeyList"); } - } else { - settings.remove("keys/savedCheckedKeyList"); - } } void MainWindow::closeAttachmentDock() { - if (!attachmentDockCreated) { - return; - } - attachmentDock->close(); - attachmentDock->deleteLater(); - attachmentDockCreated = false; + if (!attachmentDockCreated) { + return; + } + attachmentDock->close(); + attachmentDock->deleteLater(); + attachmentDockCreated = false; } void MainWindow::closeEvent(QCloseEvent *event) { - /* - * ask to save changes, if there are - * modified documents in any tab - */ - if (edit->maybeSaveAnyTab()) { - saveSettings(); - event->accept(); - } else { - event->ignore(); - } - - // clear password from memory - mCtx->clearPasswordCache(); + /* + * ask to save changes, if there are + * modified documents in any tab + */ + if (edit->maybeSaveAnyTab()) { + saveSettings(); + event->accept(); + } else { + event->ignore(); + } + + // clear password from memory + mCtx->clearPasswordCache(); } diff --git a/src/Mime.cpp b/src/Mime.cpp deleted file mode 100644 index 8e4c8d72..00000000 --- a/src/Mime.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -/* TODO: proper import / copyright statement - * - */ - -#include "Mime.h" - -Mime::Mime(QByteArray *message) { - splitParts(message); - /* - mMessage = message; - int bStart = mMessage->indexOf("boundary=\"") + 10 ; - int bEnd = mMessage->indexOf("\"\n", bStart ); - - qDebug() << "bStart: " << bStart << " bEnd: " << bEnd; - mBoundary = new QByteArray(mMessage->mid(bStart, bEnd - bStart)); - qDebug() << "boundary: " << *mBoundary; - - Part *p1 = new Part(); - - int nb = mMessage->indexOf(*mBoundary, bEnd) + mBoundary->length() +1 ; - qDebug() << "nb: " << nb; - int eh = mMessage->indexOf("\n\n", nb); - qDebug() << "eh: " << eh; - QByteArray *header = new QByteArray(mMessage->mid(nb , eh - nb)); - qDebug() << "header:" << header; - - // split header at newlines - foreach(QByteArray tmp , header->split(* "\n")) { - // split lines at : - QList<QByteArray> tmp2 = tmp.split(* ":"); - p1->header.insert(QString(tmp2[0].trimmed()), QString(tmp2[1].trimmed())); - } - - QHashIterator<QString, QString> i(p1->header); - while (i.hasNext()) { - i.next(); - qDebug() << "found: " << i.key() << ":" << i.value() << endl; - } - - int nb2 = mMessage->indexOf(*mBoundary, eh); - - p1->body = mMessage->mid(eh , nb2 - eh); - - QTextCodec *codec = QTextCodec::codecForName("ISO-8859-15"); - QString qs = codec->toUnicode(p1->body); - qDebug() << "body: " << qs; - */ -} - -Mime::~Mime() -= default; - -void Mime::splitParts(QByteArray *message) { - int pos1, pos2, headEnd; - MimePart p_tmp; - - // find the boundary - pos1 = message->indexOf("boundary=\"") + 10; - pos2 = message->indexOf("\"\n", pos1); - QByteArray boundary = message->mid(pos1, pos2 - pos1); - //qDebug() << "boundary: " << boundary; - - while (pos2 > pos1) { - - pos1 = message->indexOf(boundary, pos2) + boundary.length() + 1; - headEnd = message->indexOf("\n\n", pos1); - if (headEnd < 0) - break; - QByteArray header = message->mid(pos1, headEnd - pos1); - - p_tmp.header = parseHeader(&header); - - pos2 = message->indexOf(boundary, headEnd); - p_tmp.body = message->mid(headEnd, pos2 - headEnd); - - mPartList.append(p_tmp); - } -} - -Header Mime::parseHeader(QByteArray *header) { - - QList<HeadElem> ret; - - /** http://www.aspnetmime.com/help/welcome/overviewmimeii.html : - * If a line starts with any white space, that line is said to be 'folded' and is actually - * part of the header above it. - */ - header->replace("\n ", " "); - - //split header at newlines - foreach(QByteArray line, header->split(*"\n")) { - HeadElem elem; - //split lines at : - QList<QByteArray> tmp2 = line.split(*":"); - elem.name = tmp2[0].trimmed(); - if (tmp2[1].contains(';')) { - // split lines at ; - // TODO: what if ; is inside "" - QList<QByteArray> tmp3 = tmp2[1].split(*";"); - elem.value = QString(tmp3.takeFirst().trimmed()); - foreach(QByteArray tmp4, tmp3) { - QList<QByteArray> tmp5 = tmp4.split(*"="); - elem.params.insert(QString(tmp5[0].trimmed()), QString(tmp5[1].trimmed())); - } - } else { - elem.value = tmp2[1].trimmed(); - } - ret.append(elem); - } - return Header(ret); -} - -Header Mime::getHeader(const QByteArray *message) { - int headEnd = message->indexOf("\n\n"); - QByteArray header = message->mid(0, headEnd); - return parseHeader(&header); -} - -bool Mime::isMultipart(QByteArray *message) { - return message->startsWith("Content-Type: multipart/mixed;"); -} - -/** - * if Content-Type is specified, it should be mime - * - */ -bool Mime::isMime(const QByteArray *message) { - return message->startsWith("Content-Type:"); -} - -/*** - * quotedPrintableDecode copied from KCodecs, where it is stated: - - The quoted-printable codec as described in RFC 2045, section 6.7. is by - Rik Hemsley (C) 2001. - - */ - -static const char hexChars[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -/******************************** KCodecs ********************************/ -// strchr(3) for broken systems. -static int rikFindChar(const char *_s, const char c) { - const char *s = _s; - - while (true) { - if ((0 == *s) || (c == *s)) break; - ++s; - if ((0 == *s) || (c == *s)) break; - ++s; - if ((0 == *s) || (c == *s)) break; - ++s; - if ((0 == *s) || (c == *s)) break; - ++s; - } - - return static_cast<int>(s - _s); -} - -void Mime::quotedPrintableDecode(const QByteArray &in, QByteArray &out) { - // clear out the output buffer - out.resize(0); - if (in.isEmpty()) - return; - - char *cursor; - const char *data; - const size_t length = in.size(); - - data = in.data(); - out.resize(static_cast<int>(length)); - cursor = out.data(); - - for (unsigned int i = 0; i < length; i++) { - char c(in[i]); - - if ('=' == c) { - if (i < length - 2) { - char c1 = in[i + 1]; - char c2 = in[i + 2]; - - if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) { - // Soft line break. No output. - if ('\r' == c1) - i += 2; // CRLF line breaks - else - i += 1; - } else { - // =XX encoded byte. - - int hexChar0 = rikFindChar(hexChars, c1); - int hexChar1 = rikFindChar(hexChars, c2); - - if (hexChar0 < 16 && hexChar1 < 16) { - *cursor++ = char((hexChar0 * 16) | hexChar1); - i += 2; - } - } - } - } else { - *cursor++ = c; - } - } - - out.truncate(static_cast<int>(cursor - out.data())); -} diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index e94ce1ab..0462433d 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -24,8 +24,8 @@ #include "gpg/GpgContext.h" +#include <functional> #include <unistd.h> /* contains read/write */ -#include <Mime.h> #ifdef _WIN32 @@ -73,8 +73,10 @@ namespace GpgME { << engineInfo->home_dir << engineInfo->version; if (engineInfo->protocol == GPGME_PROTOCOL_GPGCONF && strcmp(engineInfo->version, "1.0.0") != 0) find_gpgconf = true; - if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0) + if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0) { + gpgExec = engineInfo->file_name; find_openpgp = true; + } if (engineInfo->protocol == GPGME_PROTOCOL_CMS && strcmp(engineInfo->version, "1.0.0") != 0) find_cms = true; if (engineInfo->protocol == GPGME_PROTOCOL_ASSUAN) @@ -430,38 +432,6 @@ namespace GpgME { return err; } - - /** - * if this is mime, split text and attachments... - * message contains only text afterwards - */ - void parseMime(QByteArray *message) { - - QString pText; - bool show_ma_dock = false; - - Mime *mime = new Mime(message); - for (MimePart tmp : mime->parts()) { - if (tmp.header.getValue("Content-Type") == "text/plain" && - tmp.header.getValue("Content-Transfer-Encoding") != "base64") { - QByteArray body; - if (tmp.header.getValue("Content-Transfer-Encoding") == "quoted-printable") { - Mime::quotedPrintableDecode(tmp.body, body); - } else { - body = tmp.body; - } - pText.append(QString(body)); - } else { - // TODO - show_ma_dock = true; - } - } - *message = pText.toUtf8(); - if (show_ma_dock) { - // TODO - } - } - /** Decrypt QByteAarray, return QByteArray * mainly from http://basket.kde.org/ (kgpgme.cpp) */ @@ -496,28 +466,6 @@ namespace GpgME { gpgme_data_release(dataOut); } - /* - * 1) is it mime (content-type:) - * 2) parse header - * 2) choose action depending on content-type - */ - if (Mime::isMime(outBuffer)) { - Header header = Mime::getHeader(outBuffer); - // is it multipart, is multipart-parsing enabled - if (header.getValue("Content-Type") == "multipart/mixed" - && settings.value("mime/parseMime").toBool()) { - parseMime(outBuffer); - } else if (header.getValue("Content-Type") == "text/plain" - && settings.value("mime/parseQP").toBool()) { - if (header.getValue("Content-Transfer-Encoding") == "quoted-printable") { - auto *decoded = new QByteArray(); - Mime::quotedPrintableDecode(*outBuffer, *decoded); - //TODO: remove header - outBuffer = decoded; - } - } - } - if (result != nullptr) { *result = m_result; } @@ -659,16 +607,16 @@ namespace GpgME { bool GpgContext::exportSecretKey(const GpgKey &key, QByteArray *outBuffer) { qDebug() << "Export Secret Key" << key.id; gpgme_key_t target_key[2] = { - key.key_refer, - nullptr + key.key_refer, + nullptr }; gpgme_data_t dataOut; gpgme_data_new(&dataOut); // export private key to outBuffer - gpgme_error_t error = gpgme_op_export_keys(mCtx, target_key,GPGME_EXPORT_MODE_SECRET, dataOut); + gpgme_error_t error = gpgme_op_export_keys(mCtx, target_key, GPGME_EXPORT_MODE_SECRET, dataOut); - if(gpgme_err_code(error) != GPG_ERR_NO_ERROR) { + if (gpgme_err_code(error) != GPG_ERR_NO_ERROR) { checkErr(error); gpgme_data_release(dataOut); return false; @@ -680,20 +628,31 @@ namespace GpgME { } /** return type should be gpgme_error_t*/ - void GpgContext::executeGpgCommand(const QStringList &arguments, QByteArray *stdOut, QByteArray *stdErr) { + QProcess * GpgContext::executeGpgCommand(const QStringList &arguments, QByteArray *stdOut, QByteArray *stdErr, + const std::function<void(QProcess *)> &interactFunc) { QStringList args; - args << "--homedir" << gpgKeys << "--batch" << arguments; + args << arguments; + + auto *gpgProcess = new QProcess(this); + qDebug() << "gpgExec" << gpgExec << args; + + gpgProcess->setReadChannel(QProcess::StandardOutput); + connect(gpgProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + gpgProcess, SLOT(deleteLater())); + connect(gpgProcess, &QProcess::readyReadStandardOutput, this, [gpgProcess, interactFunc]() { + qDebug() << "Function Called" << &gpgProcess; + // interactFunc(gpgProcess); + }); - qDebug() << args; - QProcess gpg; - // qDebug() << "engine->file_name" << engine->file_name; + gpgProcess->start(gpgExec, args); - gpg.start(gpgBin, args); - gpg.waitForFinished(); + if (gpgProcess->waitForStarted()){ + qDebug() << "Gpg Process Started Success"; + } else { + qDebug() << "Gpg Process Started Failed"; + } - *stdOut = gpg.readAllStandardOutput(); - *stdErr = gpg.readAllStandardError(); - qDebug() << *stdOut; + return gpgProcess; } /*** @@ -734,26 +693,6 @@ namespace GpgME { return gpgmeError; } - /*** - * return type should contain: - * -> list of sigs - * -> valid - * -> decrypted message - */ - //void GpgContext::decryptVerify(QByteArray in) { - - /* gpgme_error_t err; - gpgme_data_t in, out; - - gpgme_decrypt_result_t decrypt_result; - gpgme_verify_result_t verify_result; - - err = gpgme_op_decrypt_verify (mCtx, in, out); - decrypt_result = gpgme_op_decrypt_result (mCtx); - - verify_result = gpgme_op_verify_result (mCtx); - */ - //} gpg_error_t GpgContext::sign(const QVector<GpgKey> &keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached, gpgme_sign_result_t *result) { @@ -962,7 +901,7 @@ namespace GpgME { void GpgContext::setSigners(const QVector<GpgKey> &keys) { gpgme_signers_clear(mCtx); for (const auto &key : keys) { - if(checkIfKeyCanSign(key)) { + if (checkIfKeyCanSign(key)) { auto gpgmeError = gpgme_signers_add(mCtx, key.key_refer); checkErr(gpgmeError); } @@ -1180,7 +1119,7 @@ namespace GpgME { } } - if(gpgme_err_code(err) != GPG_ERR_NO_ERROR) + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) checkErr(err); if (dataIn) { @@ -1240,11 +1179,11 @@ namespace GpgME { return false; } - for (const auto& key : keys) { + for (const auto &key : keys) { err = gpgme_data_new(&dataOut); checkErr(err); - err = gpgme_op_export(mCtx,key.id.toUtf8().constData(), 0, dataOut); + err = gpgme_op_export(mCtx, key.id.toUtf8().constData(), 0, dataOut); checkErr(err); read_bytes = gpgme_data_seek(dataOut, 0, SEEK_END); @@ -1255,4 +1194,41 @@ namespace GpgME { } return true; } + + QProcess * GpgContext::generateRevokeCert(const GpgKey &key, const QString &outputFileName) { + QByteArray out, stdErr; + auto process = executeGpgCommand({ + "--command-fd", + "0", + "--status-fd", "1", + "-o", + outputFileName, + "--gen-revoke", + key.fpr + }, &out, &stdErr, + [](QProcess *proc) { + qDebug() << "Function Called" << proc; + while (proc->canReadLine()) { + const QString line = QString::fromUtf8(proc->readLine()).trimmed(); + // Command-fd is a stable interface, while this is all kind of hacky we + // are on a deadline :-/ + if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) { + proc->write("y\n"); + } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.code")) { + proc->write("0\n"); + } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.text")) { + proc->write("\n"); + } else if (line == QLatin1String("[GNUPG:] GET_BOOL openfile.overwrite.okay")) { + // We asked before + proc->write("y\n"); + } else if (line == QLatin1String("[GNUPG:] GET_BOOL ask_revocation_reason.okay")) { + proc->write("y\n"); + } + } + }); + + qDebug() << "GenerateRevokeCert Process" << process; + + return process; + } } diff --git a/src/main.cpp b/src/main.cpp index 00ab2738..ff3b0bb4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ */ #include "MainWindow.h" +#include "GpgFrontendBuildInfo.h" int main(int argc, char *argv[]) { @@ -61,7 +62,7 @@ int main(int argc, char *argv[]) { QTranslator translator, translator2; int return_from_event_loop_code; - qDebug() << settings.fileName(); + qDebug() << "Resource Directory" << RESOURCE_DIR(appPath); do { QApplication::removeTranslator(&translator); diff --git a/src/smtp/CMakeLists.txt b/src/smtp/CMakeLists.txt new file mode 100644 index 00000000..8e341f98 --- /dev/null +++ b/src/smtp/CMakeLists.txt @@ -0,0 +1,6 @@ +aux_source_directory(. SMTP_MIME_SOURCE) + +add_library(smtp STATIC ${SMTP_MIME_SOURCE}) + +target_link_libraries(smtp + Qt5::Network Qt5::Core) diff --git a/src/smtp/emailaddress.cpp b/src/smtp/emailaddress.cpp new file mode 100644 index 00000000..c0ecaa0d --- /dev/null +++ b/src/smtp/emailaddress.cpp @@ -0,0 +1,44 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/emailaddress.h" + +/* [1] Constructors and Destructors */ + +EmailAddress::EmailAddress(const QString &address, const QString &name) { + this->address = address; + this->name = name; +} + +EmailAddress::~EmailAddress() {} + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void EmailAddress::setName(const QString &name) { this->name = name; } + +void EmailAddress::setAddress(const QString &address) { + this->address = address; +} + +const QString &EmailAddress::getName() const { return name; } + +const QString &EmailAddress::getAddress() const { return address; } + +/* [2] --- */ diff --git a/src/smtp/mimeattachment.cpp b/src/smtp/mimeattachment.cpp new file mode 100644 index 00000000..033eecfb --- /dev/null +++ b/src/smtp/mimeattachment.cpp @@ -0,0 +1,43 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimeattachment.h" +#include <QFileInfo> + +/* [1] Constructors and Destructors */ + +MimeAttachment::MimeAttachment(QFile *file) : MimeFile(file) {} + +MimeAttachment::MimeAttachment(const QByteArray &stream, + const QString &fileName) + : MimeFile(stream, fileName) {} + +MimeAttachment::~MimeAttachment() = default; + +/* [1] --- */ + +/* [2] Protected methods */ + +void MimeAttachment::prepare() { + this->header += "Content-disposition: attachment\r\n"; + + /* !!! IMPORTANT !!! */ + MimeFile::prepare(); +} + +/* [2] --- */ diff --git a/src/smtp/mimecontentformatter.cpp b/src/smtp/mimecontentformatter.cpp new file mode 100644 index 00000000..8f538457 --- /dev/null +++ b/src/smtp/mimecontentformatter.cpp @@ -0,0 +1,59 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimecontentformatter.h" + +MimeContentFormatter::MimeContentFormatter(int max_length) + : max_length(max_length) {} + +QString MimeContentFormatter::format(const QString &content, + bool quotedPrintable) const { + + QString out; + + int chars = 0; + for (auto i : content) { + chars++; + if (!quotedPrintable) { + if (chars > max_length) { + out.append("\r\n"); + chars = 1; + } + } else { + if (i == '\n') { // new line + out.append(i); + chars = 0; + continue; + } + + if ((chars > max_length - 1) || + ((i == '=') && (chars > max_length - 3))) { + out.append('='); + out.append("\r\n"); + chars = 1; + } + } + out.append(i); + } + + return out; +} + +void MimeContentFormatter::setMaxLength(int l) { max_length = l; } + +int MimeContentFormatter::getMaxLength() const { return max_length; } diff --git a/src/smtp/mimefile.cpp b/src/smtp/mimefile.cpp new file mode 100644 index 00000000..4f095b84 --- /dev/null +++ b/src/smtp/mimefile.cpp @@ -0,0 +1,61 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimefile.h" +#include <QFileInfo> + +/* [1] Constructors and Destructors */ + +MimeFile::MimeFile(QFile *file) { + this->file = file; + this->cType = "application/octet-stream"; + this->cName = QFileInfo(*file).fileName(); + this->cEncoding = Base64; +} + +MimeFile::MimeFile(const QByteArray &stream, const QString &fileName) { + this->cEncoding = Base64; + this->cType = "application/octet-stream"; + this->file = nullptr; + this->cName = fileName; + this->content = stream; +} + +MimeFile::~MimeFile() { + delete file; +} + +/* [1] --- */ + +/* [2] Getters and setters */ + +/* [2] --- */ + +/* [3] Protected methods */ + +void MimeFile::prepare() { + if (this->file) { + file->open(QIODevice::ReadOnly); + this->content = file->readAll(); + file->close(); + } + /* !!! IMPORTANT !!!! */ + MimePart::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/mimehtml.cpp b/src/smtp/mimehtml.cpp new file mode 100644 index 00000000..9f3a53c3 --- /dev/null +++ b/src/smtp/mimehtml.cpp @@ -0,0 +1,46 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimehtml.h" + +/* [1] Constructors and Destructors */ + +MimeHtml::MimeHtml(const QString &html) : MimeText(html) { + this->cType = "text/html"; +} + +MimeHtml::~MimeHtml() = default; + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void MimeHtml::setHtml(const QString &html) { this->text = html; } + +const QString &MimeHtml::getHtml() const { return text; } + +/* [2] --- */ + +/* [3] Protected methods */ + +void MimeHtml::prepare() { + /* !!! IMPORTANT !!! */ + MimeText::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/mimeinlinefile.cpp b/src/smtp/mimeinlinefile.cpp new file mode 100644 index 00000000..a49167e8 --- /dev/null +++ b/src/smtp/mimeinlinefile.cpp @@ -0,0 +1,42 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimeinlinefile.h" + +/* [1] Constructors and Destructors */ + +MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {} + +MimeInlineFile::~MimeInlineFile() = default; + +/* [1] --- */ + +/* [2] Getters and Setters */ + +/* [2] --- */ + +/* [3] Protected methods */ + +void MimeInlineFile::prepare() { + this->header += "Content-Disposition: inline\r\n"; + + /* !!! IMPORTANT !!! */ + MimeFile::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/mimemessage.cpp b/src/smtp/mimemessage.cpp new file mode 100644 index 00000000..cf653e0a --- /dev/null +++ b/src/smtp/mimemessage.cpp @@ -0,0 +1,308 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimemessage.h" +#include "smtp/quotedprintable.h" + +#include <QDateTime> +#include <QLocale> +#include <typeinfo> + +/* [1] Constructors and Destructors */ +MimeMessage::MimeMessage(bool createAutoMimeContent) + : replyTo(nullptr), hEncoding(MimePart::_8Bit) { + if (createAutoMimeContent) + this->content = new MimeMultiPart(); + + autoMimeContentCreated = createAutoMimeContent; +} + +MimeMessage::~MimeMessage() { + if (this->autoMimeContentCreated) { + this->autoMimeContentCreated = false; + delete (this->content); + } +} + +/* [1] --- */ + +/* [2] Getters and Setters */ +MimePart &MimeMessage::getContent() { return *content; } + +void MimeMessage::setContent(MimePart *content) { + if (this->autoMimeContentCreated) { + this->autoMimeContentCreated = false; + delete (this->content); + } + this->content = content; +} + +void MimeMessage::setReplyTo(EmailAddress *rto) { replyTo = rto; } + +void MimeMessage::setSender(EmailAddress *e) { + this->sender = e; + e->setParent(this); +} + +void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) { + switch (type) { + case To: + recipientsTo << rcpt; + break; + case Cc: + recipientsCc << rcpt; + break; + case Bcc: + recipientsBcc << rcpt; + break; + } + + rcpt->setParent(this); +} + +void MimeMessage::addTo(EmailAddress *rcpt) { this->recipientsTo << rcpt; } + +void MimeMessage::addCc(EmailAddress *rcpt) { this->recipientsCc << rcpt; } + +void MimeMessage::addBcc(EmailAddress *rcpt) { this->recipientsBcc << rcpt; } + +void MimeMessage::setSubject(const QString &subject) { + this->subject = subject; +} + +void MimeMessage::addPart(MimePart *part) { + if (typeid(*content) == typeid(MimeMultiPart)) { + ((MimeMultiPart *) content)->addPart(part); + }; +} + +void MimeMessage::setInReplyTo(const QString &inReplyTo) { + mInReplyTo = inReplyTo; +} + +void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc) { + this->hEncoding = hEnc; +} + +const EmailAddress &MimeMessage::getSender() const { return *sender; } + +const QList<EmailAddress *> & +MimeMessage::getRecipients(RecipientType type) const { + switch (type) { + default: + case To: + return recipientsTo; + case Cc: + return recipientsCc; + case Bcc: + return recipientsBcc; + } +} + +const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; } + +const QString &MimeMessage::getSubject() const { return subject; } + +const QList<MimePart *> &MimeMessage::getParts() const { + if (typeid(*content) == typeid(MimeMultiPart)) { + return ((MimeMultiPart *) content)->getParts(); + } else { + auto *res = new QList<MimePart *>(); + res->append(content); + return *res; + } +} + +/* [2] --- */ + +/* [3] Public Methods */ + +QString MimeMessage::toString() { + QString mime; + + /* =========== MIME HEADER ============ */ + + /* ---------- Sender / From ----------- */ + mime = "From:"; + if (sender->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append(sender->getName().toUtf8()).toBase64() + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode( + QByteArray().append(sender->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + sender->getName(); + } + } + mime += " <" + sender->getAddress() + ">\r\n"; + /* ---------------------------------- */ + + /* ------- Recipients / To ---------- */ + mime += "To:"; + QList<EmailAddress *>::iterator it; + int i; + for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) { + if (i != 0) { + mime += ","; + } + + if ((*it)->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append((*it)->getName().toUtf8()).toBase64() + + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode( + QByteArray().append((*it)->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + (*it)->getName(); + } + } + mime += " <" + (*it)->getAddress() + ">"; + } + mime += "\r\n"; + /* ---------------------------------- */ + + /* ------- Recipients / Cc ---------- */ + if (!recipientsCc.empty()) { + mime += "Cc:"; + } + for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i) { + if (i != 0) { + mime += ","; + } + + if ((*it)->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append((*it)->getName().toUtf8()).toBase64() + + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode( + QByteArray().append((*it)->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + (*it)->getName(); + } + } + mime += " <" + (*it)->getAddress() + ">"; + } + if (!recipientsCc.empty()) { + mime += "\r\n"; + } + /* ---------------------------------- */ + + /* ------------ Subject ------------- */ + mime += "Subject: "; + + switch (hEncoding) { + case MimePart::Base64: + mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?="; + break; + case MimePart::QuotedPrintable: + mime += "=?utf-8?Q?" + + QuotedPrintable::encode(QByteArray().append(subject.toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += subject; + } + mime += "\r\n"; + /* ---------------------------------- */ + + /* ---------- Reply-To -------------- */ + if (replyTo) { + mime += "Reply-To: "; + if (replyTo->getName() != "") { + switch (hEncoding) { + case MimePart::Base64: + mime += " =?utf-8?B?" + + QByteArray().append(replyTo->getName().toUtf8()).toBase64() + "?="; + break; + case MimePart::QuotedPrintable: + mime += " =?utf-8?Q?" + + QuotedPrintable::encode(QByteArray().append(replyTo->getName().toUtf8())) + .replace(' ', "_") + .replace(':', "=3A") + + "?="; + break; + default: + mime += " " + replyTo->getName(); + } + } + mime += " <" + replyTo->getAddress() + ">\r\n"; + } + + /* ---------------------------------- */ + + mime += "MIME-Version: 1.0\r\n"; + if (!mInReplyTo.isEmpty()) { + mime += "In-Reply-To: <" + mInReplyTo + ">\r\n"; + mime += "References: <" + mInReplyTo + ">\r\n"; + } + + QDateTime now = QDateTime::currentDateTime(); +#if QT_VERSION_MAJOR < 5 // Qt4 workaround since RFC2822Date isn't defined + QString shortDayName = + QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat); + QString shortMonthName = + QLocale::c().monthName(now.date().month(), QLocale::ShortFormat); + int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60; + char timezoneSign = utcOffset >= 0 ? '+' : '-'; + utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset; + QString timezone = QString("%1%2%3") + .arg(timezoneSign) + .arg(utcOffset / 60, 2, 10, QChar('0')) + .arg(utcOffset % 60, 2, 10, QChar('0')); + mime += QString("Date: %1\r\n") + .arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3") + .arg(shortDayName) + .arg(shortMonthName) + .arg(timezone)); +#else // Qt5 supported + mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date)); +#endif // support RFC2822Date + + mime += content->toString(); + return mime; +} + +/* [3] --- */ diff --git a/src/smtp/mimemultipart.cpp b/src/smtp/mimemultipart.cpp new file mode 100644 index 00000000..14a813c2 --- /dev/null +++ b/src/smtp/mimemultipart.cpp @@ -0,0 +1,70 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimemultipart.h" +#include <QCryptographicHash> +#include <QRandomGenerator> +#include <QTime> + +const QString MULTI_PART_NAMES[] = { + "multipart/mixed", // Mixed + "multipart/digest", // Digest + "multipart/alternative", // Alternative + "multipart/related", // Related + "multipart/report", // Report + "multipart/signed", // Signed + "multipart/encrypted" // Encrypted +}; + +MimeMultiPart::MimeMultiPart(MultiPartType type) { + this->type = type; + this->cType = MULTI_PART_NAMES[this->type]; + this->cEncoding = _8Bit; + + QRandomGenerator generator; + + QCryptographicHash md5(QCryptographicHash::Md5); + md5.addData(QByteArray().append((char) generator.generate())); + cBoundary = md5.result().toHex(); +} + +void MimeMultiPart::addPart(MimePart *part) { parts.append(part); } + +const QList<MimePart *> &MimeMultiPart::getParts() const { return parts; } + +void MimeMultiPart::prepare() { + QList<MimePart *>::iterator it; + + content = ""; + for (it = parts.begin(); it != parts.end(); it++) { + content += QString("--" + cBoundary + "\r\n").toUtf8(); + (*it)->prepare(); + content += (*it)->toString().toUtf8(); + }; + + content += QString("--" + cBoundary + "--\r\n").toUtf8(); + + MimePart::prepare(); +} + +void MimeMultiPart::setMimeType(const MultiPartType type) { + this->type = type; + this->cType = MULTI_PART_NAMES[type]; +} + +MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; } diff --git a/src/smtp/mimepart.cpp b/src/smtp/mimepart.cpp new file mode 100644 index 00000000..5d33884d --- /dev/null +++ b/src/smtp/mimepart.cpp @@ -0,0 +1,159 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimepart.h" +#include "smtp/quotedprintable.h" + +/* [1] Constructors and Destructors */ + +MimePart::MimePart() { + cEncoding = _7Bit; + prepared = false; + cBoundary = ""; +} + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void MimePart::setContent(const QByteArray &content) { + this->content = content; +} + +void MimePart::setHeader(const QString &header) { this->header = header; } + +void MimePart::addHeaderLine(const QString &line) { + this->header += line + "\r\n"; +} + +const QString &MimePart::getHeader() const { return header; } + +const QByteArray &MimePart::getContent() const { return content; } + +void MimePart::setContentId(const QString &cId) { this->cId = cId; } + +const QString &MimePart::getContentId() const { return this->cId; } + +void MimePart::setContentName(const QString &cName) { this->cName = cName; } + +const QString &MimePart::getContentName() const { return this->cName; } + +void MimePart::setContentType(const QString &cType) { this->cType = cType; } + +const QString &MimePart::getContentType() const { return this->cType; } + +void MimePart::setCharset(const QString &charset) { this->cCharset = charset; } + +const QString &MimePart::getCharset() const { return this->cCharset; } + +void MimePart::setEncoding(Encoding enc) { this->cEncoding = enc; } + +MimePart::Encoding MimePart::getEncoding() const { return this->cEncoding; } + +MimeContentFormatter &MimePart::getContentFormatter() { + return this->formatter; +} + +/* [2] --- */ + +/* [3] Public methods */ + +QString MimePart::toString() { + if (!prepared) + prepare(); + + return mimeString; +} + +/* [3] --- */ + +/* [4] Protected methods */ + +void MimePart::prepare() { + mimeString = QString(); + + /* === Header Prepare === */ + + /* Content-Type */ + mimeString.append("Content-Type: ").append(cType); + + if (cName != "") + mimeString.append("; name=\"").append(cName).append("\""); + + if (cCharset != "") + mimeString.append("; charset=").append(cCharset); + + if (cBoundary != "") + mimeString.append("; boundary=").append(cBoundary); + + mimeString.append("\r\n"); + /* ------------ */ + + /* Content-Transfer-Encoding */ + mimeString.append("Content-Transfer-Encoding: "); + switch (cEncoding) { + case _7Bit: + mimeString.append("7bit\r\n"); + break; + case _8Bit: + mimeString.append("8bit\r\n"); + break; + case Base64: + mimeString.append("base64\r\n"); + break; + case QuotedPrintable: + mimeString.append("quoted-printable\r\n"); + break; + } + /* ------------------------ */ + + /* Content-Id */ + if (cId != NULL) + mimeString.append("Content-ID: <").append(cId).append(">\r\n"); + /* ---------- */ + + /* Addition header lines */ + + mimeString.append(header).append("\r\n"); + + /* ------------------------- */ + + /* === End of Header Prepare === */ + + /* === Content === */ + switch (cEncoding) { + case _7Bit: + mimeString.append(QString(content).toLatin1()); + break; + case _8Bit: + mimeString.append(content); + break; + case Base64: + mimeString.append(formatter.format(content.toBase64())); + break; + case QuotedPrintable: + mimeString.append(formatter.format(QuotedPrintable::encode(content), true)); + break; + } + mimeString.append("\r\n"); + /* === End of Content === */ + + prepared = true; +} + +/* [4] --- */ diff --git a/src/smtp/mimetext.cpp b/src/smtp/mimetext.cpp new file mode 100644 index 00000000..3726647e --- /dev/null +++ b/src/smtp/mimetext.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/mimetext.h" + +/* [1] Constructors and Destructors */ + +MimeText::MimeText(const QString &txt) { + this->text = txt; + this->cType = "text/plain"; + this->cCharset = "utf-8"; + this->cEncoding = _8Bit; +} + +MimeText::~MimeText() = default; + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void MimeText::setText(const QString &text) { this->text = text; } + +const QString &MimeText::getText() const { return text; } + +/* [2] --- */ + +/* [3] Protected Methods */ + +void MimeText::prepare() { + this->content.clear(); + this->content.append(text.toUtf8()); + + /* !!! IMPORTANT !!! */ + MimePart::prepare(); +} + +/* [3] --- */ diff --git a/src/smtp/quotedprintable.cpp b/src/smtp/quotedprintable.cpp new file mode 100644 index 00000000..93e51122 --- /dev/null +++ b/src/smtp/quotedprintable.cpp @@ -0,0 +1,62 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/quotedprintable.h" + +QString QuotedPrintable::encode(const QByteArray &input) { + QString output; + + char byte; + const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + for (char i : input) { + byte = i; + + if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) { + output.append(byte); + } else { + output.append('='); + output.append(hex[((byte >> 4) & 0x0F)]); + output.append(hex[(byte & 0x0F)]); + } + } + + return output; +} + +QByteArray QuotedPrintable::decode(const QString &input) { + // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B + // C D E F + const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, + 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15}; + + QByteArray output; + + for (int i = 0; i < input.length(); ++i) { + if (input.at(i).toLatin1() == '=') { + output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) + + hexVal[input.at(i + 2).toLatin1() - '0']); + i += 2; + } else { + output.append(input.at(i).toLatin1()); + } + } + + return output; +} diff --git a/src/smtp/smtpclient.cpp b/src/smtp/smtpclient.cpp new file mode 100644 index 00000000..63202998 --- /dev/null +++ b/src/smtp/smtpclient.cpp @@ -0,0 +1,407 @@ +/* + Copyright (c) 2011-2012 - Tőkés Attila + + This file is part of SmtpClient for Qt. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + See the LICENSE file for more details. +*/ + +#include "smtp/smtpclient.h" + +#include <QByteArray> +#include <QFileInfo> + +/* [1] Constructors and destructors */ + +SmtpClient::SmtpClient(const QString &host, int port, + ConnectionType connectionType) + : socket(NULL), name("localhost"), authMethod(AuthPlain), + connectionTimeout(5000), responseTimeout(5000), + sendMessageTimeout(60000) { + setConnectionType(connectionType); + + this->host = host; + this->port = port; + + connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, + SLOT(socketStateChanged(QAbstractSocket::SocketState))); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, + SLOT(socketError(QAbstractSocket::SocketError))); + connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); +} + +SmtpClient::~SmtpClient() { + if (socket) + delete socket; +} + +/* [1] --- */ + +/* [2] Getters and Setters */ + +void SmtpClient::setUser(const QString &user) { this->user = user; } + +void SmtpClient::setPassword(const QString &password) { + this->password = password; +} + +void SmtpClient::setAuthMethod(AuthMethod method) { this->authMethod = method; } + +void SmtpClient::setHost(const QString &host) { this->host = host; } + +void SmtpClient::setPort(int port) { this->port = port; } + +void SmtpClient::setConnectionType(ConnectionType ct) { + this->connectionType = ct; + + if (socket) + delete socket; + + switch (connectionType) { + case TcpConnection: + socket = new QTcpSocket(this); + break; + case SslConnection: + case TlsConnection: + socket = new QSslSocket(this); + } +} + +const QString &SmtpClient::getHost() const { return this->host; } + +const QString &SmtpClient::getUser() const { return this->user; } + +const QString &SmtpClient::getPassword() const { return this->password; } + +SmtpClient::AuthMethod SmtpClient::getAuthMethod() const { + return this->authMethod; +} + +int SmtpClient::getPort() const { return this->port; } + +SmtpClient::ConnectionType SmtpClient::getConnectionType() const { + return connectionType; +} + +const QString &SmtpClient::getName() const { return this->name; } + +void SmtpClient::setName(const QString &name) { this->name = name; } + +const QString &SmtpClient::getResponseText() const { return responseText; } + +int SmtpClient::getResponseCode() const { return responseCode; } + +QTcpSocket *SmtpClient::getSocket() { return socket; } + +int SmtpClient::getConnectionTimeout() const { return connectionTimeout; } + +void SmtpClient::setConnectionTimeout(int msec) { connectionTimeout = msec; } + +int SmtpClient::getResponseTimeout() const { return responseTimeout; } + +void SmtpClient::setResponseTimeout(int msec) { responseTimeout = msec; } + +int SmtpClient::getSendMessageTimeout() const { return sendMessageTimeout; } + +void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; } + +/* [2] --- */ + +/* [3] Public methods */ + +bool SmtpClient::connectToHost() { + switch (connectionType) { + case TlsConnection: + case TcpConnection: + socket->connectToHost(host, port); + break; + case SslConnection: + ((QSslSocket *) socket)->connectToHostEncrypted(host, port); + break; + } + + // Tries to connect to server + if (!socket->waitForConnected(connectionTimeout)) { + emit smtpError(ConnectionTimeoutError); + return false; + } + + try { + // Wait for the server's response + waitForResponse(); + + // If the response code is not 220 (Service ready) + // means that is something wrong with the server + if (responseCode != 220) { + emit smtpError(ServerError); + return false; + } + + // Send a EHLO/HELO message to the server + // The client's first command must be EHLO/HELO + sendMessage("EHLO " + name); + + // Wait for the server's response + waitForResponse(); + + // The response code needs to be 250. + if (responseCode != 250) { + emit smtpError(ServerError); + return false; + } + + if (connectionType == TlsConnection) { + // send a request to start TLS handshake + sendMessage("STARTTLS"); + + // Wait for the server's response + waitForResponse(); + + // The response code needs to be 220. + if (responseCode != 220) { + emit smtpError(ServerError); + return false; + }; + + ((QSslSocket *) socket)->startClientEncryption(); + + if (!((QSslSocket *) socket)->waitForEncrypted(connectionTimeout)) { + qDebug() << ((QSslSocket *) socket)->errorString(); + emit smtpError(ConnectionTimeoutError); + return false; + } + + // Send ELHO one more time + sendMessage("EHLO " + name); + + // Wait for the server's response + waitForResponse(); + + // The response code needs to be 250. + if (responseCode != 250) { + emit smtpError(ServerError); + return false; + } + } + } catch (ResponseTimeoutException) { + return false; + } catch (SendMessageTimeoutException) { + return false; + } + + // If no errors occured the function returns true. + return true; +} + +bool SmtpClient::login() { return login(user, password, authMethod); } + +bool SmtpClient::login(const QString &user, const QString &password, + AuthMethod method) { + try { + if (method == AuthPlain) { + // Sending command: AUTH PLAIN base64('\0' + username + '\0' + password) + sendMessage("AUTH PLAIN " + QByteArray() + .append((char) 0) + .append(user.toUtf8()) + .append((char) 0) + .append(password.toUtf8()) + .toBase64()); + + // Wait for the server's response + waitForResponse(); + + // If the response is not 235 then the authentication was faild + if (responseCode != 235) { + emit smtpError(AuthenticationFailedError); + return false; + } + } else if (method == AuthLogin) { + // Sending command: AUTH LOGIN + sendMessage("AUTH LOGIN"); + + // Wait for 334 response code + waitForResponse(); + if (responseCode != 334) { + emit smtpError(AuthenticationFailedError); + return false; + } + + // Send the username in base64 + sendMessage(QByteArray().append(user.toUtf8()).toBase64()); + + // Wait for 334 + waitForResponse(); + if (responseCode != 334) { + emit smtpError(AuthenticationFailedError); + return false; + } + + // Send the password in base64 + sendMessage(QByteArray().append(password.toUtf8()).toBase64()); + + // Wait for the server's responce + waitForResponse(); + + // If the response is not 235 then the authentication was faild + if (responseCode != 235) { + emit smtpError(AuthenticationFailedError); + return false; + } + } + } catch (ResponseTimeoutException) { + // Responce Timeout exceeded + emit smtpError(AuthenticationFailedError); + return false; + } catch (SendMessageTimeoutException) { + // Send Timeout exceeded + emit smtpError(AuthenticationFailedError); + return false; + } + + return true; +} + +bool SmtpClient::sendMail(MimeMessage &email) { + try { + // Send the MAIL command with the sender + sendMessage("MAIL FROM:<" + email.getSender().getAddress() + ">"); + + waitForResponse(); + + if (responseCode != 250) + return false; + + // Send RCPT command for each recipient + QList<EmailAddress *>::const_iterator it, itEnd; + // To (primary recipients) + for (it = email.getRecipients().begin(), + itEnd = email.getRecipients().end(); + it != itEnd; ++it) { + + sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); + waitForResponse(); + + if (responseCode != 250) + return false; + } + + // Cc (carbon copy) + for (it = email.getRecipients(MimeMessage::Cc).begin(), + itEnd = email.getRecipients(MimeMessage::Cc).end(); + it != itEnd; ++it) { + sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); + waitForResponse(); + + if (responseCode != 250) + return false; + } + + // Bcc (blind carbon copy) + for (it = email.getRecipients(MimeMessage::Bcc).begin(), + itEnd = email.getRecipients(MimeMessage::Bcc).end(); + it != itEnd; ++it) { + sendMessage("RCPT TO:<" + (*it)->getAddress() + ">"); + waitForResponse(); + + if (responseCode != 250) + return false; + } + + // Send DATA command + sendMessage("DATA"); + waitForResponse(); + + if (responseCode != 354) + return false; + + sendMessage(email.toString()); + + // Send \r\n.\r\n to end the mail data + sendMessage("."); + + waitForResponse(); + + if (responseCode != 250) + return false; + } catch (ResponseTimeoutException) { + return false; + } catch (SendMessageTimeoutException) { + return false; + } + + return true; +} + +void SmtpClient::quit() { + try { + sendMessage("QUIT"); + } catch (SmtpClient::SendMessageTimeoutException) { + // Manually close the connection to the smtp server if message "QUIT" wasn't + // received by the smtp server + if (socket->state() == QAbstractSocket::ConnectedState || + socket->state() == QAbstractSocket::ConnectingState || + socket->state() == QAbstractSocket::HostLookupState) + socket->disconnectFromHost(); + } +} + +/* [3] --- */ + +/* [4] Protected methods */ + +void SmtpClient::waitForResponse() { + do { + if (!socket->waitForReadyRead(responseTimeout)) { + emit smtpError(ResponseTimeoutError); + throw ResponseTimeoutException(); + } + + while (socket->canReadLine()) { + // Save the server's response + responseText = socket->readLine(); + + // Extract the respose code from the server's responce (first 3 digits) + responseCode = responseText.leftRef(3).toInt(); + + if (responseCode / 100 == 4) + emit smtpError(ServerError); + + if (responseCode / 100 == 5) + emit smtpError(ClientError); + + if (responseText[3] == ' ') { + return; + } + } + } while (true); +} + +void SmtpClient::sendMessage(const QString &text) { + socket->write(text.toUtf8() + "\r\n"); + if (!socket->waitForBytesWritten(sendMessageTimeout)) { + emit smtpError(SendDataTimeoutError); + throw SendMessageTimeoutException(); + } +} + +/* [4] --- */ + +/* [5] Slots for the socket's signals */ + +void SmtpClient::socketStateChanged(QAbstractSocket::SocketState /*state*/) {} + +void SmtpClient::socketError(QAbstractSocket::SocketError /*socketError*/) {} + +void SmtpClient::socketReadyRead() {} + +/* [5] --- */ diff --git a/src/ui/AboutDialog.cpp b/src/ui/AboutDialog.cpp deleted file mode 100644 index e51f225d..00000000 --- a/src/ui/AboutDialog.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#include "ui/AboutDialog.h" - -AboutDialog::AboutDialog(QWidget *parent) - : QDialog(parent) { - this->setWindowTitle(tr("About ") + qApp->applicationName()); - - auto *tabWidget = new QTabWidget; - auto *infoTab = new InfoTab; - auto *translatorsTab = new TranslatorsTab; - - tabWidget->addTab(infoTab, tr("General")); - tabWidget->addTab(translatorsTab, tr("Translators")); - - auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); - connect(buttonBox, SIGNAL(accepted()), this, SLOT(close())); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(tabWidget); - mainLayout->addWidget(buttonBox); - setLayout(mainLayout); - - this->exec(); -} - -InfoTab::InfoTab(QWidget *parent) - : QWidget(parent) { - auto *pixmap = new QPixmap(":gpgfrontend-logo.png"); - auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>" - + "<center><b>" + qApp->applicationVersion() + "</b></center>" - + "<center>" + GIT_VERSION + "</center>" - + tr("<br><center>GPGFrontend is an easy-to-use, compact, <br>" - "cross-platform, and installation-free gpg front-end tool.<br>" - "It visualizes most of the common operations of gpg commands.<br>" - "It's licensed under the GPL v3<br><br>" - "<b>Developer:</b><br>" - "Saturneric<br><br>" - "If you have any questions or suggestions, raise an issue<br/>" - "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") + - tr("<br><br> Built with Qt ") + qVersion() - + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() + - tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>"); - - auto *layout = new QGridLayout(); - auto *pixmapLabel = new QLabel(); - pixmapLabel->setPixmap(*pixmap); - layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter); - auto *aboutLabel = new QLabel(); - aboutLabel->setText(*text); - aboutLabel->setOpenExternalLinks(true); - layout->addWidget(aboutLabel, 1, 0, 1, -1); - layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, - QSizePolicy::Fixed), 2, 1, 1, 1); - - setLayout(layout); -} - -TranslatorsTab::TranslatorsTab(QWidget *parent) - : QWidget(parent) { - QFile translatorsFile; - translatorsFile.setFileName(qApp->applicationDirPath() + "/About"); - translatorsFile.open(QIODevice::ReadOnly); - QByteArray inBuffer = translatorsFile.readAll(); - - auto *label = new QLabel(inBuffer); - auto *mainLayout = new QVBoxLayout(this); - mainLayout->addWidget(label); - - setLayout(mainLayout); -} - diff --git a/src/ui/AttachmentTableModel.cpp b/src/ui/AttachmentTableModel.cpp deleted file mode 100644 index 79cbdf9b..00000000 --- a/src/ui/AttachmentTableModel.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -#include "ui/AttachmentTableModel.h" - -#include <utility> - -/** compare with http://doc.qt.nokia.com/4.6/itemviews-addressbook.html - */ - -AttachmentTableModel::AttachmentTableModel(QObject *parent) : - QAbstractTableModel(parent) { -} - -AttachmentTableModel::AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent) : - QAbstractTableModel(parent) { - listOfMimeparts = std::move(mimeparts); -} - - -void AttachmentTableModel::add(const MimePart &mp) { - listOfMimeparts.append(mp); - //QModelIndex changedIndex0 = createIndex(listOfMimeparts.size(), 0); - //QModelIndex changedIndex1 = createIndex(listOfMimeparts.size(), 1); - - //emit(dataChanged(changedIndex0, changedIndex1)); - // TODO: check the data-changed signal - // reset(); -} - -MimePart AttachmentTableModel::getSelectedMimePart(QModelIndex index) { - return listOfMimeparts.at(index.row()); -} - -MimePart AttachmentTableModel::getMimePart(int index) { - return listOfMimeparts.at(index); -} - -/*QList<MimePart> AttachmentTableModel::getSelectedMimeParts(QModelIndexList indexes){ - - foreach(QModelIndex index, indexes) { - qDebug() << "ir: "<< index.row(); - } - -}*/ - -int AttachmentTableModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return listOfMimeparts.size(); -} - -int AttachmentTableModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return 2; -} - -QVariant AttachmentTableModel::data(const QModelIndex &index, int role) const { - - //qDebug() << "called, index: " << index.column(); - - if (!index.isValid()) - return QVariant(); - - if (index.row() >= listOfMimeparts.size() || index.row() < 0) - return QVariant(); - - if (role == Qt::DisplayRole) { - MimePart mp = listOfMimeparts.at(index.row()); - - if (index.column() == 0) - return mp.header.getParam("Content-Type", "name"); - if (index.column() == 1) - return mp.header.getValue("Content-Type"); - - } - - // set icon - // TODO more generic matching, e.g. for audio - if (role == Qt::DecorationRole && index.column() == 0) { - MimePart mp = listOfMimeparts.at(index.row()); - QString icon; - if (mp.header.getValue("Content-Type").startsWith("image")) { - icon = ":mimetypes/image-x-generic.png"; - } else { - icon = mp.header.getValue("Content-Type").replace("/", "-"); - icon = ":mimetypes/" + icon + ".png"; - } - if (!QFile::exists(icon)) icon = ":mimetypes/unknown.png"; - return QIcon(icon); - } - - return QVariant(); -} - -QVariant AttachmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const { - //qDebug() << "called, section: " << section; - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - switch (section) { - case 0: - return tr("Filename"); - - case 1: - return tr("Contenttype"); - - default: - return QVariant(); - } - } - return QVariant(); -} diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 68f57b81..618b5d28 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -3,6 +3,7 @@ aux_source_directory(./keypair_details UI_SOURCE) aux_source_directory(./widgets UI_SOURCE) aux_source_directory(./keygen UI_SOURCE) aux_source_directory(./main_window UI_SOURCE) +aux_source_directory(./help UI_SOURCE) add_library(gpgfrontend-ui STATIC ${UI_SOURCE}) diff --git a/src/ui/FileEncryptionDialog.cpp b/src/ui/FileEncryptionDialog.cpp index 9cb7b00a..e92dfc90 100755 --- a/src/ui/FileEncryptionDialog.cpp +++ b/src/ui/FileEncryptionDialog.cpp @@ -203,27 +203,50 @@ void FileEncryptionDialog::slotExecuteAction() { QVector<GpgKey> keys; mKeyList->getCheckedKeys(keys); + qDebug() << "slotExecuteAction" << mAction; + if (mAction == Encrypt) { - if (!mCtx->encrypt(keys, inBuffer, outBuffer, nullptr)) return; + qDebug() << "Action Encrypt"; + gpgme_error_t err = mCtx->encrypt(keys, inBuffer, outBuffer, nullptr); + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) { + qDebug() << "Error" << gpgme_strerror(err); + QMessageBox::warning(this, tr("Error"), + tr("Error Occurred During Encryption")); + return; + } } if (mAction == Decrypt) { - if (!mCtx->decrypt(inBuffer, outBuffer, nullptr)) return; + qDebug() << "Action Decrypt"; + gpgme_error_t err = mCtx->decrypt(inBuffer, outBuffer, nullptr); + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) { + qDebug() << "Error" << gpgme_strerror(err); + QMessageBox::warning(this, tr("Error"), + tr("Error Occurred During Decryption")); + return; + } } if (mAction == Sign) { - if (gpgme_err_code(mCtx->sign(keys, inBuffer, outBuffer, true)) != GPG_ERR_NO_ERROR) return; + qDebug() << "Action Sign"; + gpgme_error_t err = mCtx->sign(keys, inBuffer, outBuffer, true); + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) { + qDebug() << "Error" << gpgme_strerror(err); + QMessageBox::warning(this, tr("Error"), + tr("Error Occurred During Signature")); + return; + } } if (mAction == Verify) { - QFile signfile; - signfile.setFileName(signFileEdit->text()); - if (!signfile.open(QIODevice::ReadOnly)) { + QFile sign_file; + sign_file.setFileName(signFileEdit->text()); + if (!sign_file.open(QIODevice::ReadOnly)) { statusLabel->setText(tr("Couldn't open file")); signFileEdit->setStyleSheet("QLineEdit { background: yellow }"); return; } - auto signBuffer = signfile.readAll(); + auto signBuffer = sign_file.readAll(); gpgme_verify_result_t result; auto error = mCtx->verify(&inBuffer, &signBuffer, &result); new VerifyDetailsDialog(this, mCtx, mKeyList, error, result); diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp index 0e2d9c9a..ce5343bf 100755 --- a/src/ui/KeyMgmt.cpp +++ b/src/ui/KeyMgmt.cpp @@ -78,7 +78,7 @@ KeyMgmt::KeyMgmt(GpgME::GpgContext *ctx, QWidget *parent ) : this->settings.setValue("keymgmt/setWindowSize", true); } - setWindowTitle(tr("KeyPairs Management")); + setWindowTitle(tr("Key Pair Management")); mKeyList->addMenuAction(deleteSelectedKeysAct); mKeyList->addMenuAction(showKeyDetailsAct); } diff --git a/src/ui/KeyServerImportDialog.cpp b/src/ui/KeyServerImportDialog.cpp index ec740691..a1355120 100644 --- a/src/ui/KeyServerImportDialog.cpp +++ b/src/ui/KeyServerImportDialog.cpp @@ -176,7 +176,7 @@ void KeyServerImportDialog::setMessage(const QString &text, bool error) { void KeyServerImportDialog::slotSearch() { if (searchLineEdit->text().isEmpty()) { - setMessage(tr("<h4>Text is empty.</h4>"), false); + setMessage("<h4>" + tr("Text is empty.") + "</h4>", false); return; } @@ -227,23 +227,23 @@ void KeyServerImportDialog::slotSearchFinished() { if (firstLine.contains("Error")) { QString text = QString(reply->readLine(1024)); if (text.contains("Too many responses")) { - setMessage(tr("<h4>CToo many responses from keyserver!</h4>"), true); + setMessage("<h4>" +tr("Too many responses from keyserver!") + "</h4>", true); return; } else if (text.contains("No keys found")) { // if string looks like hex string, search again with 0x prepended QRegExp rx("[0-9A-Fa-f]*"); QString query = searchLineEdit->text(); if (rx.exactMatch(query)) { - setMessage(tr("<h4>No keys found, input may be kexId, retrying search with 0x.</h4>"), true); + setMessage("<h4>" + tr("No keys found, input may be kexId, retrying search with 0x.") + "</h4>", true); searchLineEdit->setText(query.prepend("0x")); this->slotSearch(); return; } else { - setMessage(tr("<h4>No keys found containing the search string!</h4>"), true); + setMessage("<h4>" +tr("No keys found containing the search string!") + "</h4>", true); return; } } else if (text.contains("Insufficiently specific words")) { - setMessage(tr("<h4>Insufficiently specific search string!</h4>"), true); + setMessage("<h4>" + tr("Insufficiently specific search string!") + "</h4>", true); return; } else { setMessage(text, true); diff --git a/src/ui/KeyUploadDialog.cpp b/src/ui/KeyUploadDialog.cpp index e28b4230..faf892f0 100644 --- a/src/ui/KeyUploadDialog.cpp +++ b/src/ui/KeyUploadDialog.cpp @@ -36,9 +36,13 @@ KeyUploadDialog::KeyUploadDialog(GpgME::GpgContext *ctx, const QVector<GpgKey> & auto *pb = new QProgressBar(); pb->setRange(0, 0); + pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + pb->setTextVisible(false); auto *layout = new QVBoxLayout(); layout->addWidget(pb); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); this->setLayout(layout); this->setModal(true); diff --git a/src/ui/SendMailDialog.cpp b/src/ui/SendMailDialog.cpp new file mode 100644 index 00000000..5bea7cb2 --- /dev/null +++ b/src/ui/SendMailDialog.cpp @@ -0,0 +1,173 @@ +/** + * This file is part of GPGFrontend. + * + * GPGFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + +#include "ui/SendMailDialog.h" + +#include <utility> +#include "smtp/SmtpMime" + +SendMailDialog::SendMailDialog(QString text, QWidget *parent) + : QDialog(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat), mText(std::move(text)) { + + if (smtpAddress.isEmpty()) { + QMessageBox::critical(this, tr("Incomplete configuration"), + tr("The SMTP address is empty, please go to the setting interface to complete the configuration.")); + + deleteLater(); + return; + + } + + senderEdit = new QLineEdit(); + senderEdit->setText(defaultSender); + recipientEdit = new QTextEdit(); + recipientEdit->setPlaceholderText("One or more email addresses. Please use ; to separate."); + subjectEdit = new QLineEdit(); + + errorLabel = new QLabel(); + + qDebug() << "Send Mail Settings" << smtpAddress << username << password << defaultSender << connectionTypeSettings; + + confirmButton = new QPushButton("Confirm"); + + auto layout = new QGridLayout(); + layout->addWidget(new QLabel("Sender"), 0, 0); + layout->addWidget(senderEdit, 0, 1); + layout->addWidget(new QLabel("Recipient"), 1, 0); + layout->addWidget(recipientEdit, 1, 1); + layout->addWidget(new QLabel("Subject"), 2, 0); + layout->addWidget(subjectEdit, 2, 1); + layout->addWidget(confirmButton, 3, 1); + layout->addWidget(errorLabel, 4, 0, 1, 2); + + connect(confirmButton, SIGNAL(clicked(bool)), this, SLOT(slotConfirm())); + + this->setLayout(layout); + this->setWindowTitle("Send Mail"); + this->setModal(true); + this->setFixedWidth(320); + this->show(); +} + +bool SendMailDialog::check_email_address(const QString &str) { + return re_email.match(str).hasMatch(); +} + +void SendMailDialog::slotConfirm() { + + QString errString; + errorLabel->clear(); + + QStringList rcptStringList = recipientEdit->toPlainText().split(';'); + + if (rcptStringList.isEmpty()) { + errString.append(tr(" Recipient cannot be empty \n")); + } else { + for (const auto& reci : rcptStringList) { + qDebug() << "Receiver" << reci.trimmed(); + if (!check_email_address(reci.trimmed())) { + errString.append(tr(" One or more Recipient's Email Address is invalid \n")); + break; + } + } + } + if (senderEdit->text().isEmpty()) { + errString.append(tr(" Sender cannot be empty \n")); + } else if (!check_email_address(senderEdit->text())) { + errString.append(tr(" Sender's Email Address is invalid \n")); + } + + if (!errString.isEmpty()) { + errorLabel->setAutoFillBackground(true); + QPalette error = errorLabel->palette(); + error.setColor(QPalette::Window, "#ff8080"); + errorLabel->setPalette(error); + errorLabel->setText(errString); + return; + } + + SmtpClient::ConnectionType connectionType = SmtpClient::ConnectionType::TcpConnection; + + if (connectionTypeSettings == "SSL") { + connectionType = SmtpClient::ConnectionType::SslConnection; + } else if (connectionTypeSettings == "TLS") { + connectionType = SmtpClient::ConnectionType::TlsConnection; + } else if (connectionTypeSettings == "STARTTLS") { + connectionType = SmtpClient::ConnectionType::TlsConnection; + } else { + connectionType = SmtpClient::ConnectionType::TcpConnection; + } + + SmtpClient smtp(smtpAddress, port, connectionType); + + // We need to set the username (your email address) and the password + // for smtp authentification. + + smtp.setUser(username); + smtp.setPassword(password); + + // Now we create a MimeMessage object. This will be the email. + + MimeMessage message; + + message.setSender(new EmailAddress(senderEdit->text())); + for (const auto &reci : rcptStringList) { + if(!reci.isEmpty()) + message.addRecipient(new EmailAddress(reci.trimmed())); + } + message.setSubject(subjectEdit->text()); + + // Now add some text to the email. + // First we create a MimeText object. + + MimeText text; + + text.setText(mText); + + // Now add it to the mail + message.addPart(&text); + + // Now we can send the mail + if (!smtp.connectToHost()) { + qDebug() << "Connect to SMTP Server Failed"; + QMessageBox::critical(this, tr("Fail"), tr("Fail to Connect SMTP Server")); + return; + } + if (!smtp.login()) { + qDebug() << "Login to SMTP Server Failed"; + QMessageBox::critical(this, tr("Fail"), tr("Fail to Login into SMTP Server")); + return; + } + if (!smtp.sendMail(message)) { + qDebug() << "Send Mail to SMTP Server Failed"; + QMessageBox::critical(this, tr("Fail"), tr("Fail to Send Mail to SMTP Server")); + return; + } + smtp.quit(); + + // Close after sending email + QMessageBox::information(this, tr("Success"), tr("Succeed in Sending Mail to SMTP Server")); + deleteLater(); +} diff --git a/src/ui/SettingsDialog.cpp b/src/ui/SettingsDialog.cpp index 74c507e4..1732d718 100755 --- a/src/ui/SettingsDialog.cpp +++ b/src/ui/SettingsDialog.cpp @@ -23,203 +23,205 @@ */ #include "ui/SettingsDialog.h" +#include "smtp/SmtpMime" +#include "ui/WaitingDialog.h" SettingsDialog::SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent) - : QDialog(parent) { - mCtx = ctx; - tabWidget = new QTabWidget; - generalTab = new GeneralTab(mCtx); - appearanceTab = new AppearanceTab; - mimeTab = new MimeTab; - keyserverTab = new KeyserverTab; - advancedTab = new AdvancedTab; - gpgPathsTab = new GpgPathsTab; - - tabWidget->addTab(generalTab, tr("General")); - tabWidget->addTab(appearanceTab, tr("Appearance")); - tabWidget->addTab(mimeTab, tr("PGP/Mime")); - tabWidget->addTab(keyserverTab, tr("Key Server")); - // tabWidget->addTab(gpgPathsTab, tr("Gpg paths")); - tabWidget->addTab(advancedTab, tr("Advanced")); - - buttonBox = - new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - - connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(tabWidget); - mainLayout->addWidget(buttonBox); - setLayout(mainLayout); - - setWindowTitle(tr("Settings")); - - // slots for handling the restartneeded member - this->slotSetRestartNeeded(false); - connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this, - SLOT(slotSetRestartNeeded(bool))); - connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this, - SLOT(slotSetRestartNeeded(bool))); - connect(mimeTab, SIGNAL(signalRestartNeeded(bool)), this, - SLOT(slotSetRestartNeeded(bool))); - connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this, - SLOT(slotSetRestartNeeded(bool))); - connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this, - SLOT(slotSetRestartNeeded(bool))); - - connect(this, SIGNAL(signalRestartNeeded(bool)), parent, - SLOT(slotSetRestartNeeded(bool))); - - this->show(); + : QDialog(parent) { + mCtx = ctx; + tabWidget = new QTabWidget; + generalTab = new GeneralTab(mCtx); + appearanceTab = new AppearanceTab; + sendMailTab = new SendMailTab; + keyserverTab = new KeyserverTab; + advancedTab = new AdvancedTab; + gpgPathsTab = new GpgPathsTab; + + tabWidget->addTab(generalTab, tr("General")); + tabWidget->addTab(appearanceTab, tr("Appearance")); + tabWidget->addTab(sendMailTab, tr("Send Mail")); + tabWidget->addTab(keyserverTab, tr("Key Server")); + // tabWidget->addTab(gpgPathsTab, tr("Gpg paths")); + tabWidget->addTab(advancedTab, tr("Advanced")); + + buttonBox = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(tabWidget); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + setWindowTitle(tr("Settings")); + + // slots for handling the restartneeded member + this->slotSetRestartNeeded(false); + connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this, + SLOT(slotSetRestartNeeded(bool))); + connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this, + SLOT(slotSetRestartNeeded(bool))); + connect(sendMailTab, SIGNAL(signalRestartNeeded(bool)), this, + SLOT(slotSetRestartNeeded(bool))); + connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this, + SLOT(slotSetRestartNeeded(bool))); + connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this, + SLOT(slotSetRestartNeeded(bool))); + + connect(this, SIGNAL(signalRestartNeeded(bool)), parent, + SLOT(slotSetRestartNeeded(bool))); + + this->show(); } bool SettingsDialog::getRestartNeeded() const { return this->restartNeeded; } void SettingsDialog::slotSetRestartNeeded(bool needed) { - this->restartNeeded = needed; + this->restartNeeded = needed; } void SettingsDialog::slotAccept() { - generalTab->applySettings(); - mimeTab->applySettings(); - appearanceTab->applySettings(); - keyserverTab->applySettings(); - advancedTab->applySettings(); - gpgPathsTab->applySettings(); - if (getRestartNeeded()) { - emit signalRestartNeeded(true); - } - close(); + generalTab->applySettings(); + sendMailTab->applySettings(); + appearanceTab->applySettings(); + keyserverTab->applySettings(); + advancedTab->applySettings(); + gpgPathsTab->applySettings(); + if (getRestartNeeded()) { + emit signalRestartNeeded(true); + } + close(); } // http://www.informit.com/articles/article.aspx?p=1405555&seqNum=3 // http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application QHash<QString, QString> SettingsDialog::listLanguages() { - QHash<QString, QString> languages; + QHash<QString, QString> languages; - languages.insert("", tr("System Default")); + languages.insert("", tr("System Default")); - QString appPath = qApp->applicationDirPath(); - QDir qmDir = QDir(RESOURCE_DIR(appPath) + "/ts/"); - QStringList fileNames = qmDir.entryList(QStringList("gpgfrontend_*.qm")); + QString appPath = qApp->applicationDirPath(); + QDir qmDir = QDir(RESOURCE_DIR(appPath) + "/ts/"); + QStringList fileNames = qmDir.entryList(QStringList("gpgfrontend_*.qm")); - for (int i = 0; i < fileNames.size(); ++i) { - QString locale = fileNames[i]; - locale.truncate(locale.lastIndexOf('.')); - locale.remove(0, locale.indexOf('_') + 1); + for (int i = 0; i < fileNames.size(); ++i) { + QString locale = fileNames[i]; + locale.truncate(locale.lastIndexOf('.')); + locale.remove(0, locale.indexOf('_') + 1); - // this works in qt 4.8 - QLocale qloc(locale); + // this works in qt 4.8 + QLocale qloc(locale); #if QT_VERSION < 0x040800 - QString language = - QLocale::languageToString(qloc.language()) + " (" + locale + - ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")"; + QString language = + QLocale::languageToString(qloc.language()) + " (" + locale + + ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")"; #else - QString language = qloc.nativeLanguageName() + " (" + locale + ")"; + QString language = qloc.nativeLanguageName() + " (" + locale + ")"; #endif - languages.insert(locale, language); - } - return languages; + languages.insert(locale, language); + } + return languages; } GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent) - : QWidget(parent), appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - mCtx = ctx; - - /***************************************** - * remember Password-Box - *****************************************/ - auto *rememberPasswordBox = new QGroupBox(tr("Remember Password")); - auto *rememberPasswordBoxLayout = new QHBoxLayout(); - rememberPasswordCheckBox = - new QCheckBox(tr("Remember password until closing gpg4usb"), this); - rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox); - rememberPasswordBox->setLayout(rememberPasswordBoxLayout); - - /***************************************** - * Save-Checked-Keys-Box - *****************************************/ - auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys")); - auto *saveCheckedKeysBoxLayout = new QHBoxLayout(); - saveCheckedKeysCheckBox = new QCheckBox( - tr("Save checked private keys on exit and restore them on next start."), - this); - saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox); - saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout); - - /***************************************** - * Key-Impport-Confirmation Box - *****************************************/ - auto *importConfirmationBox = - new QGroupBox(tr("Confirm drag'n'drop key import")); - auto *importConfirmationBoxLayout = new QHBoxLayout(); - importConfirmationCheckBox = new QCheckBox( - tr("Import files dropped on the keylist without confirmation."), this); - importConfirmationBoxLayout->addWidget(importConfirmationCheckBox); - importConfirmationBox->setLayout(importConfirmationBoxLayout); - - /***************************************** - * Language Select Box - *****************************************/ - auto *langBox = new QGroupBox(tr("Language")); - auto *langBoxLayout = new QVBoxLayout(); - langSelectBox = new QComboBox; - lang = SettingsDialog::listLanguages(); - - foreach (QString l, lang) { langSelectBox->addItem(l); } - - langBoxLayout->addWidget(langSelectBox); - langBoxLayout->addWidget( - new QLabel(tr("<b>NOTE: </b> GpgFrontend will restart automatically if " - "you change the language!"))); - langBox->setLayout(langBoxLayout); - connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this, - SLOT(slotLanguageChanged())); - - /***************************************** - * Own Key Select Box - *****************************************/ - auto *ownKeyBox = new QGroupBox(tr("Own key")); - auto *ownKeyBoxLayout = new QVBoxLayout(); - ownKeySelectBox = new QComboBox; - - ownKeyBox->setLayout(ownKeyBoxLayout); - mKeyList = new KeyList(mCtx); - - // Fill the keyid hashmap - keyIds.insert("", tr("<none>")); - - for (const auto &keyid : *mKeyList->getAllPrivateKeys()) { - auto &key = mCtx->getKeyById(keyid); - keyIds.insert(key.id, key.uids.first().uid); - } - for (const auto &k : keyIds.keys()) { - ownKeySelectBox->addItem(keyIds.find(k).value()); - keyIdsList.append(k); - } - connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this, - SLOT(slotOwnKeyIdChanged())); - - ownKeyBoxLayout->addWidget(new QLabel( - tr("Key pair for synchronization and identity authentication"))); - ownKeyBoxLayout->addWidget(ownKeySelectBox); - - /***************************************** - * Mainlayout - *****************************************/ - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(rememberPasswordBox); - mainLayout->addWidget(saveCheckedKeysBox); - mainLayout->addWidget(importConfirmationBox); - mainLayout->addWidget(langBox); - mainLayout->addWidget(ownKeyBox); - - setSettings(); - mainLayout->addStretch(1); - setLayout(mainLayout); + : QWidget(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + mCtx = ctx; + + /***************************************** + * remember Password-Box + *****************************************/ + auto *rememberPasswordBox = new QGroupBox(tr("Remember Password")); + auto *rememberPasswordBoxLayout = new QHBoxLayout(); + rememberPasswordCheckBox = + new QCheckBox(tr("Remember password until closing gpg4usb"), this); + rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox); + rememberPasswordBox->setLayout(rememberPasswordBoxLayout); + + /***************************************** + * Save-Checked-Keys-Box + *****************************************/ + auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys")); + auto *saveCheckedKeysBoxLayout = new QHBoxLayout(); + saveCheckedKeysCheckBox = new QCheckBox( + tr("Save checked private keys on exit and restore them on next start."), + this); + saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox); + saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout); + + /***************************************** + * Key-Impport-Confirmation Box + *****************************************/ + auto *importConfirmationBox = + new QGroupBox(tr("Confirm drag'n'drop key import")); + auto *importConfirmationBoxLayout = new QHBoxLayout(); + importConfirmationCheckBox = new QCheckBox( + tr("Import files dropped on the keylist without confirmation."), this); + importConfirmationBoxLayout->addWidget(importConfirmationCheckBox); + importConfirmationBox->setLayout(importConfirmationBoxLayout); + + /***************************************** + * Language Select Box + *****************************************/ + auto *langBox = new QGroupBox(tr("Language")); + auto *langBoxLayout = new QVBoxLayout(); + langSelectBox = new QComboBox; + lang = SettingsDialog::listLanguages(); + + foreach (QString l, lang) { langSelectBox->addItem(l); } + + langBoxLayout->addWidget(langSelectBox); + langBoxLayout->addWidget( + new QLabel(tr("<b>NOTE: </b> GpgFrontend will restart automatically if " + "you change the language!"))); + langBox->setLayout(langBoxLayout); + connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this, + SLOT(slotLanguageChanged())); + + /***************************************** + * Own Key Select Box + *****************************************/ + auto *ownKeyBox = new QGroupBox(tr("Own key")); + auto *ownKeyBoxLayout = new QVBoxLayout(); + ownKeySelectBox = new QComboBox; + + ownKeyBox->setLayout(ownKeyBoxLayout); + mKeyList = new KeyList(mCtx); + + // Fill the keyid hashmap + keyIds.insert("", tr("<none>")); + + for (const auto &keyid : *mKeyList->getAllPrivateKeys()) { + auto &key = mCtx->getKeyById(keyid); + keyIds.insert(key.id, key.uids.first().uid); + } + for (const auto &k : keyIds.keys()) { + ownKeySelectBox->addItem(keyIds.find(k).value()); + keyIdsList.append(k); + } + connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this, + SLOT(slotOwnKeyIdChanged())); + + ownKeyBoxLayout->addWidget(new QLabel( + tr("Key pair for synchronization and identity authentication"))); + ownKeyBoxLayout->addWidget(ownKeySelectBox); + + /***************************************** + * Mainlayout + *****************************************/ + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(rememberPasswordBox); + mainLayout->addWidget(saveCheckedKeysBox); + mainLayout->addWidget(importConfirmationBox); + mainLayout->addWidget(langBox); + mainLayout->addWidget(ownKeyBox); + + setSettings(); + mainLayout->addStretch(1); + setLayout(mainLayout); } /********************************** @@ -228,32 +230,32 @@ GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent) * appropriately **********************************/ void GeneralTab::setSettings() { - // Keysaving - if (settings.value("keys/saveKeyChecked").toBool()) { - saveCheckedKeysCheckBox->setCheckState(Qt::Checked); - } - - // Language setting - QString langKey = settings.value("int/lang").toString(); - QString langValue = lang.value(langKey); - if (langKey != "") { - langSelectBox->setCurrentIndex(langSelectBox->findText(langValue)); - } - - QString ownKeyId = settings.value("general/ownKeyId").toString(); - qDebug() << "OwnKeyId" << ownKeyId; - if (ownKeyId.isEmpty()) { - ownKeySelectBox->setCurrentText("<none>"); - } else { - const auto text = keyIds.find(ownKeyId).value(); - qDebug() << "OwnKey" << ownKeyId << text; - ownKeySelectBox->setCurrentText(text); - } - - // Get own key information from keydb/gpg.conf (if contained) - if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) { - importConfirmationCheckBox->setCheckState(Qt::Checked); - } + // Keysaving + if (settings.value("keys/saveKeyChecked").toBool()) { + saveCheckedKeysCheckBox->setCheckState(Qt::Checked); + } + + // Language setting + QString langKey = settings.value("int/lang").toString(); + QString langValue = lang.value(langKey); + if (langKey != "") { + langSelectBox->setCurrentIndex(langSelectBox->findText(langValue)); + } + + QString ownKeyId = settings.value("general/ownKeyId").toString(); + qDebug() << "OwnKeyId" << ownKeyId; + if (ownKeyId.isEmpty()) { + ownKeySelectBox->setCurrentText("<none>"); + } else { + const auto text = keyIds.find(ownKeyId).value(); + qDebug() << "OwnKey" << ownKeyId << text; + ownKeySelectBox->setCurrentText(text); + } + + // Get own key information from keydb/gpg.conf (if contained) + if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) { + importConfirmationCheckBox->setCheckState(Qt::Checked); + } } /*********************************** @@ -261,70 +263,72 @@ void GeneralTab::setSettings() { * write them to settings-file *************************************/ void GeneralTab::applySettings() { - settings.setValue("keys/saveKeyChecked", - saveCheckedKeysCheckBox->isChecked()); - // TODO: clear passwordCache instantly on unset rememberPassword - settings.setValue("general/rememberPassword", - rememberPasswordCheckBox->isChecked()); - settings.setValue("int/lang", lang.key(langSelectBox->currentText())); - settings.setValue("general/ownKeyId", - keyIdsList[ownKeySelectBox->currentIndex()]); - settings.setValue("general/confirmImportKeys", - importConfirmationCheckBox->isChecked()); + settings.setValue("keys/saveKeyChecked", + saveCheckedKeysCheckBox->isChecked()); + // TODO: clear passwordCache instantly on unset rememberPassword + settings.setValue("general/rememberPassword", + rememberPasswordCheckBox->isChecked()); + settings.setValue("int/lang", lang.key(langSelectBox->currentText())); + settings.setValue("general/ownKeyId", + keyIdsList[ownKeySelectBox->currentIndex()]); + settings.setValue("general/confirmImportKeys", + importConfirmationCheckBox->isChecked()); } void GeneralTab::slotLanguageChanged() { emit signalRestartNeeded(true); } void GeneralTab::slotOwnKeyIdChanged() { - // Set ownKeyId to currently selected + // Set ownKeyId to currently selected } -MimeTab::MimeTab(QWidget *parent) - : QWidget(parent), appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - /***************************************** - * MIME-Parsing-Box - *****************************************/ - auto *mimeQPBox = new QGroupBox(tr("Decode quoted printable")); - auto *mimeQPBoxLayout = new QVBoxLayout(); - mimeQPCheckBox = - new QCheckBox(tr("Try to recognize quoted printable."), this); - mimeQPBoxLayout->addWidget(mimeQPCheckBox); - mimeQPBox->setLayout(mimeQPBoxLayout); - - auto *mimeParseBox = new QGroupBox(tr("Parse PGP/MIME (Experimental)")); - auto *mimeParseBoxLayout = new QVBoxLayout(); - mimeParseCheckBox = new QCheckBox( - tr("Try to split attachments from PGP-MIME ecrypted messages."), this); - mimeParseBoxLayout->addWidget(mimeParseCheckBox); - mimeParseBox->setLayout(mimeParseBoxLayout); - - auto *mimeOpenAttachmentBox = - new QGroupBox(tr("Open with external application (Experimental)")); - auto *mimeOpenAttachmentBoxLayout = new QVBoxLayout(); - auto *mimeOpenAttachmentText = new QLabel(tr( - "Open attachments with default application for the filetype.<br> " - "There are at least two possible problems with this behaviour:" - "<ol><li>File needs to be saved unencrypted to attachments folder.<br> " - "Its your job to clean this folder.</li>" - "<li>The external application may have its own temp files.</li></ol>")); - - // mimeOpenAttachmentBox->setDisabled(true); - mimeOpenAttachmentCheckBox = - new QCheckBox(tr("Enable opening with external applications."), this); - - mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentText); - mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentCheckBox); - mimeOpenAttachmentBox->setLayout(mimeOpenAttachmentBoxLayout); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(mimeParseBox); - mainLayout->addWidget(mimeOpenAttachmentBox); - mainLayout->addWidget(mimeQPBox); - mainLayout->addStretch(1); - setLayout(mainLayout); - setSettings(); +SendMailTab::SendMailTab(QWidget *parent) + : QWidget(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + + enableCheckBox = new QCheckBox(tr("Enable")); + enableCheckBox->setTristate(false); + + smtpAddress = new QLineEdit(); + username = new QLineEdit(); + password = new QLineEdit(); + password->setEchoMode(QLineEdit::Password); + + portSpin = new QSpinBox(); + portSpin->setMinimum(1); + portSpin->setMaximum(65535); + connectionTypeComboBox = new QComboBox(); + connectionTypeComboBox->addItem("None"); + connectionTypeComboBox->addItem("SSL"); + connectionTypeComboBox->addItem("TLS"); + connectionTypeComboBox->addItem("STARTTLS"); + + defaultSender = new QLineEdit();; + checkConnectionButton = new QPushButton("Check Connection"); + + auto layout = new QGridLayout(); + layout->addWidget(enableCheckBox, 0, 0); + layout->addWidget(new QLabel(tr("SMTP Address")), 1, 0); + layout->addWidget(smtpAddress, 1, 1, 1, 4); + layout->addWidget(new QLabel(tr("Username")), 2, 0); + layout->addWidget(username, 2, 1, 1, 4); + layout->addWidget(new QLabel(tr("Password")), 3, 0); + layout->addWidget(password, 3, 1, 1, 4); + layout->addWidget(new QLabel(tr("Port")), 4, 0); + layout->addWidget(portSpin, 4, 1, 1, 1); + layout->addWidget(new QLabel(tr("Connection Security")), 5, 0); + layout->addWidget(connectionTypeComboBox, 5, 1, 1, 1); + + layout->addWidget(new QLabel(tr("Default Sender")), 6, 0); + layout->addWidget(defaultSender, 6, 1, 1, 4); + layout->addWidget(checkConnectionButton, 7, 0); + + connect(enableCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotCheckBoxSetEnableDisable(int))); + connect(checkConnectionButton, SIGNAL(clicked(bool)), this, SLOT(slotCheckConnection())); + + + this->setLayout(layout); + setSettings(); } /********************************** @@ -332,93 +336,180 @@ MimeTab::MimeTab(QWidget *parent) * and set the buttons and checkboxes * appropriately **********************************/ -void MimeTab::setSettings() { +void SendMailTab::setSettings() { + + if (settings.value("sendMail/enable", false).toBool()) + enableCheckBox->setCheckState(Qt::Checked); + else { + enableCheckBox->setCheckState(Qt::Unchecked); + smtpAddress->setDisabled(true); + username->setDisabled(true); + password->setDisabled(true); + portSpin->setDisabled(true); + connectionTypeComboBox->setDisabled(true); + defaultSender->setDisabled(true); + checkConnectionButton->setDisabled(true); + } + + smtpAddress->setText(settings.value("sendMail/smtpAddress", QString()).toString()); + username->setText(settings.value("sendMail/username", QString()).toString()); + password->setText(settings.value("sendMail/password", QString()).toString()); + portSpin->setValue(settings.value("sendMail/port", 25).toInt()); + connectionTypeComboBox->setCurrentText(settings.value("sendMail/connectionType", "None").toString()); + defaultSender->setText(settings.value("sendMail/defaultSender", QString()).toString()); - // MIME-Parsing - if (settings.value("mime/parsemime").toBool()) - mimeParseCheckBox->setCheckState(Qt::Checked); - - // Qouted Printable - if (settings.value("mime/parseQP", true).toBool()) - mimeQPCheckBox->setCheckState(Qt::Checked); - - // Open Attachments with external app - if (settings.value("mime/openAttachment").toBool()) - mimeOpenAttachmentCheckBox->setCheckState(Qt::Checked); } /*********************************** * get the values of the buttons and * write them to settings-file *************************************/ -void MimeTab::applySettings() { - settings.setValue("mime/parsemime", mimeParseCheckBox->isChecked()); - settings.setValue("mime/parseQP", mimeQPCheckBox->isChecked()); - settings.setValue("mime/openAttachment", - mimeOpenAttachmentCheckBox->isChecked()); +void SendMailTab::applySettings() { + + settings.setValue("sendMail/smtpAddress", smtpAddress->text()); + settings.setValue("sendMail/username", username->text()); + settings.setValue("sendMail/password", password->text()); + settings.setValue("sendMail/port", portSpin->value()); + settings.setValue("sendMail/connectionType", connectionTypeComboBox->currentText()); + settings.setValue("sendMail/defaultSender", defaultSender->text()); + + settings.setValue("sendMail/enable", enableCheckBox->isChecked()); +} + +void SendMailTab::slotCheckConnection() { + + SmtpClient::ConnectionType connectionType = SmtpClient::ConnectionType::TcpConnection; + + if (connectionTypeComboBox->currentText() == "SSL") { + connectionType = SmtpClient::ConnectionType::SslConnection; + } else if (connectionTypeComboBox->currentText() == "TLS") { + connectionType = SmtpClient::ConnectionType::TlsConnection; + } else if (connectionTypeComboBox->currentText() == "STARTTLS") { + connectionType = SmtpClient::ConnectionType::TlsConnection; + } else { + connectionType = SmtpClient::ConnectionType::TcpConnection; + } + + SmtpClient smtp(smtpAddress->text(), portSpin->value(), connectionType); + + // We need to set the username (your email address) and the password + // for smtp authentification. + + smtp.setUser(username->text()); + smtp.setPassword(password->text()); + + bool if_success = true; + + if (!smtp.connectToHost()) { + QMessageBox::critical(this, tr("Fail"), tr("Fail to Connect SMTP Server")); + if_success = false; + } + if (if_success && !smtp.login()) { + QMessageBox::critical(this, tr("Fail"), tr("Fail to Login")); + if_success = false; + } + + if (if_success) + QMessageBox::information(this, tr("Success"), tr("Succeed in connecting and login")); + +} + +void SendMailTab::slotCheckBoxSetEnableDisable(int state) { + if (state == Qt::Checked) { + smtpAddress->setEnabled(true); + username->setEnabled(true); + password->setEnabled(true); + portSpin->setEnabled(true); + connectionTypeComboBox->setEnabled(true); + defaultSender->setEnabled(true); + checkConnectionButton->setEnabled(true); + } else { + smtpAddress->setDisabled(true); + username->setDisabled(true); + password->setDisabled(true); + portSpin->setDisabled(true); + connectionTypeComboBox->setDisabled(true); + defaultSender->setDisabled(true); + checkConnectionButton->setDisabled(true); + } } AppearanceTab::AppearanceTab(QWidget *parent) - : QWidget(parent), appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - /***************************************** - * Icon-Size-Box - *****************************************/ - auto *iconSizeBox = new QGroupBox(tr("Iconsize")); - iconSizeGroup = new QButtonGroup(); - iconSizeSmall = new QRadioButton(tr("small")); - iconSizeMedium = new QRadioButton(tr("medium")); - iconSizeLarge = new QRadioButton(tr("large")); - - iconSizeGroup->addButton(iconSizeSmall, 1); - iconSizeGroup->addButton(iconSizeMedium, 2); - iconSizeGroup->addButton(iconSizeLarge, 3); - - auto *iconSizeBoxLayout = new QHBoxLayout(); - iconSizeBoxLayout->addWidget(iconSizeSmall); - iconSizeBoxLayout->addWidget(iconSizeMedium); - iconSizeBoxLayout->addWidget(iconSizeLarge); - - iconSizeBox->setLayout(iconSizeBoxLayout); - - /***************************************** - * Icon-Style-Box - *****************************************/ - auto *iconStyleBox = new QGroupBox(tr("Iconstyle")); - iconStyleGroup = new QButtonGroup(); - iconTextButton = new QRadioButton(tr("just text")); - iconIconsButton = new QRadioButton(tr("just icons")); - iconAllButton = new QRadioButton(tr("text and icons")); - - iconStyleGroup->addButton(iconTextButton, 1); - iconStyleGroup->addButton(iconIconsButton, 2); - iconStyleGroup->addButton(iconAllButton, 3); - - auto *iconStyleBoxLayout = new QHBoxLayout(); - iconStyleBoxLayout->addWidget(iconTextButton); - iconStyleBoxLayout->addWidget(iconIconsButton); - iconStyleBoxLayout->addWidget(iconAllButton); - - iconStyleBox->setLayout(iconStyleBoxLayout); - - /***************************************** - * Window-Size-Box - *****************************************/ - auto *windowSizeBox = new QGroupBox(tr("Windowstate")); - auto *windowSizeBoxLayout = new QHBoxLayout(); - windowSizeCheckBox = - new QCheckBox(tr("Save window size and position on exit."), this); - windowSizeBoxLayout->addWidget(windowSizeCheckBox); - windowSizeBox->setLayout(windowSizeBoxLayout); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(iconSizeBox); - mainLayout->addWidget(iconStyleBox); - mainLayout->addWidget(windowSizeBox); - mainLayout->addStretch(1); - setSettings(); - setLayout(mainLayout); + : QWidget(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + /***************************************** + * Icon-Size-Box + *****************************************/ + auto *iconSizeBox = new QGroupBox(tr("Iconsize")); + iconSizeGroup = new QButtonGroup(); + iconSizeSmall = new QRadioButton(tr("small")); + iconSizeMedium = new QRadioButton(tr("medium")); + iconSizeLarge = new QRadioButton(tr("large")); + + iconSizeGroup->addButton(iconSizeSmall, 1); + iconSizeGroup->addButton(iconSizeMedium, 2); + iconSizeGroup->addButton(iconSizeLarge, 3); + + auto *iconSizeBoxLayout = new QHBoxLayout(); + iconSizeBoxLayout->addWidget(iconSizeSmall); + iconSizeBoxLayout->addWidget(iconSizeMedium); + iconSizeBoxLayout->addWidget(iconSizeLarge); + + iconSizeBox->setLayout(iconSizeBoxLayout); + + /***************************************** + * Icon-Style-Box + *****************************************/ + auto *iconStyleBox = new QGroupBox(tr("Iconstyle")); + iconStyleGroup = new QButtonGroup(); + iconTextButton = new QRadioButton(tr("just text")); + iconIconsButton = new QRadioButton(tr("just icons")); + iconAllButton = new QRadioButton(tr("text and icons")); + + iconStyleGroup->addButton(iconTextButton, 1); + iconStyleGroup->addButton(iconIconsButton, 2); + iconStyleGroup->addButton(iconAllButton, 3); + + auto *iconStyleBoxLayout = new QHBoxLayout(); + iconStyleBoxLayout->addWidget(iconTextButton); + iconStyleBoxLayout->addWidget(iconIconsButton); + iconStyleBoxLayout->addWidget(iconAllButton); + + iconStyleBox->setLayout(iconStyleBoxLayout); + + /***************************************** + * Window-Size-Box + *****************************************/ + auto *windowSizeBox = new QGroupBox(tr("Windowstate")); + auto *windowSizeBoxLayout = new QHBoxLayout(); + windowSizeCheckBox = + new QCheckBox(tr("Save window size and position on exit."), this); + windowSizeBoxLayout->addWidget(windowSizeCheckBox); + windowSizeBox->setLayout(windowSizeBoxLayout); + + /***************************************** + * Info-Board-Font-Size-Box + *****************************************/ + + auto *infoBoardBox = new QGroupBox(tr("Information Board")); + auto *infoBoardLayout = new QHBoxLayout(); + infoBoardFontSizeSpin = new QSpinBox(); + infoBoardFontSizeSpin->setRange(9, 18); + infoBoardFontSizeSpin->setValue(10); + infoBoardFontSizeSpin->setSingleStep(1); + infoBoardLayout->addWidget(new QLabel(tr(" Front Size"))); + infoBoardLayout->addWidget(infoBoardFontSizeSpin); + infoBoardBox->setLayout(infoBoardLayout); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(iconSizeBox); + mainLayout->addWidget(iconStyleBox); + mainLayout->addWidget(windowSizeBox); + mainLayout->addWidget(infoBoardBox); + mainLayout->addStretch(1); + setSettings(); + setLayout(mainLayout); } /********************************** @@ -428,40 +519,46 @@ AppearanceTab::AppearanceTab(QWidget *parent) **********************************/ void AppearanceTab::setSettings() { - // Iconsize - QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize(); - switch (iconSize.height()) { - case 12: - iconSizeSmall->setChecked(true); - break; - case 24: - iconSizeMedium->setChecked(true); - break; - case 32: - iconSizeLarge->setChecked(true); - break; - } - // Iconstyle - Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>( - settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon) - .toUInt()); - switch (iconStyle) { - case Qt::ToolButtonTextOnly: - iconTextButton->setChecked(true); - break; - case Qt::ToolButtonIconOnly: - iconIconsButton->setChecked(true); - break; - case Qt::ToolButtonTextUnderIcon: - iconAllButton->setChecked(true); - break; - default: - break; - } - - // Window Save and Position - if (settings.value("window/windowSave").toBool()) - windowSizeCheckBox->setCheckState(Qt::Checked); + // Iconsize + QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize(); + switch (iconSize.height()) { + case 12: + iconSizeSmall->setChecked(true); + break; + case 24: + iconSizeMedium->setChecked(true); + break; + case 32: + iconSizeLarge->setChecked(true); + break; + } + // Iconstyle + Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>( + settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon) + .toUInt()); + switch (iconStyle) { + case Qt::ToolButtonTextOnly: + iconTextButton->setChecked(true); + break; + case Qt::ToolButtonIconOnly: + iconIconsButton->setChecked(true); + break; + case Qt::ToolButtonTextUnderIcon: + iconAllButton->setChecked(true); + break; + default: + break; + } + + // Window Save and Position + if (settings.value("window/windowSave").toBool()) + windowSizeCheckBox->setCheckState(Qt::Checked); + + // infoBoardFontSize + auto infoBoardFontSize = settings.value("informationBoard/fontSize", 10).toInt(); + if (infoBoardFontSize < 9 || infoBoardFontSize > 18) + infoBoardFontSize = 10; + infoBoardFontSizeSpin->setValue(infoBoardFontSize); } /*********************************** @@ -469,72 +566,74 @@ void AppearanceTab::setSettings() { * write them to settings-file *************************************/ void AppearanceTab::applySettings() { - switch (iconSizeGroup->checkedId()) { - case 1: - settings.setValue("toolbar/iconsize", QSize(12, 12)); - break; - case 2: - settings.setValue("toolbar/iconsize", QSize(24, 24)); - break; - case 3: - settings.setValue("toolbar/iconsize", QSize(32, 32)); - break; - } - - switch (iconStyleGroup->checkedId()) { - case 1: - settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly); - break; - case 2: - settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly); - break; - case 3: - settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon); - break; - } - - settings.setValue("window/windowSave", windowSizeCheckBox->isChecked()); + switch (iconSizeGroup->checkedId()) { + case 1: + settings.setValue("toolbar/iconsize", QSize(12, 12)); + break; + case 2: + settings.setValue("toolbar/iconsize", QSize(24, 24)); + break; + case 3: + settings.setValue("toolbar/iconsize", QSize(32, 32)); + break; + } + + switch (iconStyleGroup->checkedId()) { + case 1: + settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly); + break; + case 2: + settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly); + break; + case 3: + settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon); + break; + } + + settings.setValue("window/windowSave", windowSizeCheckBox->isChecked()); + + settings.setValue("informationBoard/fontSize", infoBoardFontSizeSpin->value()); } KeyserverTab::KeyserverTab(QWidget *parent) - : QWidget(parent), appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - - auto keyServerList = settings.value("keyserver/keyServerList").toStringList(); - - auto *mainLayout = new QVBoxLayout(this); - - auto *label = new QLabel(tr("Default Keyserver for import:")); - comboBox = new QComboBox; - comboBox->setEditable(false); - comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - - for (const auto &keyServer : keyServerList) { - comboBox->addItem(keyServer); - qDebug() << "KeyserverTab Get ListItemText" << keyServer; - } - - comboBox->setCurrentText( - settings.value("keyserver/defaultKeyServer").toString()); - - auto *addKeyServerBox = new QWidget(this); - auto *addKeyServerLayout = new QHBoxLayout(addKeyServerBox); - auto *http = new QLabel("URL: "); - newKeyServerEdit = new QLineEdit(this); - auto *newKeyServerButton = new QPushButton(tr("Add"), this); - connect(newKeyServerButton, SIGNAL(clicked()), this, SLOT(addKeyServer())); - addKeyServerLayout->addWidget(http); - addKeyServerLayout->addWidget(newKeyServerEdit); - addKeyServerLayout->addWidget(newKeyServerButton); - - mainLayout->addWidget(label); - mainLayout->addWidget(comboBox); - mainLayout->addWidget(addKeyServerBox); - mainLayout->addStretch(1); - - // Read keylist from ini-file and fill it into combobox - setSettings(); + : QWidget(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + + auto keyServerList = settings.value("keyserver/keyServerList").toStringList(); + + auto *mainLayout = new QVBoxLayout(this); + + auto *label = new QLabel(tr("Default Key Server for import:")); + comboBox = new QComboBox; + comboBox->setEditable(false); + comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + + for (const auto &keyServer : keyServerList) { + comboBox->addItem(keyServer); + qDebug() << "KeyserverTab Get ListItemText" << keyServer; + } + + comboBox->setCurrentText( + settings.value("keyserver/defaultKeyServer").toString()); + + auto *addKeyServerBox = new QWidget(this); + auto *addKeyServerLayout = new QHBoxLayout(addKeyServerBox); + auto *http = new QLabel("URL: "); + newKeyServerEdit = new QLineEdit(this); + auto *newKeyServerButton = new QPushButton(tr("Add"), this); + connect(newKeyServerButton, SIGNAL(clicked()), this, SLOT(addKeyServer())); + addKeyServerLayout->addWidget(http); + addKeyServerLayout->addWidget(newKeyServerEdit); + addKeyServerLayout->addWidget(newKeyServerButton); + + mainLayout->addWidget(label); + mainLayout->addWidget(comboBox); + mainLayout->addWidget(addKeyServerBox); + mainLayout->addStretch(1); + + // Read keylist from ini-file and fill it into combobox + setSettings(); } /********************************** @@ -543,23 +642,23 @@ KeyserverTab::KeyserverTab(QWidget *parent) * appropriately **********************************/ void KeyserverTab::setSettings() { - auto *keyServerList = new QStringList(); - for (int i = 0; i < comboBox->count(); i++) { - keyServerList->append(comboBox->itemText(i)); - qDebug() << "KeyserverTab ListItemText" << comboBox->itemText(i); - } - settings.setValue("keyserver/keyServerList", *keyServerList); - settings.setValue("keyserver/defaultKeyServer", comboBox->currentText()); + auto *keyServerList = new QStringList(); + for (int i = 0; i < comboBox->count(); i++) { + keyServerList->append(comboBox->itemText(i)); + qDebug() << "KeyserverTab ListItemText" << comboBox->itemText(i); + } + settings.setValue("keyserver/keyServerList", *keyServerList); + settings.setValue("keyserver/defaultKeyServer", comboBox->currentText()); } void KeyserverTab::addKeyServer() { - if (newKeyServerEdit->text().startsWith("http://") || - newKeyServerEdit->text().startsWith("https://")) { - comboBox->addItem(newKeyServerEdit->text()); - } else { - comboBox->addItem("http://" + newKeyServerEdit->text()); - } - comboBox->setCurrentIndex(comboBox->count() - 1); + if (newKeyServerEdit->text().startsWith("http://") || + newKeyServerEdit->text().startsWith("https://")) { + comboBox->addItem(newKeyServerEdit->text()); + } else { + comboBox->addItem("http://" + newKeyServerEdit->text()); + } + comboBox->setCurrentIndex(comboBox->count() - 1); } /*********************************** @@ -567,112 +666,112 @@ void KeyserverTab::addKeyServer() { * write them to settings-file *************************************/ void KeyserverTab::applySettings() { - settings.setValue("keyserver/defaultKeyServer", comboBox->currentText()); + settings.setValue("keyserver/defaultKeyServer", comboBox->currentText()); } AdvancedTab::AdvancedTab(QWidget *parent) - : QWidget(parent), appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - /***************************************** - * Steganography Box - *****************************************/ - auto *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]")); - auto *steganoBoxLayout = new QHBoxLayout(); - steganoCheckBox = new QCheckBox(tr("Show Steganographic Options."), this); - steganoBoxLayout->addWidget(steganoCheckBox); - steganoBox->setLayout(steganoBoxLayout); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(steganoBox); - setSettings(); - mainLayout->addStretch(1); - setLayout(mainLayout); + : QWidget(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + /***************************************** + * Steganography Box + *****************************************/ + auto *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]")); + auto *steganoBoxLayout = new QHBoxLayout(); + steganoCheckBox = new QCheckBox(tr("Show Steganographic Options."), this); + steganoBoxLayout->addWidget(steganoCheckBox); + steganoBox->setLayout(steganoBoxLayout); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(steganoBox); + setSettings(); + mainLayout->addStretch(1); + setLayout(mainLayout); } void AdvancedTab::setSettings() { - if (settings.value("advanced/steganography").toBool()) { - steganoCheckBox->setCheckState(Qt::Checked); - } + if (settings.value("advanced/steganography").toBool()) { + steganoCheckBox->setCheckState(Qt::Checked); + } } void AdvancedTab::applySettings() { - settings.setValue("advanced/steganography", steganoCheckBox->isChecked()); + settings.setValue("advanced/steganography", steganoCheckBox->isChecked()); } GpgPathsTab::GpgPathsTab(QWidget *parent) - : QWidget(parent), appPath(qApp->applicationDirPath()), - settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", - QSettings::IniFormat) { - setSettings(); - - /***************************************** - * Keydb Box - *****************************************/ - auto *keydbBox = new QGroupBox(tr("Relative path to keydb")); - auto *keydbBoxLayout = new QGridLayout(); - - // Label containing the current keydbpath relative to default keydb path - keydbLabel = new QLabel(accKeydbPath, this); - - auto *keydbButton = new QPushButton("Change keydb path", this); - connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir())); - auto *keydbDefaultButton = new QPushButton("Set keydb to default path", this); - connect(keydbDefaultButton, SIGNAL(clicked()), this, - SLOT(setKeydbPathToDefault())); - - keydbBox->setLayout(keydbBoxLayout); - keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")), 1, 1); - keydbBoxLayout->addWidget(keydbLabel, 1, 2); - keydbBoxLayout->addWidget(keydbButton, 1, 3); - keydbBoxLayout->addWidget(keydbDefaultButton, 2, 3); - keydbBoxLayout->addWidget( - new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you " - "change the keydb path!")), - 3, 1, 1, 3); - - auto *mainLayout = new QVBoxLayout; - mainLayout->addWidget(keydbBox); - mainLayout->addStretch(1); - setLayout(mainLayout); + : QWidget(parent), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { + setSettings(); + + /***************************************** + * Keydb Box + *****************************************/ + auto *keydbBox = new QGroupBox(tr("Relative path to keydb")); + auto *keydbBoxLayout = new QGridLayout(); + + // Label containing the current keydbpath relative to default keydb path + keydbLabel = new QLabel(accKeydbPath, this); + + auto *keydbButton = new QPushButton("Change keydb path", this); + connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir())); + auto *keydbDefaultButton = new QPushButton("Set keydb to default path", this); + connect(keydbDefaultButton, SIGNAL(clicked()), this, + SLOT(setKeydbPathToDefault())); + + keydbBox->setLayout(keydbBoxLayout); + keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")), 1, 1); + keydbBoxLayout->addWidget(keydbLabel, 1, 2); + keydbBoxLayout->addWidget(keydbButton, 1, 3); + keydbBoxLayout->addWidget(keydbDefaultButton, 2, 3); + keydbBoxLayout->addWidget( + new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you " + "change the keydb path!")), + 3, 1, 1, 3); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(keydbBox); + mainLayout->addStretch(1); + setLayout(mainLayout); } QString GpgPathsTab::getRelativePath(const QString &dir1, const QString &dir2) { - QDir dir(dir1); - QString s; - - s = dir.relativeFilePath(dir2); - qDebug() << "relative path: " << s; - if (s.isEmpty()) { - s = "."; - } - return s; + QDir dir(dir1); + QString s; + + s = dir.relativeFilePath(dir2); + qDebug() << "relative path: " << s; + if (s.isEmpty()) { + s = "."; + } + return s; } void GpgPathsTab::setKeydbPathToDefault() { - accKeydbPath = "."; - keydbLabel->setText("."); + accKeydbPath = "."; + keydbLabel->setText("."); } QString GpgPathsTab::chooseKeydbDir() { - QString dir = QFileDialog::getExistingDirectory( - this, tr("Choose keydb directory"), accKeydbPath, - QFileDialog::ShowDirsOnly); + QString dir = QFileDialog::getExistingDirectory( + this, tr("Choose keydb directory"), accKeydbPath, + QFileDialog::ShowDirsOnly); - accKeydbPath = getRelativePath(defKeydbPath, dir); - keydbLabel->setText(accKeydbPath); - return ""; + accKeydbPath = getRelativePath(defKeydbPath, dir); + keydbLabel->setText(accKeydbPath); + return ""; } void GpgPathsTab::setSettings() { - defKeydbPath = qApp->applicationDirPath() + "/keydb"; + defKeydbPath = qApp->applicationDirPath() + "/keydb"; - accKeydbPath = settings.value("gpgpaths/keydbpath").toString(); - if (accKeydbPath.isEmpty()) { - accKeydbPath = "."; - } + accKeydbPath = settings.value("gpgpaths/keydbpath").toString(); + if (accKeydbPath.isEmpty()) { + accKeydbPath = "."; + } } void GpgPathsTab::applySettings() { - settings.setValue("gpgpaths/keydbpath", accKeydbPath); + settings.setValue("gpgpaths/keydbpath", accKeydbPath); } diff --git a/src/ui/WaitingDialog.cpp b/src/ui/WaitingDialog.cpp index 8281385a..daccc3ca 100644 --- a/src/ui/WaitingDialog.cpp +++ b/src/ui/WaitingDialog.cpp @@ -1,15 +1,20 @@ #include "ui/WaitingDialog.h" -WaitingDialog::WaitingDialog(QWidget *parent) : QDialog(parent) { +WaitingDialog::WaitingDialog(const QString &title, QWidget *parent) : QDialog(parent) { auto *pb = new QProgressBar(); pb->setRange(0, 0); + pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + pb->setTextVisible(false); auto *layout = new QVBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); layout->addWidget(pb); this->setLayout(layout); this->setModal(true); - this->setWindowTitle(tr("Processing")); + this->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint); + this->setWindowTitle(title); this->setFixedSize(240, 42); this->show(); } diff --git a/src/ui/Wizard.cpp b/src/ui/Wizard.cpp index 456e8c52..b0486cc9 100644 --- a/src/ui/Wizard.cpp +++ b/src/ui/Wizard.cpp @@ -108,16 +108,20 @@ bool Wizard::importPubAndSecKeysFromDir(const QString &dir, KeyMgmt *keyMgmt) { IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent), appPath(qApp->applicationDirPath()), settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat) { - setTitle(tr("Getting started...")); + setTitle(tr("Getting Started...")); setSubTitle(tr("... with GPGFrontend")); - auto *topLabel = new QLabel(tr("To use GPGFrontend for decrypting and signing messages, you need a " - "private key. The next page will help you with " - "key generation or import.<br><br>" - "For more information have a look at the <a href='docu_concepts.html'>concepts</a> " - "(by clicking the link, the page will open in the main window). <br>")); + auto *topLabel = new QLabel(tr("Welcome to use GPGFrontend for decrypting and signing text or file!")+ + " <br><br><a href='https://github.com/saturneric/GpgFrontend'>GpgFrontend</a> " + + tr("is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.") + + tr("For brief information have a look at the") + "<a href='https://saturneric.github.io/GpgFrontend/index.html#/overview'>"+ + tr("Overview") +"</a> (" + + tr("by clicking the link, the page will open in the web browser") + + "). <br>"); + topLabel->setTextFormat(Qt::RichText); + topLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + topLabel->setOpenExternalLinks(true); topLabel->setWordWrap(true); - // connect(topLabel, SIGNAL(linkActivated(QString)), parentWidget()->parentWidget(), SLOT(openHelp(QString))); // QComboBox for language selection auto *langLabel = new QLabel(tr("Choose a Language")); @@ -126,9 +130,9 @@ IntroPage::IntroPage(QWidget *parent) languages = SettingsDialog::listLanguages(); auto *langSelectBox = new QComboBox(); - foreach(QString l, languages) { - langSelectBox->addItem(l); - } + for(const auto &l : languages) { + langSelectBox->addItem(l); + } // selected entry from config QString langKey = settings.value("int/lang").toString(); QString langValue = languages.value(langKey); @@ -162,25 +166,31 @@ ChoosePage::ChoosePage(QWidget *parent) setSubTitle(tr("...by clicking on the appropriate link.")); auto *keygenLabel = new QLabel(tr("If you have never used GPGFrontend before and also don't own a gpg key yet you " - "may possibly want to read how to") + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/generate-key\">" - + tr("create a new keypair") + "</a><hr>"); + "may possibly want to read how to") + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/generate-key\">" + + tr("Generate Key") + "</a><hr>"); keygenLabel->setTextFormat(Qt::RichText); keygenLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); keygenLabel->setOpenExternalLinks(true); keygenLabel->setWordWrap(true); - auto *encrDecyTextLabel = new QLabel(tr("If you want to learn how to encrypt and decrypt text, you can read ") + auto *encrDecyTextLabel = new QLabel(tr("If you want to learn how to encrypt, decrypt, sign and verify text, you can read ") + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/encrypt-decrypt-text\">" - + tr("this document") + "</a><hr>"); + + tr("Encrypt & Decrypt Text") + "</a> " + tr("or") + + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-text\">" + + tr("Sign & Verify Text") + +"</a><hr>"); encrDecyTextLabel->setTextFormat(Qt::RichText); encrDecyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); encrDecyTextLabel->setOpenExternalLinks(true); encrDecyTextLabel->setWordWrap(true); - auto *signVerifyTextLabel = new QLabel(tr("If you want to sign and verify text, you can read ") - + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-text\">" - + tr("this document") + "</a>"); + auto *signVerifyTextLabel = new QLabel(tr("If you want to operate file, you can read ") + + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/encrypt-decrypt-file\">" + + tr("Encrypt & Sign File") + "</a> " + tr("or") + + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-file\">" + + tr("Sign & Verify File") + +"</a><hr>"); signVerifyTextLabel->setTextFormat(Qt::RichText); signVerifyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); signVerifyTextLabel->setOpenExternalLinks(true); diff --git a/src/ui/help/AboutDialog.cpp b/src/ui/help/AboutDialog.cpp new file mode 100644 index 00000000..807c509d --- /dev/null +++ b/src/ui/help/AboutDialog.cpp @@ -0,0 +1,215 @@ +/** + * This file is part of GPGFrontend. + * + * GPGFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + +#include "ui/help/AboutDialog.h" +#include "GpgFrontendBuildInfo.h" + +#include "rapidjson/document.h" +#include "rapidjson/writer.h" + +using namespace rapidjson; + +AboutDialog::AboutDialog(int defaultIndex, QWidget *parent) + : QDialog(parent) { + this->setWindowTitle(tr("About ") + qApp->applicationName()); + + auto *tabWidget = new QTabWidget; + auto *infoTab = new InfoTab(); + auto *translatorsTab = new TranslatorsTab(); + auto *updateTab = new UpdateTab(); + + tabWidget->addTab(infoTab, tr("General")); + tabWidget->addTab(translatorsTab, tr("Translators")); + tabWidget->addTab(updateTab, tr("Update")); + + connect(tabWidget, &QTabWidget::currentChanged, this, [&](int index) { + qDebug() << "Current Index" << index; + if(index == 2) { + updateTab->getLatestVersion(); + } + }); + + if(defaultIndex < tabWidget->count() && defaultIndex >= 0) { + tabWidget->setCurrentIndex(defaultIndex); + } + + auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(close())); + + auto *mainLayout = new QVBoxLayout; + mainLayout->addWidget(tabWidget); + mainLayout->addWidget(buttonBox); + setLayout(mainLayout); + + this->exec(); +} + +InfoTab::InfoTab(QWidget *parent) + : QWidget(parent) { + auto *pixmap = new QPixmap(":gpgfrontend-logo.png"); + auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>" + + "<center><b>" + qApp->applicationVersion() + "</b></center>" + + "<center>" + GIT_VERSION + "</center>" + + tr("<br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>" + "and installation-free gpg front-end tool.<br>" + "It visualizes most of the common operations of gpg commands.<br>" + "It's licensed under the GPL v3<br><br>" + "<b>Developer:</b><br>" + "Saturneric<br><br>" + "If you have any questions or suggestions, raise an issue<br/>" + "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") + + tr("<br><br> Built with Qt ") + qVersion() + + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() + + tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>"); + + auto *layout = new QGridLayout(); + auto *pixmapLabel = new QLabel(); + pixmapLabel->setPixmap(*pixmap); + layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter); + auto *aboutLabel = new QLabel(); + aboutLabel->setText(*text); + aboutLabel->setOpenExternalLinks(true); + layout->addWidget(aboutLabel, 1, 0, 1, -1); + layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, + QSizePolicy::Fixed), 2, 1, 1, 1); + + setLayout(layout); +} + +TranslatorsTab::TranslatorsTab(QWidget *parent) + : QWidget(parent) { + QFile translatorsFile; + translatorsFile.setFileName(qApp->applicationDirPath() + "/About"); + translatorsFile.open(QIODevice::ReadOnly); + QByteArray inBuffer = translatorsFile.readAll(); + + auto *label = new QLabel(inBuffer); + auto *mainLayout = new QVBoxLayout(this); + mainLayout->addWidget(label); + + setLayout(mainLayout); +} + +UpdateTab::UpdateTab(QWidget *parent) { + auto *pixmap = new QPixmap(":gpgfrontend-logo.png"); + auto *layout = new QGridLayout(); + auto *pixmapLabel = new QLabel(); + pixmapLabel->setPixmap(*pixmap); + layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter); + + currentVersion = "v" + QString::number(VERSION_MAJOR) + "." + + QString::number(VERSION_MINOR) + "." + + QString::number(VERSION_PATCH); + + auto tipsLabel = new QLabel(); + tipsLabel->setText("<center>" + + tr("It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.") + + "</center><br><center>" + + tr("New versions not only represent new features, but also often represent functional and security fixes.") + "</center>"); + tipsLabel->setWordWrap(true); + + currentVersionLabel = new QLabel(); + currentVersionLabel->setText("<center>" + tr("Current Version: ") + "<b>" + currentVersion + "</b></center>"); + currentVersionLabel->setWordWrap(true); + + latestVersionLabel = new QLabel(); + latestVersionLabel->setWordWrap(true); + + upgradeLabel = new QLabel(); + upgradeLabel->setText("<center>" + + tr("The current version is inconsistent with the latest version on github.") + + "</center><br><center>" + + tr("Please click <a href=\"https://github.com/saturneric/GpgFrontend/releases\">here</a> to download the latest version.") + "</center>"); + upgradeLabel->setWordWrap(true); + upgradeLabel->setOpenExternalLinks(true); + upgradeLabel->setHidden(true); + + pb = new QProgressBar(); + pb->setRange(0, 0); + pb->setTextVisible(false); + + layout->addWidget(tipsLabel, 1, 0, 1, -1); + layout->addWidget(currentVersionLabel, 2, 0, 1, -1); + layout->addWidget(latestVersionLabel, 3, 0, 1, -1); + layout->addWidget(upgradeLabel, 4, 0, 1, -1); + layout->addWidget(pb, 5, 0, 1, -1); + layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, + QSizePolicy::Fixed), 2, 1, 1, 1); + + setLayout(layout); +} + +void UpdateTab::getLatestVersion() { + + this->pb->setHidden(false); + + qDebug() << "Try to get latest version"; + + QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; + + auto manager = new QNetworkAccessManager(this); + + QNetworkRequest request; + request.setUrl(QUrl(baseUrl)); + + QNetworkReply *replay = manager->get(request); + + while(replay->isRunning()) { + QApplication::processEvents(); + } + + this->pb->setHidden(true); + + if(replay->error() != QNetworkReply::NoError) { + qDebug() << "VersionCheckThread Found Network Error"; + auto latestVersion = "Unknown"; + latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>"); + return; + } + + QByteArray bytes = replay->readAll(); + + Document d; + d.Parse(bytes.constData()); + + QString latestVersion = d["tag_name"].GetString(); + + qDebug() << "Latest Version From Github" << latestVersion; + + QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)"); + QRegularExpressionMatch match = re.match(latestVersion); + if (match.hasMatch()) { + latestVersion = match.captured(0); // matched == "23 def" + qDebug() << "Latest Version Matched" << latestVersion; + } else { + latestVersion = "Unknown"; + } + + latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>"); + + if(latestVersion > currentVersion) { + upgradeLabel->setHidden(false); + } + +} diff --git a/src/ui/help/VersionCheckThread.cpp b/src/ui/help/VersionCheckThread.cpp new file mode 100644 index 00000000..c7c77d1c --- /dev/null +++ b/src/ui/help/VersionCheckThread.cpp @@ -0,0 +1,55 @@ +// +// Created by Administrator on 2021/7/12. +// + +#include "ui/help/VersionCheckThread.h" +#include "GpgFrontendBuildInfo.h" +#include "rapidjson/document.h" +#include "rapidjson/writer.h" + +using namespace rapidjson; + +void VersionCheckThread::run() { + qDebug() << "Start Version Thread to get latest version from Github"; + + auto currentVersion = "v" + QString::number(VERSION_MAJOR) + "." + + QString::number(VERSION_MINOR) + "." + + QString::number(VERSION_PATCH); + + while(mNetworkReply->isRunning()) { + QApplication::processEvents(); + } + + if(mNetworkReply->error() != QNetworkReply::NoError) { + qDebug() << "VersionCheckThread Found Network Error"; + return; + } + + QByteArray bytes = mNetworkReply->readAll(); + + Document d; + d.Parse(bytes.constData()); + + QString latestVersion = d["tag_name"].GetString(); + + qDebug() << "Latest Version From Github" << latestVersion; + + QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)"); + QRegularExpressionMatch match = re.match(latestVersion); + if (match.hasMatch()) { + latestVersion = match.captured(0); // matched == "23 def" + qDebug() << "Latest Version Matched" << latestVersion; + } else { + latestVersion = currentVersion; + qDebug() << "Latest Version Unknown" << latestVersion; + } + + if(latestVersion != currentVersion) { + emit upgradeVersion(currentVersion, latestVersion); + } + +} + +VersionCheckThread::VersionCheckThread(QNetworkReply *networkReply):mNetworkReply(networkReply) { + +} diff --git a/src/ui/keygen/KeygenDialog.cpp b/src/ui/keygen/KeygenDialog.cpp index b9fdae3f..7991ddd1 100644 --- a/src/ui/keygen/KeygenDialog.cpp +++ b/src/ui/keygen/KeygenDialog.cpp @@ -74,8 +74,7 @@ void KeyGenDialog::slotKeyGenAccept() { * primary keys should have a reasonable expiration date (no more than 2 years in the future) */ if(dateEdit->dateTime() > QDateTime::currentDateTime().addYears(2)) { - - errorString.append(tr(" Expiration time no more than 2 years. ")); + errorString.append(tr(" Expiration time no more than 2 years. \n")); } if (errorString.isEmpty()) { @@ -148,7 +147,7 @@ QGroupBox *KeyGenDialog::create_key_usage_group_box() { auto *groupBox = new QGroupBox(this); auto *grid = new QGridLayout(this); - groupBox->setTitle("Key Usage"); + groupBox->setTitle(tr("Key Usage")); auto* encrypt = new QCheckBox(tr("Encryption"), groupBox); encrypt->setTristate(false); diff --git a/src/ui/keygen/SubkeyGenerateThread.cpp b/src/ui/keygen/SubkeyGenerateThread.cpp index 4f19ac1f..125f35f8 100644 --- a/src/ui/keygen/SubkeyGenerateThread.cpp +++ b/src/ui/keygen/SubkeyGenerateThread.cpp @@ -24,8 +24,6 @@ #include "ui/keygen/SubkeyGenerateThread.h" -#include <utility> - SubkeyGenerateThread::SubkeyGenerateThread(GpgKey key, GenKeyInfo *keyGenParams, GpgME::GpgContext *ctx) : mKey(std::move(key)), keyGenParams(keyGenParams) , mCtx(ctx) { connect(this, &SubkeyGenerateThread::finished, this, &SubkeyGenerateThread::deleteLater); diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp index 013d8e11..9ca4e37e 100644 --- a/src/ui/keypair_details/KeyPairDetailTab.cpp +++ b/src/ui/keypair_details/KeyPairDetailTab.cpp @@ -23,8 +23,10 @@ */ #include "ui/keypair_details/KeyPairDetailTab.h" +#include "ui/WaitingDialog.h" -KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey), QWidget(parent) { +KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey), + QWidget(parent) { mCtx = ctx; keyid = new QString(mKey.id); @@ -53,8 +55,8 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q algorithmVarLabel = new QLabel(); // Show the situation that master key not exists. - masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? "Exists" : "Not Exists"); - if(!mKey.has_master_key){ + masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? tr("Exists") : tr("Not Exists")); + if (!mKey.has_master_key) { auto paletteExpired = masterKeyExistVarLabel->palette(); paletteExpired.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::red); masterKeyExistVarLabel->setPalette(paletteExpired); @@ -64,7 +66,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q masterKeyExistVarLabel->setPalette(paletteValid); } - if(mKey.expired){ + if (mKey.expired) { auto paletteExpired = expireVarLabel->palette(); paletteExpired.setColor(expireVarLabel->foregroundRole(), Qt::red); expireVarLabel->setPalette(paletteExpired); @@ -131,18 +133,27 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q auto *privKeyBox = new QGroupBox(tr("Operations")); auto *vboxPK = new QVBoxLayout(); - auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkeys)")); + auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkey)")); vboxPK->addWidget(exportButton); connect(exportButton, SIGNAL(clicked()), this, SLOT(slotExportPrivateKey())); - if(mKey.has_master_key) { + if (mKey.has_master_key) { auto *editExpiresButton = new QPushButton(tr("Modify Expiration Datetime (Master Key)")); vboxPK->addWidget(editExpiresButton); connect(editExpiresButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime())); + auto hBoxLayout = new QHBoxLayout(); auto *keyServerOperaButton = new QPushButton(tr("Key Server Operation (Pubkey)")); keyServerOperaButton->setStyleSheet("text-align:center;"); - vboxPK->addWidget(keyServerOperaButton); + + auto *revokeCertGenButton = new QPushButton(tr("Generate Revoke Certificate")); + revokeCertGenButton->setDisabled(true); + connect(revokeCertGenButton, SIGNAL(clicked()), this, SLOT(slotGenRevokeCert())); + + hBoxLayout->addWidget(keyServerOperaButton); + hBoxLayout->addWidget(revokeCertGenButton); + + vboxPK->addLayout(hBoxLayout); connect(keyServerOperaButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime())); // Set Menu @@ -152,8 +163,6 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q privKeyBox->setLayout(vboxPK); mvbox->addWidget(privKeyBox); - - } if ((mKey.expired) || (mKey.revoked)) { @@ -169,7 +178,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q expLabel->setText(tr("Warning: The Master Key has been revoked")); } - iconLabel->setPixmap(pixmap.scaled(24,24,Qt::KeepAspectRatio)); + iconLabel->setPixmap(pixmap.scaled(24, 24, Qt::KeepAspectRatio)); QFont font = expLabel->font(); font.setBold(true); expLabel->setFont(font); @@ -179,10 +188,11 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q mvbox->addLayout(expBox); } + mvbox->setContentsMargins(0, 0, 0, 0); + connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshKeyInfo())); slotRefreshKeyInfo(); - setAttribute(Qt::WA_DeleteOnClose, true); setLayout(mvbox); } @@ -190,22 +200,23 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q void KeyPairDetailTab::slotExportPrivateKey() { // Show a information box with explanation about private key int ret = QMessageBox::information(this, tr("Exporting private Key"), - tr("<h3>You are about to export your <font color=\"red\">PRIVATE KEY</font>!</h3>\n" - "This is NOT your Public Key, so DON'T give it away.<br />" - "Do you REALLY want to export your PRIVATE KEY?"), + "<h3>" + tr("You are about to export your") + "<font color=\"red\">" + + tr("PRIVATE KEY") + "</font>!</h3>\n" + + tr("This is NOT your Public Key, so DON'T give it away.") + "<br />" + + tr("Do you REALLY want to export your PRIVATE KEY?"), QMessageBox::Cancel | QMessageBox::Ok); // export key, if ok was clicked if (ret == QMessageBox::Ok) { auto *keyArray = new QByteArray(); - if(!mCtx->exportSecretKey(mKey, keyArray)) { - QMessageBox::critical(this, "Error", "An error occurred during the export operation."); - return; - } + if (!mCtx->exportSecretKey(mKey, keyArray)) { + QMessageBox::critical(this, "Error", "An error occurred during the export operation."); + return; + } auto &key = mCtx->getKeyById(*keyid); - QString fileString = key.name + " " +key.email + "(" + + QString fileString = key.name + " " + key.email + "(" + key.id + ")_secret.asc"; QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)"); @@ -251,13 +262,13 @@ void KeyPairDetailTab::slotRefreshKeyInfo() { QString usage; QTextStream usage_steam(&usage); - if(mKey.can_certify) + if (mKey.can_certify) usage_steam << "Cert "; - if(mKey.can_encrypt) + if (mKey.can_encrypt) usage_steam << "Encr "; - if(mKey.can_sign) + if (mKey.can_sign) usage_steam << "Sign "; - if(mKey.can_authenticate) + if (mKey.can_authenticate) usage_steam << "Auth "; usageVarLabel->setText(usage); @@ -265,13 +276,13 @@ void KeyPairDetailTab::slotRefreshKeyInfo() { QString actualUsage; QTextStream actual_usage_steam(&actualUsage); - if(GpgME::GpgContext::checkIfKeyCanCert(mKey)) + if (GpgME::GpgContext::checkIfKeyCanCert(mKey)) actual_usage_steam << "Cert "; - if(GpgME::GpgContext::checkIfKeyCanEncr(mKey)) + if (GpgME::GpgContext::checkIfKeyCanEncr(mKey)) actual_usage_steam << "Encr "; - if(GpgME::GpgContext::checkIfKeyCanSign(mKey)) + if (GpgME::GpgContext::checkIfKeyCanSign(mKey)) actual_usage_steam << "Sign "; - if(GpgME::GpgContext::checkIfKeyCanAuth(mKey)) + if (GpgME::GpgContext::checkIfKeyCanAuth(mKey)) actual_usage_steam << "Auth "; actualUsageVarLabel->setText(actualUsage); @@ -301,7 +312,7 @@ void KeyPairDetailTab::slotRefreshKeyInfo() { void KeyPairDetailTab::createKeyServerOperaMenu() { keyServerOperaMenu = new QMenu(this); - auto *uploadKeyPair = new QAction(tr("Upload Key Pair"), this); + auto *uploadKeyPair = new QAction(tr("Upload Key Pair to Key Server"), this); connect(uploadKeyPair, SIGNAL(triggered()), this, SLOT(slotUploadKeyToServer())); auto *updateKeyPair = new QAction(tr("Update Key Pair"), this); connect(updateKeyPair, SIGNAL(triggered()), this, SLOT(slotUpdateKeyToServer())); @@ -325,3 +336,21 @@ void KeyPairDetailTab::slotUpdateKeyToServer() { dialog->slotImportKey(keys); } +void KeyPairDetailTab::slotGenRevokeCert() { + auto mOutputFileName = QFileDialog::getSaveFileName(this, tr("Generate revocation certificate"), + QString(), + QStringLiteral("%1 (*.rev)").arg( + tr("Revocation Certificates"))); + + auto process = mCtx->generateRevokeCert(mKey, mOutputFileName); + + auto *dialog = new WaitingDialog("Generating", this); + + while (process->state() == QProcess::Running) { + QApplication::processEvents(); + } + + dialog->close(); + +} + diff --git a/src/ui/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/keypair_details/KeyPairSubkeyTab.cpp index 70c7e4b8..74b52284 100644 --- a/src/ui/keypair_details/KeyPairSubkeyTab.cpp +++ b/src/ui/keypair_details/KeyPairSubkeyTab.cpp @@ -47,6 +47,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW auto subkeyListLayout = new QGridLayout(); subkeyListLayout->addWidget(subkeyList, 0, 0); subkeyListLayout->addLayout(uidButtonsLayout, 1, 0); + subkeyListLayout->setContentsMargins(0, 10, 0, 0); auto *subkeyDetailLayout = new QGridLayout(); @@ -79,6 +80,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW subkeyDetailLayout->addWidget(fingerPrintVarLabel, 7, 1); listBox->setLayout(subkeyListLayout); + listBox->setContentsMargins(0, 5, 0, 0); detailBox->setLayout(subkeyDetailLayout); baseLayout->addWidget(listBox); @@ -89,6 +91,8 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshSubkeyList())); connect(subkeyList, SIGNAL(itemSelectionChanged()), this, SLOT(slotRefreshSubkeyDetail())); + baseLayout->setContentsMargins(0, 0, 0, 0); + setLayout(baseLayout); setAttribute(Qt::WA_DeleteOnClose, true); diff --git a/src/ui/keypair_details/KeyPairUIDTab.cpp b/src/ui/keypair_details/KeyPairUIDTab.cpp index 51f188bd..2954aadb 100644 --- a/src/ui/keypair_details/KeyPairUIDTab.cpp +++ b/src/ui/keypair_details/KeyPairUIDTab.cpp @@ -52,21 +52,24 @@ KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget gridLayout->addWidget(uidList, 0, 0); gridLayout->addLayout(uidButtonsLayout, 1, 0); + gridLayout->setContentsMargins(0, 10, 0, 0); auto uidGroupBox = new QGroupBox(); uidGroupBox->setLayout(gridLayout); - uidGroupBox->setTitle("UIDs"); + uidGroupBox->setTitle(tr("UIDs")); auto signGridLayout = new QGridLayout(); signGridLayout->addWidget(sigList, 0, 0); + signGridLayout->setContentsMargins(0, 10, 0, 0); auto signGroupBox = new QGroupBox(); signGroupBox->setLayout(signGridLayout); - signGroupBox->setTitle("Signature of Selected UID"); + signGroupBox->setTitle(tr("Signature of Selected UID")); auto vboxLayout = new QVBoxLayout(); vboxLayout->addWidget(uidGroupBox); vboxLayout->addWidget(signGroupBox); + vboxLayout->setContentsMargins(0, 0, 0, 0); connect(addUIDButton, SIGNAL(clicked(bool)), this, SLOT(slotAddUID())); connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshUIDList())); diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 36d8f363..4bcee080 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -23,6 +23,7 @@ */ #include "MainWindow.h" +#include "ui/SendMailDialog.h" void MainWindow::slotEncrypt() { @@ -58,12 +59,12 @@ void MainWindow::slotEncrypt() { auto thread = QThread::create([&]() { error = mCtx->encrypt(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &result); }); - + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); thread->start(); - WaitingDialog *dialog = new WaitingDialog(this); + auto *dialog = new WaitingDialog(tr("Encrypting"), this); - while(thread->isRunning()) { + while (thread->isRunning()) { QApplication::processEvents(); } @@ -83,6 +84,19 @@ void MainWindow::slotEncrypt() { else infoBoard->slotRefresh(reportText, INFO_ERROR_WARN); + if (resultAnalyse->getStatus() >= 0) { + infoBoard->resetOptionActionsMenu(); + infoBoard->addOptionalAction("Send Mail", [this]() { + if(settings.value("sendMail/enable", false).toBool()) + new SendMailDialog(edit->curTextPage()->toPlainText(), this); + else { + QMessageBox::warning(nullptr, + tr("Function Disabled"), + tr("Please go to the settings interface to enable and configure this function.")); + } + }); + } + delete resultAnalyse; } else if (edit->slotCurPageFileTreeView() != nullptr) { this->slotFileEncrypt(); @@ -118,7 +132,19 @@ void MainWindow::slotSign() { gpgme_sign_result_t result = nullptr; - auto error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result); + gpgme_error_t error; + auto thread = QThread::create([&]() { + error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result); + }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); + thread->start(); + + auto *dialog = new WaitingDialog(tr("Signing"), this); + while (thread->isRunning()) { + QApplication::processEvents(); + } + dialog->close(); + infoBoard->associateTextEdit(edit->curTextPage()); edit->slotFillTextEditWithText(QString::fromUtf8(*tmp)); @@ -154,10 +180,11 @@ void MainWindow::slotDecrypt() { // try decrypt, if fail do nothing, especially don't replace text error = mCtx->decrypt(text, decrypted, &result); }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); thread->start(); - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { + auto *dialog = new WaitingDialog(tr("Decrypting"), this); + while (thread->isRunning()) { QApplication::processEvents(); } @@ -213,13 +240,13 @@ void MainWindow::slotVerify() { auto thread = QThread::create([&]() { error = mCtx->verify(&text, nullptr, &result); }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); thread->start(); - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { + auto *dialog = new WaitingDialog(tr("Verifying"), this); + while (thread->isRunning()) { QApplication::processEvents(); } - dialog->close(); auto resultAnalyse = new VerifyResultAnalyse(mCtx, error, result); @@ -268,27 +295,27 @@ void MainWindow::slotEncryptSign() { if (!key_can_sign && !key_can_encr) { QMessageBox::critical(nullptr, - tr("Invalid KeyPair"), - tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>") - + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid); + tr("Invalid KeyPair"), + tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>") + + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid); return; } - if(key_can_sign) can_sign = true; - if(key_can_encr) can_encr = true; + if (key_can_sign) can_sign = true; + if (key_can_encr) can_encr = true; } - if(!can_encr) { - QMessageBox::critical(nullptr, - tr("Incomplete Operation"), - tr("None of the selected key pairs can provide the encryption function.")); - return; + if (!can_encr) { + QMessageBox::critical(nullptr, + tr("Incomplete Operation"), + tr("None of the selected key pairs can provide the encryption function.")); + return; } - if(!can_sign) { - QMessageBox::warning(nullptr, - tr("Incomplete Operation"), - tr("None of the selected key pairs can provide the signature function.")); + if (!can_sign) { + QMessageBox::warning(nullptr, + tr("Incomplete Operation"), + tr("None of the selected key pairs can provide the signature function.")); } auto *tmp = new QByteArray(); @@ -300,18 +327,19 @@ void MainWindow::slotEncryptSign() { gpgme_error_t error; auto thread = QThread::create([&]() { error = mCtx->encryptSign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &encr_result, - &sign_result); + &sign_result); }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); thread->start(); - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { + auto *dialog = new WaitingDialog(tr("Encrypting and Signing"), this); + while (thread->isRunning()) { QApplication::processEvents(); } dialog->close(); - if(gpgme_err_code(error) == GPG_ERR_NO_ERROR) { + if (gpgme_err_code(error) == GPG_ERR_NO_ERROR) { auto *tmp2 = new QString(*tmp); edit->slotFillTextEditWithText(*tmp2); } @@ -330,6 +358,19 @@ void MainWindow::slotEncryptSign() { else infoBoard->slotRefresh(reportText, INFO_ERROR_WARN); + if (status >= 0) { + infoBoard->resetOptionActionsMenu(); + infoBoard->addOptionalAction("Send Mail", [this]() { + if(settings.value("sendMail/enable", false).toBool()) + new SendMailDialog(edit->curTextPage()->toPlainText(), this); + else { + QMessageBox::warning(nullptr, + tr("Function Disabled"), + tr("Please go to the settings interface to enable and configure this function.")); + } + }); + } + delete resultAnalyseEncr; delete resultAnalyseSign; } else if (edit->slotCurPageFileTreeView() != nullptr) { @@ -354,10 +395,11 @@ void MainWindow::slotDecryptVerify() { auto thread = QThread::create([&]() { error = mCtx->decryptVerify(text, decrypted, &d_result, &v_result); }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); thread->start(); - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { + auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this); + while (thread->isRunning()) { QApplication::processEvents(); } @@ -495,22 +537,27 @@ void MainWindow::slotFileEncrypt() { } } - try { - gpgme_encrypt_result_t result; + gpgme_encrypt_result_t result; - gpgme_error_t error; - auto thread = QThread::create([&]() { + gpgme_error_t error; + bool if_error = false; + auto thread = QThread::create([&]() { + try { error = GpgFileOpera::encryptFile(mCtx, keys, path, &result); - }); - thread->start(); - - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { - QApplication::processEvents(); + } catch (const std::runtime_error &e) { + if_error = true; } + }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); + thread->start(); - dialog->close(); + auto *dialog = new WaitingDialog(tr("Encrypting"), this); + while (thread->isRunning()) { + QApplication::processEvents(); + } + dialog->close(); + if (!if_error) { auto resultAnalyse = new EncryptResultAnalyse(error, result); auto &reportText = resultAnalyse->getResultReport(); infoBoard->associateTabWidget(edit->tabWidget); @@ -526,11 +573,10 @@ void MainWindow::slotFileEncrypt() { delete resultAnalyse; fileTreeView->update(); - - } catch (const std::runtime_error &e) { + } else { QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation.")); + return; } - } void MainWindow::slotFileDecrypt() { @@ -572,21 +618,28 @@ void MainWindow::slotFileDecrypt() { return; } - try { - gpgme_decrypt_result_t result; - gpgme_error_t error; - auto thread = QThread::create([&]() { - error = GpgFileOpera::decryptFile(mCtx, path, &result); - }); - thread->start(); + gpgme_decrypt_result_t result; + gpgme_error_t error; + bool if_error = false; - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { - QApplication::processEvents(); + auto thread = QThread::create([&]() { + try { + error = GpgFileOpera::decryptFile(mCtx, path, &result); + } catch (const std::runtime_error &e) { + if_error = true; } + }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); + thread->start(); - dialog->close(); + auto *dialog = new WaitingDialog("Decrypting", this); + while (thread->isRunning()) { + QApplication::processEvents(); + } + + dialog->close(); + if (!if_error) { auto resultAnalyse = new DecryptResultAnalyse(mCtx, error, result); auto &reportText = resultAnalyse->getResultReport(); infoBoard->associateTabWidget(edit->tabWidget); @@ -602,7 +655,7 @@ void MainWindow::slotFileDecrypt() { delete resultAnalyse; fileTreeView->update(); - } catch (const std::runtime_error &e) { + } else { QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation.")); return; } @@ -661,20 +714,28 @@ void MainWindow::slotFileSign() { } } - try { - gpgme_sign_result_t result; - gpgme_error_t error; - auto thread = QThread::create([&]() { - error = GpgFileOpera::signFile(mCtx, keys, path, &result); - }); - thread->start(); + gpgme_sign_result_t result; + gpgme_error_t error; + bool if_error = false; - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { - QApplication::processEvents(); + auto thread = QThread::create([&]() { + try { + error = GpgFileOpera::signFile(mCtx, keys, path, &result); + } catch (const std::runtime_error &e) { + if_error = true; } + }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); + thread->start(); - dialog->close(); + auto *dialog = new WaitingDialog(tr("Signing"), this); + while (thread->isRunning()) { + QApplication::processEvents(); + } + + dialog->close(); + + if (!if_error) { auto resultAnalyse = new SignResultAnalyse(error, result); auto &reportText = resultAnalyse->getResultReport(); @@ -692,8 +753,9 @@ void MainWindow::slotFileSign() { fileTreeView->update(); - } catch (const std::runtime_error &e) { + } else { QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation.")); + return; } fileTreeView->update(); @@ -709,11 +771,10 @@ void MainWindow::slotFileVerify() { QString signFilePath, dataFilePath; - if(fileInfo.suffix() == "gpg") { + if (fileInfo.suffix() == "gpg") { dataFilePath = path; signFilePath = path; - } - else if (fileInfo.suffix() == "sig") { + } else if (fileInfo.suffix() == "sig") { int pos = path.lastIndexOf(QChar('.')); dataFilePath = path.left(pos); signFilePath = path; @@ -743,21 +804,22 @@ void MainWindow::slotFileVerify() { gpgme_error_t error; bool if_error = false; auto thread = QThread::create([&]() { - try{ + try { error = GpgFileOpera::verifyFile(mCtx, dataFilePath, &result); } catch (const std::runtime_error &e) { if_error = true; } }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); thread->start(); - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { + auto *dialog = new WaitingDialog(tr("Verifying"), this); + while (thread->isRunning()) { QApplication::processEvents(); } dialog->close(); - if(!if_error) { + if (!if_error) { auto resultAnalyse = new VerifyResultAnalyse(mCtx, error, result); auto &reportText = resultAnalyse->getResultReport(); infoBoard->associateTabWidget(edit->tabWidget); @@ -832,45 +894,52 @@ void MainWindow::slotFileEncryptSign() { if (!key_can_sign && !key_can_encr) { QMessageBox::critical(nullptr, - tr("Invalid KeyPair"), - tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>") - + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid); + tr("Invalid KeyPair"), + tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>") + + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid); return; } - if(key_can_sign) can_sign = true; - if(key_can_encr) can_encr = true; + if (key_can_sign) can_sign = true; + if (key_can_encr) can_encr = true; } - if(!can_encr) { - QMessageBox::critical(nullptr, - tr("Incomplete Operation"), - tr("None of the selected key pairs can provide the encryption function.")); - return; + if (!can_encr) { + QMessageBox::critical(nullptr, + tr("Incomplete Operation"), + tr("None of the selected key pairs can provide the encryption function.")); + return; } - if(!can_sign) { - QMessageBox::warning(nullptr, - tr("Incomplete Operation"), - tr("None of the selected key pairs can provide the signature function.")); + if (!can_sign) { + QMessageBox::warning(nullptr, + tr("Incomplete Operation"), + tr("None of the selected key pairs can provide the signature function.")); } - try { + gpgme_encrypt_result_t encr_result = nullptr; + gpgme_sign_result_t sign_result = nullptr; - gpgme_encrypt_result_t encr_result = nullptr; - gpgme_sign_result_t sign_result = nullptr; + gpgme_error_t error; + bool if_error = false; - gpgme_error_t error; - auto thread = QThread::create([&]() { + auto thread = QThread::create([&]() { + try { error = GpgFileOpera::encryptSignFile(mCtx, keys, path, &encr_result, &sign_result); - }); - thread->start(); - - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { - QApplication::processEvents(); + } catch (const std::runtime_error &e) { + if_error = true; } - dialog->close(); + }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); + thread->start(); + + WaitingDialog *dialog = new WaitingDialog(tr("Encrypting and Signing"), this); + while (thread->isRunning()) { + QApplication::processEvents(); + } + dialog->close(); + + if (!if_error) { auto resultAnalyseEncr = new EncryptResultAnalyse(error, encr_result); auto resultAnalyseSign = new SignResultAnalyse(error, sign_result); @@ -891,8 +960,9 @@ void MainWindow::slotFileEncryptSign() { fileTreeView->update(); - } catch (std::runtime_error &e) { + } else { QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation.")); + return; } } @@ -924,22 +994,30 @@ void MainWindow::slotFileDecryptVerify() { outFileName = path + ".out"; } - try { + gpgme_decrypt_result_t d_result = nullptr; + gpgme_verify_result_t v_result = nullptr; - gpgme_decrypt_result_t d_result = nullptr; - gpgme_verify_result_t v_result = nullptr; + gpgme_error_t error; + bool if_error = false; - gpgme_error_t error; - auto thread = QThread::create([&]() { + auto thread = QThread::create([&]() { + try { error = GpgFileOpera::decryptVerifyFile(mCtx, path, &d_result, &v_result); - }); - thread->start(); - - WaitingDialog *dialog = new WaitingDialog(this); - while(thread->isRunning()) { - QApplication::processEvents(); + } catch (const std::runtime_error &e) { + if_error = true; } - dialog->close(); + }); + connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater())); + thread->start(); + + + auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this); + while (thread->isRunning()) { + QApplication::processEvents(); + } + dialog->close(); + + if (!if_error) { infoBoard->associateFileTreeView(edit->curFilePage()); auto resultAnalyseDecrypt = new DecryptResultAnalyse(mCtx, error, d_result); @@ -964,7 +1042,7 @@ void MainWindow::slotFileDecryptVerify() { delete resultAnalyseVerify; fileTreeView->update(); - } catch (std::runtime_error &e) { + } else { QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation.")); return; } @@ -997,3 +1075,21 @@ void MainWindow::slotFileVerifyCustom() { void MainWindow::slotOpenFile(QString &path) { edit->slotOpenFile(path); } + +void MainWindow::slotVersionUpgrade(const QString ¤tVersion, const QString &latestVersion) { + if(currentVersion < latestVersion) { + QMessageBox::warning(this, + tr("Outdated Version"), + tr("This version(%1) is out of date, please update the latest version in time. ").arg( + currentVersion) + + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg( + latestVersion)); + } else if(currentVersion > latestVersion) { + QMessageBox::warning(this, + tr("Unreleased Version"), + tr("This version(%1) has not been officially released and is not recommended for use in a production environment. <br/>").arg( + currentVersion) + + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg( + latestVersion)); + } +} diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index 189ead53..7065e41c 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -25,7 +25,11 @@ #include "MainWindow.h" void MainWindow::slotAbout() { - new AboutDialog(this); + new AboutDialog(0, this); +} + +void MainWindow::slotCheckUpdate() { + new AboutDialog(2, this); } void MainWindow::slotSetStatusBarText(const QString &text) { @@ -141,13 +145,6 @@ void MainWindow::slotOpenSettingsDialog() { importButton->setToolButtonStyle(buttonStyle); fileEncButton->setToolButtonStyle(buttonStyle); - // Mime-settings - if (settings.value("mime/parseMime").toBool()) { - createAttachmentDock(); - } else if (attachmentDockCreated) { - closeAttachmentDock(); - } - // restart mainwindow if necessary if (getRestartNeeded()) { if (edit->maybeSaveAnyTab()) { diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 233a0927..21f6e3b7 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -209,18 +209,27 @@ void MainWindow::createActions() { importKeyFromEditAct->setToolTip(tr("Import New Key From Editor")); connect(importKeyFromEditAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromEdit())); - openKeyManagementAct = new QAction(tr("Manage &keys"), this); + openKeyManagementAct = new QAction(tr("Manage &Keys"), this); openKeyManagementAct->setIcon(QIcon(":keymgmt.png")); openKeyManagementAct->setToolTip(tr("Open Keymanagement")); connect(openKeyManagementAct, SIGNAL(triggered()), this, SLOT(slotOpenKeyManagement())); - /* About Menu + /* + * About Menu */ aboutAct = new QAction(tr("&About"), this); aboutAct->setIcon(QIcon(":help.png")); aboutAct->setToolTip(tr("Show the application's About box")); connect(aboutAct, SIGNAL(triggered()), this, SLOT(slotAbout())); + /* + * Check Update Menu + */ + checkUpdateAct = new QAction(tr("&Check for Updates"), this); + checkUpdateAct->setIcon(QIcon(":help.png")); + checkUpdateAct->setToolTip(tr("Check for updates")); + connect(checkUpdateAct, SIGNAL(triggered()), this, SLOT(slotCheckUpdate())); + startWizardAct = new QAction(tr("Open &Wizard"), this); startWizardAct->setToolTip(tr("Open the wizard")); connect(startWizardAct, SIGNAL(triggered()), this, SLOT(slotStartWizard())); @@ -231,8 +240,8 @@ void MainWindow::createActions() { appendSelectedKeysAct->setToolTip(tr("Append The Selected Keys To Text in Editor")); connect(appendSelectedKeysAct, SIGNAL(triggered()), this, SLOT(slotAppendSelectedKeys())); - copyMailAddressToClipboardAct = new QAction(tr("Copy EMail-address"), this); - copyMailAddressToClipboardAct->setToolTip(tr("Copy selected EMailaddress to clipboard")); + copyMailAddressToClipboardAct = new QAction(tr("Copy Email"), this); + copyMailAddressToClipboardAct->setToolTip(tr("Copy selected Email to clipboard")); connect(copyMailAddressToClipboardAct, SIGNAL(triggered()), this, SLOT(slotCopyMailAddressToClipboard())); // TODO: find central place for shared actions, to avoid code-duplication with keymgmt.cpp @@ -247,6 +256,7 @@ void MainWindow::createActions() { uploadKeyToServerAct = new QAction(tr("Upload Public Key(s) To Server"), this); uploadKeyToServerAct->setToolTip(tr("Upload The Selected Public Keys To Server")); connect(uploadKeyToServerAct, SIGNAL(triggered()), this, SLOT(uploadKeyToServer())); + /* Key-Shortcuts for Tab-Switchung-Action */ switchTabUpAct = new QAction(this); @@ -339,6 +349,7 @@ void MainWindow::createMenus() { helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(startWizardAct); helpMenu->addSeparator(); + helpMenu->addAction(checkUpdateAct); helpMenu->addAction(aboutAct); } @@ -436,26 +447,4 @@ void MainWindow::createDockWindows() { infoBoardDock->setWidget(infoBoard); infoBoardDock->widget()->layout()->setContentsMargins(0, 0, 0, 0); viewMenu->addAction(infoBoardDock->toggleViewAction()); - - /* Attachments-Dockwindow - */ - if (settings.value("mime/parseMime").toBool()) { - createAttachmentDock(); - } -} - -void MainWindow::createAttachmentDock() { - if (attachmentDockCreated) { - return; - } - mAttachments = new Attachments(); - attachmentDock = new QDockWidget(tr("Attached files:"), this); - attachmentDock->setObjectName("AttachmentDock"); - attachmentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); - addDockWidget(Qt::LeftDockWidgetArea, attachmentDock); - attachmentDock->setWidget(mAttachments); - // hide till attachment is decrypted - viewMenu->addAction(attachmentDock->toggleViewAction()); - attachmentDock->hide(); - attachmentDockCreated = true; } diff --git a/src/ui/widgets/Attachments.cpp b/src/ui/widgets/Attachments.cpp deleted file mode 100644 index 8f741f66..00000000 --- a/src/ui/widgets/Attachments.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/** - * This file is part of GPGFrontend. - * - * GPGFrontend is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Foobar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Foobar. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from gpg4usb-team. - * Their source code version also complies with GNU General Public License. - * - * The source code version of this software was modified and released - * by Saturneric<[email protected]> starting on May 12, 2021. - * - */ - -/* TODO: - * - check content encoding (base64 / quoted-printable) and apply appropriate opperation (maybe already in mime.cpp) - * - check memory usage, use less copy operations / more references - * - possibility to clear attachment-view , e.g. with decryption or encrypting a new message - * - save all: like in thunderbird, one folder, all files go there - */ - -/* - * - save, delete (clear) all - * - each line save & clear button - * - attached files to view-menu - * - also an open button, whichs should save file to tmp-folder, and open with correct app (via QDesktopServices) - */ - - -#include "ui/widgets/Attachments.h" - -Attachments::Attachments(QWidget *parent) - : QWidget(parent) { - table = new AttachmentTableModel(this); - - tableView = new QTableView; - tableView->setModel(table); - tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - // only one entry should be selected at time - tableView->setSelectionMode(QAbstractItemView::SingleSelection); - tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); - tableView->setFocusPolicy(Qt::NoFocus); - tableView->setAlternatingRowColors(true); - tableView->verticalHeader()->hide(); - tableView->setShowGrid(false); - tableView->setColumnWidth(0, 300); - tableView->horizontalHeader()->setStretchLastSection(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(tableView); - layout->setContentsMargins(0, 0, 0, 0); - setLayout(layout); - createActions(); - -} - -void Attachments::contextMenuEvent(QContextMenuEvent *event) { - QMenu menu(this); - menu.addAction(saveFileAct); - // enable open with only if allowed by user - if (settings.value("mime/openAttachment").toBool()) - menu.addAction(openFileAct); - - menu.exec(event->globalPos()); -} - -void Attachments::createActions() { - saveFileAct = new QAction(tr("Save File"), this); - saveFileAct->setToolTip(tr("Save this file")); - saveFileAct->setIcon(QIcon(":filesave.png")); - connect(saveFileAct, SIGNAL(triggered()), this, SLOT(slotSaveFile())); - - openFileAct = new QAction(tr("Open File"), this); - openFileAct->setToolTip(tr("Open this file")); - openFileAct->setIcon(QIcon(":fileopen.png")); - connect(openFileAct, SIGNAL(triggered()), this, SLOT(slotOpenFile())); - -} - -void Attachments::slotSaveFile() { - - QModelIndexList indexes = tableView->selectionModel()->selection().indexes(); - - if (indexes.empty()) { - return; - } - - // only singe-selection possible now: TODO: foreach - MimePart mp = table->getMimePart(indexes.at(0).row()); - QString filename = mp.header.getParam("Content-Type", "name"); - // TODO: find out why filename is quoted - filename.chop(1); - filename.remove(0, 1); - // TODO: check if really base64 - saveByteArrayToFile(QByteArray::fromBase64(mp.body), filename); - -} - -void Attachments::saveByteArrayToFile(QByteArray outBuffer, QString filename) { - - //QString path=""; - QString path = std::move(filename); - QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"), path); - - if (outfileName.isEmpty()) return; - - QFile outfile(outfileName); - if (!outfile.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("File"), - tr("Cannot write file %1:\n%2.") - .arg(outfileName) - .arg(outfile.errorString())); - return; - } - - QDataStream out(&outfile); - out.writeRawData(outBuffer.data(), outBuffer.length()); - outfile.close(); -} - -/** - * WIP: TODO: - * - create attachments dir if not existing - * - ask for cleanup of dir on exit - * - remove code-duplication with saveByteArrayToFile - */ -void Attachments::slotOpenFile() { - - // TODO: make attachmentdir constant or configurable - QString attachmentDir = qApp->applicationDirPath() + "/attachments/"; - //QDir p = QDir(qApp->applicationDirPath() + "/attachments/"); - if (!QDir(attachmentDir).exists()) { - QDir().mkpath(attachmentDir); - } - - QModelIndexList indexes = tableView->selectionModel()->selection().indexes(); - MimePart mp = table->getMimePart(indexes.at(0).row()); - -// qDebug() << "mime: " << mp.header.getValue("Content-Type"); - - QString filename = mp.header.getParam("Content-Type", "name"); - // TODO: find out why filename is quoted -// qDebug() << "file: " << filename; - filename.chop(1); - filename.remove(0, 1); - filename.prepend(attachmentDir); - - // qDebug() << "file: " << filename; - QByteArray outBuffer = QByteArray::fromBase64(mp.body); - - - QFile outfile(filename); - if (!outfile.open(QFile::WriteOnly)) { - QMessageBox::warning(this, tr("File"), - tr("Cannot write file %1:\n%2.") - .arg(filename) - .arg(outfile.errorString())); - return; - } - - QDataStream out(&outfile); - out.writeRawData(outBuffer.data(), outBuffer.length()); - outfile.close(); - QDesktopServices::openUrl(QUrl("file://" + filename, QUrl::TolerantMode)); -} - -void Attachments::addMimePart(MimePart *mp) { - table->add(*mp); -} - diff --git a/src/ui/widgets/EditorPage.cpp b/src/ui/widgets/EditorPage.cpp index 8a51b721..05d5cbea 100644 --- a/src/ui/widgets/EditorPage.cpp +++ b/src/ui/widgets/EditorPage.cpp @@ -42,6 +42,9 @@ EditorPage::EditorPage(QString filePath, QWidget *parent) : QWidget(parent), setAttribute(Qt::WA_DeleteOnClose); textPage->setFocus(); + // Front in same width + this->setFont({"Courier"}); + connect(textPage, SIGNAL(textChanged()), this, SLOT(formatGpgHeader())); } diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp index bab6cf68..b9602d58 100644 --- a/src/ui/widgets/FilePage.cpp +++ b/src/ui/widgets/FilePage.cpp @@ -46,15 +46,33 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) { createPopupMenu(); - upLevelButton = new QPushButton("Up"); + + upLevelButton = new QPushButton(); connect(upLevelButton, SIGNAL(clicked(bool)), this, SLOT(slotUpLevel())); + QString buttonStyle = "QPushButton{border:none;background-color:rgba(255, 255, 255,100);}"; + + + auto upPixmap = QPixmap(":up.png"); + upPixmap = upPixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QIcon upButtonIcon(upPixmap); + upLevelButton->setIcon(upButtonIcon); + upLevelButton->setIconSize(upPixmap.rect().size()); + upLevelButton->setStyleSheet(buttonStyle); + refreshButton = new QPushButton("Refresh"); connect(refreshButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath())); - goPathButton = new QPushButton("Go"); + goPathButton = new QPushButton(); connect(goPathButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath())); + auto updatePixmap = QPixmap(":refresh.png"); + updatePixmap = updatePixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QIcon updateButtonIcon(updatePixmap); + goPathButton->setIcon(updateButtonIcon); + goPathButton->setIconSize(updatePixmap.rect().size()); + goPathButton->setStyleSheet(buttonStyle); + pathEdit = new QLineEdit(); pathEdit->setText(dirModel->rootPath()); @@ -62,7 +80,7 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) { menuLayout->addWidget(upLevelButton); menuLayout->setStretchFactor(upLevelButton, 1); menuLayout->addWidget(pathEdit); - menuLayout->setStretchFactor(pathEdit, 8); + menuLayout->setStretchFactor(pathEdit, 10); menuLayout->addWidget(goPathButton); menuLayout->setStretchFactor(goPathButton, 1); // menuLayout->addWidget(refreshButton); @@ -87,17 +105,22 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) { } void FilePage::fileTreeViewItemClicked(const QModelIndex &index) { - mPath = dirModel->fileInfo(index).absoluteFilePath(); - qDebug() << "mPath" << mPath; + selectedPath = dirModel->fileInfo(index).absoluteFilePath(); + qDebug() << "selectedPath" << selectedPath; } void FilePage::slotUpLevel() { QModelIndex currentRoot = dirTreeView->rootIndex(); - mPath = dirModel->fileInfo(currentRoot.parent()).absoluteFilePath(); - auto fileInfo = QFileInfo(mPath); + + mPath = dirModel->fileInfo(currentRoot).absoluteFilePath(); + QDir dir(mPath); + dir.makeAbsolute(); + dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral("..")))); + mPath = dir.absolutePath(); + auto fileInfo = QFileInfo(dir.absolutePath()); if(fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) { - dirTreeView->setRootIndex(currentRoot.parent()); pathEdit->setText(mPath); + slotGoPath(); } qDebug() << "Current Root mPath" << mPath; emit pathChanged(mPath); @@ -106,8 +129,9 @@ void FilePage::slotUpLevel() { void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex &index) { mPath = dirModel->fileInfo(index).absoluteFilePath(); auto fileInfo = QFileInfo(mPath); + auto targetModelIndex = dirTreeView->model()->index(index.row(), 0, index.parent()); if(fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) { - dirTreeView->setRootIndex(index); + dirTreeView->setRootIndex(targetModelIndex); pathEdit->setText(mPath); } qDebug() << "Index mPath" << mPath; @@ -115,7 +139,7 @@ void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex &index) { } QString FilePage::getSelected() const { - return mPath; + return selectedPath; } void FilePage::slotGoPath() { @@ -159,10 +183,10 @@ void FilePage::createPopupMenu() { void FilePage::onCustomContextMenu(const QPoint &point) { QModelIndex index = dirTreeView->indexAt(point); - mPath = dirModel->fileInfo(index).absoluteFilePath(); - qDebug() << "Right Click" << mPath; + selectedPath = dirModel->fileInfo(index).absoluteFilePath(); + qDebug() << "Right Click" << selectedPath; if (index.isValid()) { - QFileInfo info(mPath); + QFileInfo info(selectedPath); encryptItemAct->setEnabled(info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig")); decryptItemAct->setEnabled(info.isFile() && info.suffix() == "gpg"); signItemAct->setEnabled(info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig")); @@ -234,3 +258,10 @@ void FilePage::slotVerifyItem() { if(mainWindow != nullptr) mainWindow->slotFileVerify(); } + +void FilePage::keyPressEvent(QKeyEvent *event) { + qDebug() << "Key Press" << event->key(); + if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { + slotGoPath(); + } +} diff --git a/src/ui/widgets/InfoBoardWidget.cpp b/src/ui/widgets/InfoBoardWidget.cpp index 33517a8e..f26917a4 100644 --- a/src/ui/widgets/InfoBoardWidget.cpp +++ b/src/ui/widgets/InfoBoardWidget.cpp @@ -25,7 +25,9 @@ #include "ui/widgets/InfoBoardWidget.h" InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList) : - QWidget(parent), mCtx(ctx), mKeyList(keyList) { + QWidget(parent), mCtx(ctx), mKeyList(keyList), appPath(qApp->applicationDirPath()), + settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", + QSettings::IniFormat) { infoBoard = new QTextEdit(this); infoBoard->setReadOnly(true); @@ -42,7 +44,7 @@ InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyLis detailMenu->addAction(importFromKeyserverAct); importFromKeyserverAct->setVisible(false); - QWidget *actionButtonMenu = new QWidget(); + auto *actionButtonMenu = new QWidget(); actionButtonMenu->setContentsMargins(0, 0, 0, 0); actionButtonMenu->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); actionButtonMenu->setFixedHeight(36); @@ -52,7 +54,7 @@ InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyLis actionButtonLayout->setSpacing(0); actionButtonMenu->setLayout(actionButtonLayout); - auto label = new QLabel("Optional Actions Menu"); + auto label = new QLabel(tr("Optional Actions Menu")); label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); label->setContentsMargins(0, 0, 0, 0); @@ -107,7 +109,8 @@ void InfoBoardWidget::setInfoBoard(const QString &text, InfoBoardStatus verifyLa QPalette status = infoBoard->palette(); status.setColor(QPalette::Text, color); infoBoard->setPalette(status); - infoBoard->setFont(QFont("Times", 10)); + auto infoBoardFontSize = settings.value("informationBoard/fontSize", 10).toInt(); + infoBoard->setFont(QFont("Times", infoBoardFontSize)); } void InfoBoardWidget::slotRefresh(const QString &text, InfoBoardStatus status) { @@ -135,13 +138,16 @@ void InfoBoardWidget::associateTabWidget(QTabWidget *tab) { disconnect(mTextPage, SIGNAL(textChanged()), this, SLOT(slotReset())); // if (mFileTreeView != nullptr) // disconnect(mFileTreeView, &FilePage::pathChanged, this, &InfoBoardWidget::slotReset); - if (mTabWidget != nullptr) + if (mTabWidget != nullptr) { disconnect(mTabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset())); + connect(mTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(slotReset())); + } mTextPage = nullptr; mFileTreeView = nullptr; mTabWidget = tab; connect(tab, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset())); + connect(tab, SIGNAL(tabCloseRequested(int)), this, SLOT(slotReset())); } void InfoBoardWidget::addOptionalAction(const QString &name, const std::function<void()> &action) { diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index b044020a..3929868e 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -297,6 +297,11 @@ void KeyList::contextMenuEvent(QContextMenuEvent *event) } +void KeyList::addSeparator() +{ + popupMenu->addSeparator(); +} + void KeyList::addMenuAction(QAction *act) { popupMenu->addAction(act); diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp index 26cc3834..eab0f799 100644 --- a/src/ui/widgets/TextEdit.cpp +++ b/src/ui/widgets/TextEdit.cpp @@ -37,9 +37,6 @@ TextEdit::TextEdit(QWidget *parent) : QWidget(parent) { layout->setSpacing(0); setLayout(layout); - // Front in same width - this->setFont({"Courier"}); - connect(tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(removeTab(int))); connect(this, &TextEdit::insertTargetTextPage, this, @@ -73,7 +70,7 @@ void TextEdit::slotNewHelpTab(const QString &title, const QString &path) const { void TextEdit::slotNewFileTab() const { auto *page = new FilePage(qobject_cast<QWidget *>(parent())); - tabWidget->addTab(page, "[File Browser]"); + tabWidget->addTab(page, "[Browser]"); tabWidget->setCurrentIndex(tabWidget->count() - 1); connect(page, SIGNAL(pathChanged(const QString &)), this, SLOT(slotFilePagePathChanged(const QString &))); @@ -132,6 +129,7 @@ void TextEdit::slotInsertTargetTextPage(const QString &pagePtr, auto *taregtTextPage = qobject_cast<EditorPage *>(it.value()); if (taregtTextPage != nullptr) { taregtTextPage->getTextPage()->insertPlainText(text); + taregtTextPage->getTextPage()->document()->setModified(false); } } } @@ -164,6 +162,7 @@ void TextEdit::slotReadTargetTextPageDone(const QString &pagePtr) { tabWidget->setTabText(index, strippedName(taregtTextPage->getFilePath())); } + taregtTextPage->getTextPage()->document()->setModified(false); connect(taregtTextPage->getTextPage()->document(), SIGNAL(modificationChanged(bool)), this, SLOT(slotShowModified())); @@ -638,13 +637,13 @@ void TextEdit::slotFilePagePathChanged(const QString &path) { int index = tabWidget->currentIndex(); QString mPath; QFileInfo fileInfo(path); - QString tPath = fileInfo.path(); + QString tPath = fileInfo.absoluteFilePath(); if (path.size() > 18) { mPath = tPath.mid(tPath.size() - 18, 18).prepend("..."); } else { mPath = tPath; } - mPath.prepend("[File Browser] "); + mPath.prepend("[Browser] "); mPath.append("/"); tabWidget->setTabText(index, mPath); } |